diff options
328 files changed, 1874 insertions, 23324 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index f53c519447..f4bf49b704 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -67,7 +67,7 @@ windows_msys2_task: CIRRUS_SHELL: powershell MSYS: winsymlinks:nativestrict MSYSTEM: MINGW64 - MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2021-01-05/msys2-base-x86_64-20210105.sfx.exe + MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2021-04-19/msys2-base-x86_64-20210419.sfx.exe MSYS2_FINGERPRINT: 0 MSYS2_PACKAGES: " diffutils git grep make pkg-config sed @@ -130,7 +130,7 @@ windows_msys2_task: 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 -Syuu --overwrite=*" Write-Output "Core install time taken: $((Get-Date).Subtract($start_time))" $start_time = Get-Date diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml index 33e4046e23..4ef76d1f54 100644 --- a/.gitlab-ci.d/containers.yml +++ b/.gitlab-ci.d/containers.yml @@ -1,4 +1,4 @@ -.container_job_template: &container_job_definition +.container_job_template: image: docker:stable stage: containers services: @@ -22,230 +22,230 @@ - docker logout amd64-alpine-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: alpine amd64-centos7-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: centos7 amd64-centos8-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: centos8 amd64-debian10-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: debian10 amd64-debian11-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: debian11 alpha-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-alpha-cross amd64-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-amd64-cross amd64-debian-user-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-all-test-cross amd64-debian-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-amd64 arm64-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-arm64-cross arm64-test-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian11-container'] variables: NAME: debian-arm64-test-cross armel-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-armel-cross armhf-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-armhf-cross hppa-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-hppa-cross m68k-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-m68k-cross mips64-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-mips64-cross mips64el-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-mips64el-cross mips-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-mips-cross mipsel-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-mipsel-cross powerpc-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-powerpc-cross ppc64-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-ppc64-cross ppc64el-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-ppc64el-cross riscv64-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-riscv64-cross s390x-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-s390x-cross sh4-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-sh4-cross sparc64-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-sparc64-cross tricore-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template stage: containers-layer2 needs: ['amd64-debian10-container'] variables: NAME: debian-tricore-cross xtensa-debian-cross-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: debian-xtensa-cross cris-fedora-cross-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: fedora-cris-cross amd64-fedora-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: fedora i386-fedora-cross-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: fedora-i386-cross win32-fedora-cross-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: fedora-win32-cross win64-fedora-cross-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: fedora-win64-cross amd64-ubuntu1804-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: ubuntu1804 amd64-ubuntu2004-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: ubuntu2004 amd64-ubuntu-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: ubuntu amd64-opensuse-leap-container: - <<: *container_job_definition + extends: .container_job_template variables: NAME: opensuse-leap diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dcb6317aac..24f300aace 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,7 @@ include: - local: '/.gitlab-ci.d/containers.yml' - local: '/.gitlab-ci.d/crossbuilds.yml' -.native_build_job_template: &native_build_job_definition +.native_build_job_template: stage: build image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest before_script: @@ -41,7 +41,7 @@ include: make -j"$JOBS" $MAKE_CHECK_ARGS ; fi -.native_test_job_template: &native_test_job_definition +.native_test_job_template: stage: test image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest script: @@ -83,13 +83,13 @@ include: - du -chs ${CI_PROJECT_DIR}/avocado-cache build-system-alpine: - <<: *native_build_job_definition + extends: .native_build_job_template needs: - job: amd64-alpine-container variables: IMAGE: alpine TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu - moxie-softmmu microblazeel-softmmu mips64el-softmmu + microblazeel-softmmu mips64el-softmmu MAKE_CHECK_ARGS: check-build CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog artifacts: @@ -99,7 +99,7 @@ build-system-alpine: - build check-system-alpine: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-alpine artifacts: true @@ -108,7 +108,7 @@ check-system-alpine: MAKE_CHECK_ARGS: check acceptance-system-alpine: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-alpine artifacts: true @@ -118,14 +118,14 @@ acceptance-system-alpine: <<: *acceptance_definition build-system-ubuntu: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-ubuntu2004-container variables: IMAGE: ubuntu2004 CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu - moxie-softmmu microblazeel-softmmu mips64el-softmmu + microblazeel-softmmu mips64el-softmmu MAKE_CHECK_ARGS: check-build artifacts: expire_in: 2 days @@ -133,7 +133,7 @@ build-system-ubuntu: - build check-system-ubuntu: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-ubuntu artifacts: true @@ -142,7 +142,7 @@ check-system-ubuntu: MAKE_CHECK_ARGS: check acceptance-system-ubuntu: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-ubuntu artifacts: true @@ -152,7 +152,7 @@ acceptance-system-ubuntu: <<: *acceptance_definition build-system-debian: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-container variables: @@ -167,7 +167,7 @@ build-system-debian: - build check-system-debian: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-debian artifacts: true @@ -176,7 +176,7 @@ check-system-debian: MAKE_CHECK_ARGS: check acceptance-system-debian: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-debian artifacts: true @@ -186,7 +186,7 @@ acceptance-system-debian: <<: *acceptance_definition build-system-fedora: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-fedora-container variables: @@ -202,7 +202,7 @@ build-system-fedora: - build check-system-fedora: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-fedora artifacts: true @@ -211,7 +211,7 @@ check-system-fedora: MAKE_CHECK_ARGS: check acceptance-system-fedora: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-fedora artifacts: true @@ -221,7 +221,7 @@ acceptance-system-fedora: <<: *acceptance_definition build-system-centos: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos8-container variables: @@ -237,7 +237,7 @@ build-system-centos: - build check-system-centos: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-centos artifacts: true @@ -246,7 +246,7 @@ check-system-centos: MAKE_CHECK_ARGS: check acceptance-system-centos: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-centos artifacts: true @@ -256,7 +256,7 @@ acceptance-system-centos: <<: *acceptance_definition build-system-opensuse: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-opensuse-leap-container variables: @@ -270,7 +270,7 @@ build-system-opensuse: - build check-system-opensuse: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-opensuse artifacts: true @@ -279,7 +279,7 @@ check-system-opensuse: MAKE_CHECK_ARGS: check acceptance-system-opensuse: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-system-opensuse artifacts: true @@ -290,7 +290,7 @@ acceptance-system-opensuse: build-disabled: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-fedora-container variables: @@ -342,7 +342,6 @@ build-disabled: --disable-replication --disable-sdl --disable-seccomp - --disable-sheepdog --disable-slirp --disable-smartcard --disable-snappy @@ -377,7 +376,7 @@ build-disabled: # Also use a different coroutine implementation (which is only really of # interest to KVM users, i.e. with TCG disabled) build-tcg-disabled: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos8-container variables: @@ -400,7 +399,7 @@ build-tcg-disabled: 260 261 262 263 264 270 272 273 277 279 build-user: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: @@ -409,7 +408,7 @@ build-user: MAKE_CHECK_ARGS: check-tcg build-user-static: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: @@ -419,7 +418,7 @@ build-user-static: # Only build the softmmu targets we have check-tcg tests for build-some-softmmu: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: @@ -432,7 +431,7 @@ build-some-softmmu: # 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 + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: @@ -442,7 +441,7 @@ build-user-plugins: timeout: 1h 30m build-user-centos7: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos7-container variables: @@ -451,7 +450,7 @@ build-user-centos7: MAKE_CHECK_ARGS: check-tcg build-some-softmmu-plugins: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: @@ -461,7 +460,7 @@ build-some-softmmu-plugins: MAKE_CHECK_ARGS: check-tcg clang-system: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-fedora-container variables: @@ -473,7 +472,7 @@ clang-system: MAKE_CHECK_ARGS: check-qtest check-tcg clang-user: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: @@ -495,7 +494,7 @@ clang-user: # Split in three sets of build/check/acceptance to limit the execution time of each # job build-cfi-aarch64: - <<: *native_build_job_definition + extends: .native_build_job_template needs: - job: amd64-fedora-container variables: @@ -513,7 +512,7 @@ build-cfi-aarch64: - build check-cfi-aarch64: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-cfi-aarch64 artifacts: true @@ -522,7 +521,7 @@ check-cfi-aarch64: MAKE_CHECK_ARGS: check acceptance-cfi-aarch64: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-cfi-aarch64 artifacts: true @@ -532,7 +531,7 @@ acceptance-cfi-aarch64: <<: *acceptance_definition build-cfi-ppc64-s390x: - <<: *native_build_job_definition + extends: .native_build_job_template needs: - job: amd64-fedora-container variables: @@ -550,7 +549,7 @@ build-cfi-ppc64-s390x: - build check-cfi-ppc64-s390x: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-cfi-ppc64-s390x artifacts: true @@ -559,7 +558,7 @@ check-cfi-ppc64-s390x: MAKE_CHECK_ARGS: check acceptance-cfi-ppc64-s390x: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-cfi-ppc64-s390x artifacts: true @@ -569,7 +568,7 @@ acceptance-cfi-ppc64-s390x: <<: *acceptance_definition build-cfi-x86_64: - <<: *native_build_job_definition + extends: .native_build_job_template needs: - job: amd64-fedora-container variables: @@ -587,7 +586,7 @@ build-cfi-x86_64: - build check-cfi-x86_64: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-cfi-x86_64 artifacts: true @@ -596,7 +595,7 @@ check-cfi-x86_64: MAKE_CHECK_ARGS: check acceptance-cfi-x86_64: - <<: *native_test_job_definition + extends: .native_test_job_template needs: - job: build-cfi-x86_64 artifacts: true @@ -606,7 +605,7 @@ acceptance-cfi-x86_64: <<: *acceptance_definition tsan-build: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-ubuntu2004-container variables: @@ -618,14 +617,14 @@ tsan-build: # These targets are on the way out build-deprecated: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: IMAGE: debian-all-test-cross CONFIGURE_ARGS: --disable-tools MAKE_CHECK_ARGS: build-tcg - TARGETS: ppc64abi32-linux-user lm32-softmmu unicore32-softmmu + TARGETS: ppc64abi32-linux-user artifacts: expire_in: 2 days paths: @@ -634,7 +633,7 @@ build-deprecated: # 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 + extends: .native_test_job_template needs: - job: build-deprecated artifacts: true @@ -645,7 +644,7 @@ check-deprecated: # gprof/gcov are GCC features gprof-gcov: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-ubuntu2004-container variables: @@ -658,7 +657,7 @@ gprof-gcov: - ${CI_PROJECT_DIR}/scripts/ci/coverage-summary.sh build-oss-fuzz: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-fedora-container variables: @@ -678,13 +677,13 @@ build-oss-fuzz: - cd build-oss-fuzz && make check-qtest-i386 check-unit build-tci: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-user-cross-container variables: IMAGE: debian-all-test-cross script: - - TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64" + - TARGETS="aarch64 alpha arm hppa m68k microblaze ppc64 s390x x86_64" - mkdir build - cd build - ../configure --enable-tcg-interpreter @@ -703,7 +702,7 @@ build-tci: # Alternate coroutines implementations are only really of interest to KVM users # However we can't test against KVM on Gitlab-CI so we can only run unit tests build-coroutine-sigaltstack: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-ubuntu2004-container variables: @@ -717,7 +716,7 @@ build-coroutine-sigaltstack: # These jobs test old gcrypt and nettle from RHEL7 # which had some API differences. crypto-old-nettle: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos7-container variables: @@ -727,7 +726,7 @@ crypto-old-nettle: MAKE_CHECK_ARGS: check crypto-old-gcrypt: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos7-container variables: @@ -737,7 +736,7 @@ crypto-old-gcrypt: MAKE_CHECK_ARGS: check crypto-only-gnutls: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos7-container variables: @@ -749,7 +748,7 @@ crypto-only-gnutls: # Check our reduced build configurations build-without-default-devices: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-centos8-container variables: @@ -757,7 +756,7 @@ build-without-default-devices: CONFIGURE_ARGS: --without-default-devices --disable-user build-without-default-features: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-container variables: @@ -807,7 +806,7 @@ build-libvhost-user: # No targets are built here, just tools, docs, and unit tests. This # also feeds into the eventual documentation deployment steps later build-tools-and-docs-debian: - <<: *native_build_job_definition + extends: .native_build_job_template needs: job: amd64-debian-container variables: diff --git a/MAINTAINERS b/MAINTAINERS index c733c53bf7..78561a223f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -207,19 +207,6 @@ F: disas/hppa.c F: hw/net/*i82596* F: include/hw/net/lasi_82596.h -LM32 TCG CPUs -R: Michael Walle <michael@walle.cc> -S: Orphan -F: target/lm32/ -F: disas/lm32.c -F: hw/lm32/ -F: hw/*/lm32_* -F: hw/*/milkymist-* -F: include/hw/display/milkymist_tmu2.h -F: include/hw/char/lm32_juart.h -F: include/hw/lm32/ -F: tests/tcg/lm32/ - M68K TCG CPUs M: Laurent Vivier <laurent@vivier.eu> S: Maintained @@ -258,14 +245,6 @@ MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* -Moxie TCG CPUs -M: Anthony Green <green@moxielogic.com> -S: Maintained -F: target/moxie/ -F: disas/moxie.c -F: hw/moxie/ -F: default-configs/*/moxie-softmmu.mak - NiosII TCG CPUs M: Chris Wulff <crwulff@gmail.com> M: Marek Vasut <marex@denx.de> @@ -338,13 +317,6 @@ F: hw/sparc64/ F: include/hw/sparc/sparc64.h F: disas/sparc.c -UniCore32 TCG CPUs -M: Guan Xuetao <gxt@mprc.pku.edu.cn> -S: Maintained -F: target/unicore32/ -F: hw/unicore32/ -F: include/hw/unicore32/ - X86 TCG CPUs M: Paolo Bonzini <pbonzini@redhat.com> M: Richard Henderson <richard.henderson@linaro.org> @@ -1088,18 +1060,6 @@ F: default-configs/*/hppa-softmmu.mak F: hw/hppa/ F: pc-bios/hppa-firmware.img -LM32 Machines -------------- -EVR32 and uclinux BSP -R: Michael Walle <michael@walle.cc> -S: Orphan -F: hw/lm32/lm32_boards.c - -milkymist -R: Michael Walle <michael@walle.cc> -S: Orphan -F: hw/lm32/milkymist.c - M68K Machines ------------- an5206 @@ -1549,14 +1509,6 @@ F: hw/s390x/s390-pci* F: include/hw/s390x/s390-pci* L: qemu-s390x@nongnu.org -UniCore32 Machines ------------------- -PKUnity-3 SoC initramfs-with-busybox -M: Guan Xuetao <gxt@mprc.pku.edu.cn> -S: Maintained -F: hw/*/puv3* -F: hw/unicore32/ - X86 Machines ------------ PC @@ -2072,6 +2024,12 @@ S: Maintained F: hw/net/tulip.c F: hw/net/tulip.h +pca954x +M: Patrick Venture <venture@google.com> +S: Maintained +F: hw/i2c/i2c_mux_pca954x.c +F: include/hw/i2c/i2c_mux_pca954x.h + Generic Loader M: Alistair Francis <alistair@alistair23.me> S: Maintained @@ -3088,12 +3046,6 @@ L: qemu-block@nongnu.org S: Supported F: block/rbd.c -Sheepdog -M: Liu Yuan <namei.unix@gmail.com> -L: qemu-block@nongnu.org -S: Odd Fixes -F: block/sheepdog.c - VHDX M: Jeff Cody <codyprime@gmail.com> L: qemu-block@nongnu.org @@ -213,7 +213,7 @@ qemu-%.tar.bz2: distclean: clean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : - rm -f config-host.mak config-host.h* + rm -f config-host.mak config-host.h* config-poison.h rm -f tests/tcg/config-*.mak rm -f config-all-disas.mak config.status rm -f roms/seabios/config.mak roms/vgabios/config.mak @@ -400,7 +400,6 @@ BlockDriverState *bdrv_new(void) for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) { QLIST_INIT(&bs->op_blockers[i]); } - notifier_with_return_list_init(&bs->before_write_notifiers); qemu_co_mutex_init(&bs->reqs_lock); qemu_mutex_init(&bs->dirty_bitmap_mutex); bs->refcnt = 1; diff --git a/block/backup.c b/block/backup.c index 6cf2f974aa..bd3614ce70 100644 --- a/block/backup.c +++ b/block/backup.c @@ -331,7 +331,7 @@ static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed) } } -static void backup_cancel(Job *job) +static void backup_cancel(Job *job, bool force) { BackupBlockJob *s = container_of(job, BackupBlockJob, common.job); diff --git a/block/copy-on-read.c b/block/copy-on-read.c index 9cad9e1b8c..c428682272 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -29,7 +29,6 @@ typedef struct BDRVStateCOR { - bool active; BlockDriverState *bottom_bs; bool chain_frozen; } BDRVStateCOR; @@ -89,7 +88,6 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, */ bdrv_ref(bottom_bs); } - state->active = true; state->bottom_bs = bottom_bs; /* @@ -112,17 +110,6 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared) { - BDRVStateCOR *s = bs->opaque; - - if (!s->active) { - /* - * While the filter is being removed - */ - *nperm = 0; - *nshared = BLK_PERM_ALL; - return; - } - *nperm = perm & PERM_PASSTHROUGH; *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED; @@ -280,32 +267,14 @@ static BlockDriver bdrv_copy_on_read = { void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs) { - BdrvChild *child; - BlockDriverState *bs; BDRVStateCOR *s = cor_filter_bs->opaque; - child = bdrv_filter_child(cor_filter_bs); - if (!child) { - return; - } - bs = child->bs; - - /* Retain the BDS until we complete the graph change. */ - bdrv_ref(bs); - /* Hold a guest back from writing while permissions are being reset. */ - bdrv_drained_begin(bs); - /* Drop permissions before the graph change. */ - s->active = false; /* unfreeze, as otherwise bdrv_replace_node() will fail */ if (s->chain_frozen) { s->chain_frozen = false; bdrv_unfreeze_backing_chain(cor_filter_bs, s->bottom_bs); } - bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort); - bdrv_replace_node(cor_filter_bs, bs, &error_abort); - - bdrv_drained_end(bs); - bdrv_unref(bs); + bdrv_drop_filter(cor_filter_bs, &error_abort); bdrv_unref(cor_filter_bs); } diff --git a/block/io.c b/block/io.c index 35b6c56efc..1e826ba9e8 100644 --- a/block/io.c +++ b/block/io.c @@ -30,6 +30,7 @@ #include "block/blockjob_int.h" #include "block/block_int.h" #include "block/coroutines.h" +#include "block/write-threshold.h" #include "qemu/cutils.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -2008,8 +2009,8 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes, } else { assert(child->perm & BLK_PERM_WRITE); } - return notifier_with_return_list_notify(&bs->before_write_notifiers, - req); + bdrv_write_threshold_check_write(bs, offset, bytes); + return 0; case BDRV_TRACKED_TRUNCATE: assert(child->perm & BLK_PERM_RESIZE); return 0; @@ -3164,12 +3165,6 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov) return true; } -void bdrv_add_before_write_notifier(BlockDriverState *bs, - NotifierWithReturn *notifier) -{ - notifier_with_return_list_add(&bs->before_write_notifiers, notifier); -} - void bdrv_io_plug(BlockDriverState *bs) { BdrvChild *child; diff --git a/block/meson.build b/block/meson.build index d21990ec95..e687c54dbc 100644 --- a/block/meson.build +++ b/block/meson.build @@ -64,7 +64,6 @@ block_ss.add(when: 'CONFIG_POSIX', if_true: [files('file-posix.c'), coref, iokit block_ss.add(when: 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')) diff --git a/block/mirror.c b/block/mirror.c index 840b8e8c15..019f6deaa5 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1178,12 +1178,14 @@ static bool mirror_drained_poll(BlockJob *job) return !!s->in_flight; } -static void mirror_cancel(Job *job) +static void mirror_cancel(Job *job, bool force) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); BlockDriverState *target = blk_bs(s->target); - bdrv_cancel_in_flight(target); + if (force || !job_is_ready(job)) { + bdrv_cancel_in_flight(target); + } } static const BlockJobDriver mirror_job_driver = { diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c index ebf1033f31..3e6670c963 100644 --- a/block/monitor/block-hmp-cmds.c +++ b/block/monitor/block-hmp-cmds.c @@ -557,8 +557,10 @@ void hmp_eject(Monitor *mon, const QDict *qdict) void hmp_qemu_io(Monitor *mon, const QDict *qdict) { - BlockBackend *blk; + BlockBackend *blk = NULL; + BlockDriverState *bs = NULL; BlockBackend *local_blk = NULL; + AioContext *ctx = NULL; bool qdev = qdict_get_try_bool(qdict, "qdev", false); const char *device = qdict_get_str(qdict, "device"); const char *command = qdict_get_str(qdict, "command"); @@ -573,20 +575,24 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict) } else { blk = blk_by_name(device); if (!blk) { - BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); - if (bs) { - blk = local_blk = blk_new(bdrv_get_aio_context(bs), - 0, BLK_PERM_ALL); - ret = blk_insert_bs(blk, bs, &err); - if (ret < 0) { - goto fail; - } - } else { + bs = bdrv_lookup_bs(NULL, device, &err); + if (!bs) { goto fail; } } } + ctx = blk ? blk_get_aio_context(blk) : bdrv_get_aio_context(bs); + aio_context_acquire(ctx); + + if (bs) { + blk = local_blk = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL); + ret = blk_insert_bs(blk, bs, &err); + if (ret < 0) { + goto fail; + } + } + /* * Notably absent: Proper permission management. This is sad, but it seems * almost impossible to achieve without changing the semantics and thereby @@ -616,6 +622,11 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict) fail: blk_unref(local_blk); + + if (ctx) { + aio_context_release(ctx); + } + hmp_handle_error(mon, err); } diff --git a/block/rbd.c b/block/rbd.c index f098a89c7b..26f64cce7c 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -113,21 +113,31 @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx, const char *keypairs, const char *secretid, Error **errp); +static char *qemu_rbd_strchr(char *src, char delim) +{ + char *p; + + for (p = src; *p; ++p) { + if (*p == delim) { + return p; + } + if (*p == '\\' && p[1] != '\0') { + ++p; + } + } + + return NULL; +} + + static char *qemu_rbd_next_tok(char *src, char delim, char **p) { char *end; *p = NULL; - for (end = src; *end; ++end) { - if (*end == delim) { - break; - } - if (*end == '\\' && end[1] != '\0') { - end++; - } - } - if (*end == delim) { + end = qemu_rbd_strchr(src, delim); + if (end) { *p = end + 1; *end = '\0'; } @@ -171,7 +181,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options, qemu_rbd_unescape(found_str); qdict_put_str(options, "pool", found_str); - if (strchr(p, '@')) { + if (qemu_rbd_strchr(p, '@')) { image_name = qemu_rbd_next_tok(p, '@', &p); found_str = qemu_rbd_next_tok(p, ':', &p); @@ -181,7 +191,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options, image_name = qemu_rbd_next_tok(p, ':', &p); } /* Check for namespace in the image_name */ - if (strchr(image_name, '/')) { + if (qemu_rbd_strchr(image_name, '/')) { found_str = qemu_rbd_next_tok(image_name, '/', &image_name); qemu_rbd_unescape(found_str); qdict_put_str(options, "namespace", found_str); diff --git a/block/sheepdog.c b/block/sheepdog.c deleted file mode 100644 index a45c73826d..0000000000 --- a/block/sheepdog.c +++ /dev/null @@ -1,3356 +0,0 @@ -/* - * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "qapi/error.h" -#include "qapi/qapi-visit-sockets.h" -#include "qapi/qapi-visit-block-core.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qobject-input-visitor.h" -#include "qapi/qobject-output-visitor.h" -#include "qemu/uri.h" -#include "qemu/error-report.h" -#include "qemu/main-loop.h" -#include "qemu/module.h" -#include "qemu/option.h" -#include "qemu/sockets.h" -#include "block/block_int.h" -#include "block/qdict.h" -#include "sysemu/block-backend.h" -#include "qemu/bitops.h" -#include "qemu/cutils.h" -#include "trace.h" - -#define SD_PROTO_VER 0x01 - -#define SD_DEFAULT_ADDR "localhost" -#define SD_DEFAULT_PORT 7000 - -#define SD_OP_CREATE_AND_WRITE_OBJ 0x01 -#define SD_OP_READ_OBJ 0x02 -#define SD_OP_WRITE_OBJ 0x03 -/* 0x04 is used internally by Sheepdog */ - -#define SD_OP_NEW_VDI 0x11 -#define SD_OP_LOCK_VDI 0x12 -#define SD_OP_RELEASE_VDI 0x13 -#define SD_OP_GET_VDI_INFO 0x14 -#define SD_OP_READ_VDIS 0x15 -#define SD_OP_FLUSH_VDI 0x16 -#define SD_OP_DEL_VDI 0x17 -#define SD_OP_GET_CLUSTER_DEFAULT 0x18 - -#define SD_FLAG_CMD_WRITE 0x01 -#define SD_FLAG_CMD_COW 0x02 -#define SD_FLAG_CMD_CACHE 0x04 /* Writeback mode for cache */ -#define SD_FLAG_CMD_DIRECT 0x08 /* Don't use cache */ - -#define SD_RES_SUCCESS 0x00 /* Success */ -#define SD_RES_UNKNOWN 0x01 /* Unknown error */ -#define SD_RES_NO_OBJ 0x02 /* No object found */ -#define SD_RES_EIO 0x03 /* I/O error */ -#define SD_RES_VDI_EXIST 0x04 /* Vdi exists already */ -#define SD_RES_INVALID_PARMS 0x05 /* Invalid parameters */ -#define SD_RES_SYSTEM_ERROR 0x06 /* System error */ -#define SD_RES_VDI_LOCKED 0x07 /* Vdi is locked */ -#define SD_RES_NO_VDI 0x08 /* No vdi found */ -#define SD_RES_NO_BASE_VDI 0x09 /* No base vdi found */ -#define SD_RES_VDI_READ 0x0A /* Cannot read requested vdi */ -#define SD_RES_VDI_WRITE 0x0B /* Cannot write requested vdi */ -#define SD_RES_BASE_VDI_READ 0x0C /* Cannot read base vdi */ -#define SD_RES_BASE_VDI_WRITE 0x0D /* Cannot write base vdi */ -#define SD_RES_NO_TAG 0x0E /* Requested tag is not found */ -#define SD_RES_STARTUP 0x0F /* Sheepdog is on starting up */ -#define SD_RES_VDI_NOT_LOCKED 0x10 /* Vdi is not locked */ -#define SD_RES_SHUTDOWN 0x11 /* Sheepdog is shutting down */ -#define SD_RES_NO_MEM 0x12 /* Cannot allocate memory */ -#define SD_RES_FULL_VDI 0x13 /* we already have the maximum vdis */ -#define SD_RES_VER_MISMATCH 0x14 /* Protocol version mismatch */ -#define SD_RES_NO_SPACE 0x15 /* Server has no room for new objects */ -#define SD_RES_WAIT_FOR_FORMAT 0x16 /* Waiting for a format operation */ -#define SD_RES_WAIT_FOR_JOIN 0x17 /* Waiting for other nodes joining */ -#define SD_RES_JOIN_FAILED 0x18 /* Target node had failed to join sheepdog */ -#define SD_RES_HALT 0x19 /* Sheepdog is stopped serving IO request */ -#define SD_RES_READONLY 0x1A /* Object is read-only */ - -/* - * Object ID rules - * - * 0 - 19 (20 bits): data object space - * 20 - 31 (12 bits): reserved data object space - * 32 - 55 (24 bits): vdi object space - * 56 - 59 ( 4 bits): reserved vdi object space - * 60 - 63 ( 4 bits): object type identifier space - */ - -#define VDI_SPACE_SHIFT 32 -#define VDI_BIT (UINT64_C(1) << 63) -#define VMSTATE_BIT (UINT64_C(1) << 62) -#define MAX_DATA_OBJS (UINT64_C(1) << 20) -#define MAX_CHILDREN 1024 -#define SD_MAX_VDI_LEN 256 -#define SD_MAX_VDI_TAG_LEN 256 -#define SD_NR_VDIS (1U << 24) -#define SD_DATA_OBJ_SIZE (UINT64_C(1) << 22) -#define SD_MAX_VDI_SIZE (SD_DATA_OBJ_SIZE * MAX_DATA_OBJS) -#define SD_DEFAULT_BLOCK_SIZE_SHIFT 22 -/* - * For erasure coding, we use at most SD_EC_MAX_STRIP for data strips and - * (SD_EC_MAX_STRIP - 1) for parity strips - * - * SD_MAX_COPIES is sum of number of data strips and parity strips. - */ -#define SD_EC_MAX_STRIP 16 -#define SD_MAX_COPIES (SD_EC_MAX_STRIP * 2 - 1) - -#define SD_INODE_SIZE (sizeof(SheepdogInode)) -#define CURRENT_VDI_ID 0 - -#define LOCK_TYPE_NORMAL 0 -#define LOCK_TYPE_SHARED 1 /* for iSCSI multipath */ - -typedef struct SheepdogReq { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint32_t opcode_specific[8]; -} SheepdogReq; - -typedef struct SheepdogRsp { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint32_t result; - uint32_t opcode_specific[7]; -} SheepdogRsp; - -typedef struct SheepdogObjReq { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint64_t oid; - uint64_t cow_oid; - uint8_t copies; - uint8_t copy_policy; - uint8_t reserved[6]; - uint64_t offset; -} SheepdogObjReq; - -typedef struct SheepdogObjRsp { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint32_t result; - uint8_t copies; - uint8_t copy_policy; - uint8_t reserved[2]; - uint32_t pad[6]; -} SheepdogObjRsp; - -typedef struct SheepdogVdiReq { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint64_t vdi_size; - uint32_t base_vdi_id; - uint8_t copies; - uint8_t copy_policy; - uint8_t store_policy; - uint8_t block_size_shift; - uint32_t snapid; - uint32_t type; - uint32_t pad[2]; -} SheepdogVdiReq; - -typedef struct SheepdogVdiRsp { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint32_t result; - uint32_t rsvd; - uint32_t vdi_id; - uint32_t pad[5]; -} SheepdogVdiRsp; - -typedef struct SheepdogClusterRsp { - uint8_t proto_ver; - uint8_t opcode; - uint16_t flags; - uint32_t epoch; - uint32_t id; - uint32_t data_length; - uint32_t result; - uint8_t nr_copies; - uint8_t copy_policy; - uint8_t block_size_shift; - uint8_t __pad1; - uint32_t __pad2[6]; -} SheepdogClusterRsp; - -typedef struct SheepdogInode { - char name[SD_MAX_VDI_LEN]; - char tag[SD_MAX_VDI_TAG_LEN]; - uint64_t ctime; - uint64_t snap_ctime; - uint64_t vm_clock_nsec; - uint64_t vdi_size; - uint64_t vm_state_size; - uint16_t copy_policy; - uint8_t nr_copies; - uint8_t block_size_shift; - uint32_t snap_id; - uint32_t vdi_id; - uint32_t parent_vdi_id; - uint32_t child_vdi_id[MAX_CHILDREN]; - uint32_t data_vdi_id[MAX_DATA_OBJS]; -} SheepdogInode; - -#define SD_INODE_HEADER_SIZE offsetof(SheepdogInode, data_vdi_id) - -/* - * 64 bit FNV-1a non-zero initial basis - */ -#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 - */ -static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval) -{ - unsigned char *bp = buf; - unsigned char *be = bp + len; - while (bp < be) { - hval ^= (uint64_t) *bp++; - hval += (hval << 1) + (hval << 4) + (hval << 5) + - (hval << 7) + (hval << 8) + (hval << 40); - } - return hval; -} - -static inline bool is_data_obj_writable(SheepdogInode *inode, unsigned int idx) -{ - return inode->vdi_id == inode->data_vdi_id[idx]; -} - -static inline bool is_data_obj(uint64_t oid) -{ - return !(VDI_BIT & oid); -} - -static inline uint64_t data_oid_to_idx(uint64_t oid) -{ - return oid & (MAX_DATA_OBJS - 1); -} - -static inline uint32_t oid_to_vid(uint64_t oid) -{ - return (oid & ~VDI_BIT) >> VDI_SPACE_SHIFT; -} - -static inline uint64_t vid_to_vdi_oid(uint32_t vid) -{ - return VDI_BIT | ((uint64_t)vid << VDI_SPACE_SHIFT); -} - -static inline uint64_t vid_to_vmstate_oid(uint32_t vid, uint32_t idx) -{ - return VMSTATE_BIT | ((uint64_t)vid << VDI_SPACE_SHIFT) | idx; -} - -static inline uint64_t vid_to_data_oid(uint32_t vid, uint32_t idx) -{ - return ((uint64_t)vid << VDI_SPACE_SHIFT) | idx; -} - -static inline bool is_snapshot(struct SheepdogInode *inode) -{ - return !!inode->snap_ctime; -} - -static inline size_t count_data_objs(const struct SheepdogInode *inode) -{ - return DIV_ROUND_UP(inode->vdi_size, - (1UL << inode->block_size_shift)); -} - -typedef struct SheepdogAIOCB SheepdogAIOCB; -typedef struct BDRVSheepdogState BDRVSheepdogState; - -typedef struct AIOReq { - SheepdogAIOCB *aiocb; - unsigned int iov_offset; - - uint64_t oid; - uint64_t base_oid; - uint64_t offset; - unsigned int data_len; - uint8_t flags; - uint32_t id; - bool create; - - QLIST_ENTRY(AIOReq) aio_siblings; -} AIOReq; - -enum AIOCBState { - AIOCB_WRITE_UDATA, - AIOCB_READ_UDATA, - AIOCB_FLUSH_CACHE, - AIOCB_DISCARD_OBJ, -}; - -#define AIOCBOverlapping(x, y) \ - (!(x->max_affect_data_idx < y->min_affect_data_idx \ - || y->max_affect_data_idx < x->min_affect_data_idx)) - -struct SheepdogAIOCB { - BDRVSheepdogState *s; - - QEMUIOVector *qiov; - - int64_t sector_num; - int nb_sectors; - - int ret; - enum AIOCBState aiocb_type; - - Coroutine *coroutine; - int nr_pending; - - uint32_t min_affect_data_idx; - uint32_t max_affect_data_idx; - - /* - * The difference between affect_data_idx and dirty_data_idx: - * affect_data_idx represents range of index of all request types. - * dirty_data_idx represents range of index updated by COW requests. - * dirty_data_idx is used for updating an inode object. - */ - uint32_t min_dirty_data_idx; - uint32_t max_dirty_data_idx; - - QLIST_ENTRY(SheepdogAIOCB) aiocb_siblings; -}; - -struct BDRVSheepdogState { - BlockDriverState *bs; - AioContext *aio_context; - - SheepdogInode inode; - - char name[SD_MAX_VDI_LEN]; - bool is_snapshot; - uint32_t cache_flags; - bool discard_supported; - - SocketAddress *addr; - int fd; - - CoMutex lock; - Coroutine *co_send; - Coroutine *co_recv; - - uint32_t aioreq_seq_num; - - /* Every aio request must be linked to either of these queues. */ - QLIST_HEAD(, AIOReq) inflight_aio_head; - QLIST_HEAD(, AIOReq) failed_aio_head; - - CoMutex queue_lock; - CoQueue overlapping_queue; - QLIST_HEAD(, SheepdogAIOCB) inflight_aiocb_head; -}; - -typedef struct BDRVSheepdogReopenState { - int fd; - int cache_flags; -} BDRVSheepdogReopenState; - -static const char *sd_strerror(int err) -{ - int i; - - static const struct { - int err; - const char *desc; - } errors[] = { - {SD_RES_SUCCESS, "Success"}, - {SD_RES_UNKNOWN, "Unknown error"}, - {SD_RES_NO_OBJ, "No object found"}, - {SD_RES_EIO, "I/O error"}, - {SD_RES_VDI_EXIST, "VDI exists already"}, - {SD_RES_INVALID_PARMS, "Invalid parameters"}, - {SD_RES_SYSTEM_ERROR, "System error"}, - {SD_RES_VDI_LOCKED, "VDI is already locked"}, - {SD_RES_NO_VDI, "No vdi found"}, - {SD_RES_NO_BASE_VDI, "No base VDI found"}, - {SD_RES_VDI_READ, "Failed read the requested VDI"}, - {SD_RES_VDI_WRITE, "Failed to write the requested VDI"}, - {SD_RES_BASE_VDI_READ, "Failed to read the base VDI"}, - {SD_RES_BASE_VDI_WRITE, "Failed to write the base VDI"}, - {SD_RES_NO_TAG, "Failed to find the requested tag"}, - {SD_RES_STARTUP, "The system is still booting"}, - {SD_RES_VDI_NOT_LOCKED, "VDI isn't locked"}, - {SD_RES_SHUTDOWN, "The system is shutting down"}, - {SD_RES_NO_MEM, "Out of memory on the server"}, - {SD_RES_FULL_VDI, "We already have the maximum vdis"}, - {SD_RES_VER_MISMATCH, "Protocol version mismatch"}, - {SD_RES_NO_SPACE, "Server has no space for new objects"}, - {SD_RES_WAIT_FOR_FORMAT, "Sheepdog is waiting for a format operation"}, - {SD_RES_WAIT_FOR_JOIN, "Sheepdog is waiting for other nodes joining"}, - {SD_RES_JOIN_FAILED, "Target node had failed to join sheepdog"}, - {SD_RES_HALT, "Sheepdog is stopped serving IO request"}, - {SD_RES_READONLY, "Object is read-only"}, - }; - - for (i = 0; i < ARRAY_SIZE(errors); ++i) { - if (errors[i].err == err) { - return errors[i].desc; - } - } - - return "Invalid error code"; -} - -/* - * Sheepdog I/O handling: - * - * 1. In sd_co_rw_vector, we send the I/O requests to the server and - * link the requests to the inflight_list in the - * BDRVSheepdogState. The function yields while waiting for - * receiving the response. - * - * 2. We receive the response in aio_read_response, the fd handler to - * the sheepdog connection. We switch back to sd_co_readv/sd_writev - * after all the requests belonging to the AIOCB are finished. If - * needed, sd_co_writev will send another requests for the vdi object. - */ - -static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb, - uint64_t oid, unsigned int data_len, - uint64_t offset, uint8_t flags, bool create, - uint64_t base_oid, unsigned int iov_offset) -{ - AIOReq *aio_req; - - aio_req = g_malloc(sizeof(*aio_req)); - aio_req->aiocb = acb; - aio_req->iov_offset = iov_offset; - aio_req->oid = oid; - aio_req->base_oid = base_oid; - aio_req->offset = offset; - aio_req->data_len = data_len; - aio_req->flags = flags; - aio_req->id = s->aioreq_seq_num++; - aio_req->create = create; - - acb->nr_pending++; - return aio_req; -} - -static void wait_for_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *acb) -{ - SheepdogAIOCB *cb; - -retry: - QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) { - if (AIOCBOverlapping(acb, cb)) { - qemu_co_queue_wait(&s->overlapping_queue, &s->queue_lock); - goto retry; - } - } -} - -static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s, - QEMUIOVector *qiov, int64_t sector_num, int nb_sectors, - int type) -{ - uint32_t object_size; - - object_size = (UINT32_C(1) << s->inode.block_size_shift); - - acb->s = s; - - acb->qiov = qiov; - - acb->sector_num = sector_num; - acb->nb_sectors = nb_sectors; - - acb->coroutine = qemu_coroutine_self(); - acb->ret = 0; - acb->nr_pending = 0; - - acb->min_affect_data_idx = acb->sector_num * BDRV_SECTOR_SIZE / object_size; - acb->max_affect_data_idx = (acb->sector_num * BDRV_SECTOR_SIZE + - acb->nb_sectors * BDRV_SECTOR_SIZE) / object_size; - - acb->min_dirty_data_idx = UINT32_MAX; - acb->max_dirty_data_idx = 0; - acb->aiocb_type = type; - - if (type == AIOCB_FLUSH_CACHE) { - return; - } - - qemu_co_mutex_lock(&s->queue_lock); - wait_for_overlapping_aiocb(s, acb); - QLIST_INSERT_HEAD(&s->inflight_aiocb_head, acb, aiocb_siblings); - qemu_co_mutex_unlock(&s->queue_lock); -} - -static SocketAddress *sd_server_config(QDict *options, Error **errp) -{ - QDict *server = NULL; - Visitor *iv = NULL; - SocketAddress *saddr = NULL; - - qdict_extract_subqdict(options, &server, "server."); - - iv = qobject_input_visitor_new_flat_confused(server, errp); - if (!iv) { - goto done; - } - - if (!visit_type_SocketAddress(iv, NULL, &saddr, errp)) { - goto done; - } - -done: - visit_free(iv); - qobject_unref(server); - return saddr; -} - -/* Return -EIO in case of error, file descriptor on success */ -static int connect_to_sdog(BDRVSheepdogState *s, Error **errp) -{ - int fd; - - fd = socket_connect(s->addr, errp); - - if (s->addr->type == SOCKET_ADDRESS_TYPE_INET && fd >= 0) { - int ret = socket_set_nodelay(fd); - if (ret < 0) { - warn_report("can't set TCP_NODELAY: %s", strerror(errno)); - } - } - - if (fd >= 0) { - qemu_set_nonblock(fd); - } else { - fd = -EIO; - } - - return fd; -} - -/* Return 0 on success and -errno in case of error */ -static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data, - unsigned int *wlen) -{ - int ret; - - ret = qemu_co_send(sockfd, hdr, sizeof(*hdr)); - if (ret != sizeof(*hdr)) { - error_report("failed to send a req, %s", strerror(errno)); - return -errno; - } - - ret = qemu_co_send(sockfd, data, *wlen); - if (ret != *wlen) { - error_report("failed to send a req, %s", strerror(errno)); - return -errno; - } - - return ret; -} - -typedef struct SheepdogReqCo { - int sockfd; - BlockDriverState *bs; - AioContext *aio_context; - SheepdogReq *hdr; - void *data; - unsigned int *wlen; - unsigned int *rlen; - int ret; - bool finished; - Coroutine *co; -} SheepdogReqCo; - -static void restart_co_req(void *opaque) -{ - SheepdogReqCo *srco = opaque; - - aio_co_wake(srco->co); -} - -static coroutine_fn void do_co_req(void *opaque) -{ - int ret; - SheepdogReqCo *srco = opaque; - int sockfd = srco->sockfd; - SheepdogReq *hdr = srco->hdr; - void *data = srco->data; - unsigned int *wlen = srco->wlen; - unsigned int *rlen = srco->rlen; - - srco->co = qemu_coroutine_self(); - aio_set_fd_handler(srco->aio_context, sockfd, false, - NULL, restart_co_req, NULL, srco); - - ret = send_co_req(sockfd, hdr, data, wlen); - if (ret < 0) { - goto out; - } - - aio_set_fd_handler(srco->aio_context, sockfd, false, - restart_co_req, NULL, NULL, srco); - - ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr)); - if (ret != sizeof(*hdr)) { - error_report("failed to get a rsp, %s", strerror(errno)); - ret = -errno; - goto out; - } - - if (*rlen > hdr->data_length) { - *rlen = hdr->data_length; - } - - if (*rlen) { - ret = qemu_co_recv(sockfd, data, *rlen); - if (ret != *rlen) { - error_report("failed to get the data, %s", strerror(errno)); - ret = -errno; - goto out; - } - } - ret = 0; -out: - /* there is at most one request for this sockfd, so it is safe to - * set each handler to NULL. */ - aio_set_fd_handler(srco->aio_context, sockfd, false, - NULL, NULL, NULL, NULL); - - srco->co = NULL; - srco->ret = ret; - /* Set srco->finished before reading bs->wakeup. */ - qatomic_mb_set(&srco->finished, true); - if (srco->bs) { - bdrv_wakeup(srco->bs); - } -} - -/* - * Send the request to the sheep in a synchronous manner. - * - * Return 0 on success, -errno in case of error. - */ -static int do_req(int sockfd, BlockDriverState *bs, SheepdogReq *hdr, - void *data, unsigned int *wlen, unsigned int *rlen) -{ - Coroutine *co; - SheepdogReqCo srco = { - .sockfd = sockfd, - .aio_context = bs ? bdrv_get_aio_context(bs) : qemu_get_aio_context(), - .bs = bs, - .hdr = hdr, - .data = data, - .wlen = wlen, - .rlen = rlen, - .ret = 0, - .finished = false, - }; - - if (qemu_in_coroutine()) { - do_co_req(&srco); - } else { - co = qemu_coroutine_create(do_co_req, &srco); - if (bs) { - bdrv_coroutine_enter(bs, co); - BDRV_POLL_WHILE(bs, !srco.finished); - } else { - qemu_coroutine_enter(co); - while (!srco.finished) { - aio_poll(qemu_get_aio_context(), true); - } - } - } - - return srco.ret; -} - -static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, - struct iovec *iov, int niov, - enum AIOCBState aiocb_type); -static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req); -static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag); -static int get_sheep_fd(BDRVSheepdogState *s, Error **errp); -static void co_write_request(void *opaque); - -static coroutine_fn void reconnect_to_sdog(void *opaque) -{ - BDRVSheepdogState *s = opaque; - AIOReq *aio_req, *next; - - aio_set_fd_handler(s->aio_context, s->fd, false, NULL, - NULL, NULL, NULL); - close(s->fd); - s->fd = -1; - - /* Wait for outstanding write requests to be completed. */ - while (s->co_send != NULL) { - co_write_request(opaque); - } - - /* Try to reconnect the sheepdog server every one second. */ - while (s->fd < 0) { - Error *local_err = NULL; - s->fd = get_sheep_fd(s, &local_err); - if (s->fd < 0) { - trace_sheepdog_reconnect_to_sdog(); - error_report_err(local_err); - qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, NANOSECONDS_PER_SECOND); - } - }; - - /* - * Now we have to resend all the request in the inflight queue. However, - * resend_aioreq() can yield and newly created requests can be added to the - * inflight queue before the coroutine is resumed. To avoid mixing them, we - * have to move all the inflight requests to the failed queue before - * resend_aioreq() is called. - */ - qemu_co_mutex_lock(&s->queue_lock); - QLIST_FOREACH_SAFE(aio_req, &s->inflight_aio_head, aio_siblings, next) { - QLIST_REMOVE(aio_req, aio_siblings); - QLIST_INSERT_HEAD(&s->failed_aio_head, aio_req, aio_siblings); - } - - /* Resend all the failed aio requests. */ - while (!QLIST_EMPTY(&s->failed_aio_head)) { - aio_req = QLIST_FIRST(&s->failed_aio_head); - QLIST_REMOVE(aio_req, aio_siblings); - qemu_co_mutex_unlock(&s->queue_lock); - resend_aioreq(s, aio_req); - qemu_co_mutex_lock(&s->queue_lock); - } - qemu_co_mutex_unlock(&s->queue_lock); -} - -/* - * Receive responses of the I/O requests. - * - * This function is registered as a fd handler, and called from the - * main loop when s->fd is ready for reading responses. - */ -static void coroutine_fn aio_read_response(void *opaque) -{ - SheepdogObjRsp rsp; - BDRVSheepdogState *s = opaque; - int fd = s->fd; - int ret; - AIOReq *aio_req = NULL; - SheepdogAIOCB *acb; - uint64_t idx; - - /* read a header */ - ret = qemu_co_recv(fd, &rsp, sizeof(rsp)); - if (ret != sizeof(rsp)) { - error_report("failed to get the header, %s", strerror(errno)); - goto err; - } - - /* find the right aio_req from the inflight aio list */ - QLIST_FOREACH(aio_req, &s->inflight_aio_head, aio_siblings) { - if (aio_req->id == rsp.id) { - break; - } - } - if (!aio_req) { - error_report("cannot find aio_req %x", rsp.id); - goto err; - } - - acb = aio_req->aiocb; - - switch (acb->aiocb_type) { - case AIOCB_WRITE_UDATA: - if (!is_data_obj(aio_req->oid)) { - break; - } - idx = data_oid_to_idx(aio_req->oid); - - if (aio_req->create) { - /* - * If the object is newly created one, we need to update - * the vdi object (metadata object). min_dirty_data_idx - * and max_dirty_data_idx are changed to include updated - * index between them. - */ - if (rsp.result == SD_RES_SUCCESS) { - s->inode.data_vdi_id[idx] = s->inode.vdi_id; - acb->max_dirty_data_idx = MAX(idx, acb->max_dirty_data_idx); - acb->min_dirty_data_idx = MIN(idx, acb->min_dirty_data_idx); - } - } - break; - case AIOCB_READ_UDATA: - ret = qemu_co_recvv(fd, acb->qiov->iov, acb->qiov->niov, - aio_req->iov_offset, rsp.data_length); - if (ret != rsp.data_length) { - error_report("failed to get the data, %s", strerror(errno)); - goto err; - } - break; - case AIOCB_FLUSH_CACHE: - if (rsp.result == SD_RES_INVALID_PARMS) { - trace_sheepdog_aio_read_response(); - s->cache_flags = SD_FLAG_CMD_DIRECT; - rsp.result = SD_RES_SUCCESS; - } - break; - case AIOCB_DISCARD_OBJ: - switch (rsp.result) { - case SD_RES_INVALID_PARMS: - error_report("server doesn't support discard command"); - rsp.result = SD_RES_SUCCESS; - s->discard_supported = false; - break; - default: - break; - } - } - - /* No more data for this aio_req (reload_inode below uses its own file - * descriptor handler which doesn't use co_recv). - */ - s->co_recv = NULL; - - qemu_co_mutex_lock(&s->queue_lock); - QLIST_REMOVE(aio_req, aio_siblings); - qemu_co_mutex_unlock(&s->queue_lock); - - switch (rsp.result) { - case SD_RES_SUCCESS: - break; - case SD_RES_READONLY: - if (s->inode.vdi_id == oid_to_vid(aio_req->oid)) { - ret = reload_inode(s, 0, ""); - if (ret < 0) { - goto err; - } - } - if (is_data_obj(aio_req->oid)) { - aio_req->oid = vid_to_data_oid(s->inode.vdi_id, - data_oid_to_idx(aio_req->oid)); - } else { - aio_req->oid = vid_to_vdi_oid(s->inode.vdi_id); - } - resend_aioreq(s, aio_req); - return; - default: - acb->ret = -EIO; - error_report("%s", sd_strerror(rsp.result)); - break; - } - - g_free(aio_req); - - if (!--acb->nr_pending) { - /* - * We've finished all requests which belong to the AIOCB, so - * we can switch back to sd_co_readv/writev now. - */ - aio_co_wake(acb->coroutine); - } - - return; - -err: - reconnect_to_sdog(opaque); -} - -static void co_read_response(void *opaque) -{ - BDRVSheepdogState *s = opaque; - - if (!s->co_recv) { - s->co_recv = qemu_coroutine_create(aio_read_response, opaque); - } - - aio_co_enter(s->aio_context, s->co_recv); -} - -static void co_write_request(void *opaque) -{ - BDRVSheepdogState *s = opaque; - - aio_co_wake(s->co_send); -} - -/* - * Return a socket descriptor to read/write objects. - * - * We cannot use this descriptor for other operations because - * the block driver may be on waiting response from the server. - */ -static int get_sheep_fd(BDRVSheepdogState *s, Error **errp) -{ - int fd; - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - return fd; - } - - aio_set_fd_handler(s->aio_context, fd, false, - co_read_response, NULL, NULL, s); - return fd; -} - -/* - * Parse numeric snapshot ID in @str - * If @str can't be parsed as number, return false. - * Else, if the number is zero or too large, set *@snapid to zero and - * return true. - * Else, set *@snapid to the number and return true. - */ -static bool sd_parse_snapid(const char *str, uint32_t *snapid) -{ - unsigned long ul; - int ret; - - ret = qemu_strtoul(str, NULL, 10, &ul); - if (ret == -ERANGE) { - ul = ret = 0; - } - if (ret) { - return false; - } - if (ul > UINT32_MAX) { - ul = 0; - } - - *snapid = ul; - return true; -} - -static bool sd_parse_snapid_or_tag(const char *str, - uint32_t *snapid, char tag[]) -{ - if (!sd_parse_snapid(str, snapid)) { - *snapid = 0; - if (g_strlcpy(tag, str, SD_MAX_VDI_TAG_LEN) >= SD_MAX_VDI_TAG_LEN) { - return false; - } - } else if (!*snapid) { - return false; - } else { - tag[0] = 0; - } - return true; -} - -typedef struct { - const char *path; /* non-null iff transport is tcp */ - const char *host; /* valid when transport is tcp */ - int port; /* valid when transport is tcp */ - char vdi[SD_MAX_VDI_LEN]; - char tag[SD_MAX_VDI_TAG_LEN]; - uint32_t snap_id; - /* Remainder is only for sd_config_done() */ - URI *uri; - QueryParams *qp; -} SheepdogConfig; - -static void sd_config_done(SheepdogConfig *cfg) -{ - if (cfg->qp) { - query_params_free(cfg->qp); - } - uri_free(cfg->uri); -} - -static void sd_parse_uri(SheepdogConfig *cfg, const char *filename, - Error **errp) -{ - Error *err = NULL; - QueryParams *qp = NULL; - bool is_unix; - URI *uri; - - memset(cfg, 0, sizeof(*cfg)); - - cfg->uri = uri = uri_parse(filename); - if (!uri) { - error_setg(&err, "invalid URI '%s'", filename); - goto out; - } - - /* transport */ - if (!g_strcmp0(uri->scheme, "sheepdog")) { - is_unix = false; - } else if (!g_strcmp0(uri->scheme, "sheepdog+tcp")) { - is_unix = false; - } else if (!g_strcmp0(uri->scheme, "sheepdog+unix")) { - is_unix = true; - } else { - error_setg(&err, "URI scheme must be 'sheepdog', 'sheepdog+tcp'," - " or 'sheepdog+unix'"); - goto out; - } - - if (uri->path == NULL || !strcmp(uri->path, "/")) { - error_setg(&err, "missing file path in URI"); - goto out; - } - if (g_strlcpy(cfg->vdi, uri->path + 1, SD_MAX_VDI_LEN) - >= SD_MAX_VDI_LEN) { - error_setg(&err, "VDI name is too long"); - goto out; - } - - cfg->qp = qp = query_params_parse(uri->query); - - if (is_unix) { - /* sheepdog+unix:///vdiname?socket=path */ - if (uri->server || uri->port) { - error_setg(&err, "URI scheme %s doesn't accept a server address", - uri->scheme); - goto out; - } - if (!qp->n) { - error_setg(&err, - "URI scheme %s requires query parameter 'socket'", - uri->scheme); - goto out; - } - if (qp->n != 1 || strcmp(qp->p[0].name, "socket")) { - error_setg(&err, "unexpected query parameters"); - goto out; - } - cfg->path = qp->p[0].value; - } else { - /* sheepdog[+tcp]://[host:port]/vdiname */ - if (qp->n) { - error_setg(&err, "unexpected query parameters"); - goto out; - } - cfg->host = uri->server; - cfg->port = uri->port; - } - - /* snapshot tag */ - if (uri->fragment) { - if (!sd_parse_snapid_or_tag(uri->fragment, - &cfg->snap_id, cfg->tag)) { - error_setg(&err, "'%s' is not a valid snapshot ID", - uri->fragment); - goto out; - } - } else { - cfg->snap_id = CURRENT_VDI_ID; /* search current vdi */ - } - -out: - if (err) { - error_propagate(errp, err); - sd_config_done(cfg); - } -} - -/* - * Parse a filename (old syntax) - * - * filename must be one of the following formats: - * 1. [vdiname] - * 2. [vdiname]:[snapid] - * 3. [vdiname]:[tag] - * 4. [hostname]:[port]:[vdiname] - * 5. [hostname]:[port]:[vdiname]:[snapid] - * 6. [hostname]:[port]:[vdiname]:[tag] - * - * You can boot from the snapshot images by specifying `snapid` or - * `tag'. - * - * You can run VMs outside the Sheepdog cluster by specifying - * `hostname' and `port' (experimental). - */ -static void parse_vdiname(SheepdogConfig *cfg, const char *filename, - Error **errp) -{ - Error *err = NULL; - char *p, *q, *uri; - const char *host_spec, *vdi_spec; - int nr_sep; - - strstart(filename, "sheepdog:", &filename); - p = q = g_strdup(filename); - - /* count the number of separators */ - nr_sep = 0; - while (*p) { - if (*p == ':') { - nr_sep++; - } - p++; - } - p = q; - - /* use the first two tokens as host_spec. */ - if (nr_sep >= 2) { - host_spec = p; - p = strchr(p, ':'); - p++; - p = strchr(p, ':'); - *p++ = '\0'; - } else { - host_spec = ""; - } - - vdi_spec = p; - - p = strchr(vdi_spec, ':'); - if (p) { - *p++ = '#'; - } - - uri = g_strdup_printf("sheepdog://%s/%s", host_spec, vdi_spec); - - /* - * FIXME We to escape URI meta-characters, e.g. "x?y=z" - * produces "sheepdog://x?y=z". Because of that ... - */ - sd_parse_uri(cfg, uri, &err); - if (err) { - /* - * ... this can fail, but the error message is misleading. - * Replace it by the traditional useless one until the - * escaping is fixed. - */ - error_free(err); - error_setg(errp, "Can't parse filename"); - } - - g_free(q); - g_free(uri); -} - -static void sd_parse_filename(const char *filename, QDict *options, - Error **errp) -{ - Error *err = NULL; - SheepdogConfig cfg; - char buf[32]; - - if (strstr(filename, "://")) { - sd_parse_uri(&cfg, filename, &err); - } else { - parse_vdiname(&cfg, filename, &err); - } - if (err) { - error_propagate(errp, err); - return; - } - - if (cfg.path) { - qdict_set_default_str(options, "server.path", cfg.path); - qdict_set_default_str(options, "server.type", "unix"); - } else { - qdict_set_default_str(options, "server.type", "inet"); - qdict_set_default_str(options, "server.host", - cfg.host ?: SD_DEFAULT_ADDR); - snprintf(buf, sizeof(buf), "%d", cfg.port ?: SD_DEFAULT_PORT); - qdict_set_default_str(options, "server.port", buf); - } - qdict_set_default_str(options, "vdi", cfg.vdi); - qdict_set_default_str(options, "tag", cfg.tag); - if (cfg.snap_id) { - snprintf(buf, sizeof(buf), "%d", cfg.snap_id); - qdict_set_default_str(options, "snap-id", buf); - } - - sd_config_done(&cfg); -} - -static int find_vdi_name(BDRVSheepdogState *s, const char *filename, - uint32_t snapid, const char *tag, uint32_t *vid, - bool lock, Error **errp) -{ - int ret, fd; - SheepdogVdiReq hdr; - SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; - unsigned int wlen, rlen = 0; - char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN] QEMU_NONSTRING; - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - return fd; - } - - /* This pair of strncpy calls ensures that the buffer is zero-filled, - * which is desirable since we'll soon be sending those bytes, and - * don't want the send_req to read uninitialized data. - */ - strncpy(buf, filename, SD_MAX_VDI_LEN); - strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN); - - memset(&hdr, 0, sizeof(hdr)); - if (lock) { - hdr.opcode = SD_OP_LOCK_VDI; - hdr.type = LOCK_TYPE_NORMAL; - } else { - hdr.opcode = SD_OP_GET_VDI_INFO; - } - wlen = SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN; - hdr.proto_ver = SD_PROTO_VER; - hdr.data_length = wlen; - hdr.snapid = snapid; - hdr.flags = SD_FLAG_CMD_WRITE; - - ret = do_req(fd, s->bs, (SheepdogReq *)&hdr, buf, &wlen, &rlen); - if (ret) { - error_setg_errno(errp, -ret, "cannot get vdi info"); - goto out; - } - - if (rsp->result != SD_RES_SUCCESS) { - error_setg(errp, "cannot get vdi info, %s, %s %" PRIu32 " %s", - sd_strerror(rsp->result), filename, snapid, tag); - if (rsp->result == SD_RES_NO_VDI) { - ret = -ENOENT; - } else if (rsp->result == SD_RES_VDI_LOCKED) { - ret = -EBUSY; - } else { - ret = -EIO; - } - goto out; - } - *vid = rsp->vdi_id; - - ret = 0; -out: - closesocket(fd); - return ret; -} - -static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, - struct iovec *iov, int niov, - enum AIOCBState aiocb_type) -{ - int nr_copies = s->inode.nr_copies; - SheepdogObjReq hdr; - unsigned int wlen = 0; - int ret; - uint64_t oid = aio_req->oid; - unsigned int datalen = aio_req->data_len; - uint64_t offset = aio_req->offset; - uint8_t flags = aio_req->flags; - uint64_t old_oid = aio_req->base_oid; - bool create = aio_req->create; - - qemu_co_mutex_lock(&s->queue_lock); - QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings); - qemu_co_mutex_unlock(&s->queue_lock); - - if (!nr_copies) { - error_report("bug"); - } - - memset(&hdr, 0, sizeof(hdr)); - - switch (aiocb_type) { - case AIOCB_FLUSH_CACHE: - hdr.opcode = SD_OP_FLUSH_VDI; - break; - case AIOCB_READ_UDATA: - hdr.opcode = SD_OP_READ_OBJ; - hdr.flags = flags; - break; - case AIOCB_WRITE_UDATA: - if (create) { - hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ; - } else { - hdr.opcode = SD_OP_WRITE_OBJ; - } - wlen = datalen; - hdr.flags = SD_FLAG_CMD_WRITE | flags; - break; - case AIOCB_DISCARD_OBJ: - hdr.opcode = SD_OP_WRITE_OBJ; - hdr.flags = SD_FLAG_CMD_WRITE | flags; - s->inode.data_vdi_id[data_oid_to_idx(oid)] = 0; - offset = offsetof(SheepdogInode, - data_vdi_id[data_oid_to_idx(oid)]); - oid = vid_to_vdi_oid(s->inode.vdi_id); - wlen = datalen = sizeof(uint32_t); - break; - } - - if (s->cache_flags) { - hdr.flags |= s->cache_flags; - } - - hdr.oid = oid; - hdr.cow_oid = old_oid; - hdr.copies = s->inode.nr_copies; - - hdr.data_length = datalen; - hdr.offset = offset; - - hdr.id = aio_req->id; - - qemu_co_mutex_lock(&s->lock); - s->co_send = qemu_coroutine_self(); - aio_set_fd_handler(s->aio_context, s->fd, false, - co_read_response, co_write_request, NULL, s); - socket_set_cork(s->fd, 1); - - /* send a header */ - ret = qemu_co_send(s->fd, &hdr, sizeof(hdr)); - if (ret != sizeof(hdr)) { - error_report("failed to send a req, %s", strerror(errno)); - goto out; - } - - if (wlen) { - ret = qemu_co_sendv(s->fd, iov, niov, aio_req->iov_offset, wlen); - if (ret != wlen) { - error_report("failed to send a data, %s", strerror(errno)); - } - } -out: - socket_set_cork(s->fd, 0); - aio_set_fd_handler(s->aio_context, s->fd, false, - co_read_response, NULL, NULL, s); - s->co_send = NULL; - qemu_co_mutex_unlock(&s->lock); -} - -static int read_write_object(int fd, BlockDriverState *bs, char *buf, - uint64_t oid, uint8_t copies, - unsigned int datalen, uint64_t offset, - bool write, bool create, uint32_t cache_flags) -{ - SheepdogObjReq hdr; - SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr; - unsigned int wlen, rlen; - int ret; - - memset(&hdr, 0, sizeof(hdr)); - - if (write) { - wlen = datalen; - rlen = 0; - hdr.flags = SD_FLAG_CMD_WRITE; - if (create) { - hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ; - } else { - hdr.opcode = SD_OP_WRITE_OBJ; - } - } else { - wlen = 0; - rlen = datalen; - hdr.opcode = SD_OP_READ_OBJ; - } - - hdr.flags |= cache_flags; - - hdr.oid = oid; - hdr.data_length = datalen; - hdr.offset = offset; - hdr.copies = copies; - - ret = do_req(fd, bs, (SheepdogReq *)&hdr, buf, &wlen, &rlen); - if (ret) { - error_report("failed to send a request to the sheep"); - return ret; - } - - switch (rsp->result) { - case SD_RES_SUCCESS: - return 0; - default: - error_report("%s", sd_strerror(rsp->result)); - return -EIO; - } -} - -static int read_object(int fd, BlockDriverState *bs, char *buf, - uint64_t oid, uint8_t copies, - unsigned int datalen, uint64_t offset, - uint32_t cache_flags) -{ - return read_write_object(fd, bs, buf, oid, copies, - datalen, offset, false, - false, cache_flags); -} - -static int write_object(int fd, BlockDriverState *bs, char *buf, - uint64_t oid, uint8_t copies, - unsigned int datalen, uint64_t offset, bool create, - uint32_t cache_flags) -{ - return read_write_object(fd, bs, buf, oid, copies, - datalen, offset, true, - create, cache_flags); -} - -/* update inode with the latest state */ -static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag) -{ - Error *local_err = NULL; - SheepdogInode *inode; - int ret = 0, fd; - uint32_t vid = 0; - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - return -EIO; - } - - inode = g_malloc(SD_INODE_HEADER_SIZE); - - ret = find_vdi_name(s, s->name, snapid, tag, &vid, false, &local_err); - if (ret) { - error_report_err(local_err); - goto out; - } - - ret = read_object(fd, s->bs, (char *)inode, vid_to_vdi_oid(vid), - s->inode.nr_copies, SD_INODE_HEADER_SIZE, 0, - s->cache_flags); - if (ret < 0) { - goto out; - } - - if (inode->vdi_id != s->inode.vdi_id) { - memcpy(&s->inode, inode, SD_INODE_HEADER_SIZE); - } - -out: - g_free(inode); - closesocket(fd); - - return ret; -} - -static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req) -{ - SheepdogAIOCB *acb = aio_req->aiocb; - - aio_req->create = false; - - /* check whether this request becomes a CoW one */ - if (acb->aiocb_type == AIOCB_WRITE_UDATA && is_data_obj(aio_req->oid)) { - int idx = data_oid_to_idx(aio_req->oid); - - if (is_data_obj_writable(&s->inode, idx)) { - goto out; - } - - if (s->inode.data_vdi_id[idx]) { - aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx); - aio_req->flags |= SD_FLAG_CMD_COW; - } - aio_req->create = true; - } -out: - if (is_data_obj(aio_req->oid)) { - add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, - acb->aiocb_type); - } else { - struct iovec iov; - iov.iov_base = &s->inode; - iov.iov_len = sizeof(s->inode); - add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA); - } -} - -static void sd_detach_aio_context(BlockDriverState *bs) -{ - BDRVSheepdogState *s = bs->opaque; - - aio_set_fd_handler(s->aio_context, s->fd, false, NULL, - NULL, NULL, NULL); -} - -static void sd_attach_aio_context(BlockDriverState *bs, - AioContext *new_context) -{ - BDRVSheepdogState *s = bs->opaque; - - s->aio_context = new_context; - aio_set_fd_handler(new_context, s->fd, false, - co_read_response, NULL, NULL, s); -} - -static QemuOptsList runtime_opts = { - .name = "sheepdog", - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), - .desc = { - { - .name = "vdi", - .type = QEMU_OPT_STRING, - }, - { - .name = "snap-id", - .type = QEMU_OPT_NUMBER, - }, - { - .name = "tag", - .type = QEMU_OPT_STRING, - }, - { /* end of list */ } - }, -}; - -static int sd_open(BlockDriverState *bs, QDict *options, int flags, - Error **errp) -{ - int ret, fd; - uint32_t vid = 0; - BDRVSheepdogState *s = bs->opaque; - const char *vdi, *snap_id_str, *tag; - uint64_t snap_id; - char *buf = NULL; - QemuOpts *opts; - - deprecation_warning(); - - s->bs = bs; - s->aio_context = bdrv_get_aio_context(bs); - - opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); - if (!qemu_opts_absorb_qdict(opts, options, errp)) { - ret = -EINVAL; - goto err_no_fd; - } - - s->addr = sd_server_config(options, errp); - if (!s->addr) { - ret = -EINVAL; - goto err_no_fd; - } - - vdi = qemu_opt_get(opts, "vdi"); - snap_id_str = qemu_opt_get(opts, "snap-id"); - snap_id = qemu_opt_get_number(opts, "snap-id", CURRENT_VDI_ID); - tag = qemu_opt_get(opts, "tag"); - - if (!vdi) { - error_setg(errp, "parameter 'vdi' is missing"); - ret = -EINVAL; - goto err_no_fd; - } - if (strlen(vdi) >= SD_MAX_VDI_LEN) { - error_setg(errp, "value of parameter 'vdi' is too long"); - ret = -EINVAL; - goto err_no_fd; - } - - if (snap_id > UINT32_MAX) { - snap_id = 0; - } - if (snap_id_str && !snap_id) { - error_setg(errp, "'snap-id=%s' is not a valid snapshot ID", - snap_id_str); - ret = -EINVAL; - goto err_no_fd; - } - - if (!tag) { - tag = ""; - } - if (strlen(tag) >= SD_MAX_VDI_TAG_LEN) { - error_setg(errp, "value of parameter 'tag' is too long"); - ret = -EINVAL; - goto err_no_fd; - } - - QLIST_INIT(&s->inflight_aio_head); - QLIST_INIT(&s->failed_aio_head); - QLIST_INIT(&s->inflight_aiocb_head); - - s->fd = get_sheep_fd(s, errp); - if (s->fd < 0) { - ret = s->fd; - goto err_no_fd; - } - - ret = find_vdi_name(s, vdi, (uint32_t)snap_id, tag, &vid, true, errp); - if (ret) { - goto err; - } - - /* - * QEMU block layer emulates writethrough cache as 'writeback + flush', so - * we always set SD_FLAG_CMD_CACHE (writeback cache) as default. - */ - s->cache_flags = SD_FLAG_CMD_CACHE; - if (flags & BDRV_O_NOCACHE) { - s->cache_flags = SD_FLAG_CMD_DIRECT; - } - s->discard_supported = true; - - if (snap_id || tag[0]) { - trace_sheepdog_open(vid); - s->is_snapshot = true; - } - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - ret = fd; - goto err; - } - - buf = g_malloc(SD_INODE_SIZE); - ret = read_object(fd, s->bs, buf, vid_to_vdi_oid(vid), - 0, SD_INODE_SIZE, 0, s->cache_flags); - - closesocket(fd); - - if (ret) { - error_setg(errp, "Can't read snapshot inode"); - goto err; - } - - memcpy(&s->inode, buf, sizeof(s->inode)); - - bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE; - bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; - pstrcpy(s->name, sizeof(s->name), vdi); - qemu_co_mutex_init(&s->lock); - qemu_co_mutex_init(&s->queue_lock); - qemu_co_queue_init(&s->overlapping_queue); - qemu_opts_del(opts); - g_free(buf); - return 0; - -err: - aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, - false, NULL, NULL, NULL, NULL); - closesocket(s->fd); -err_no_fd: - qemu_opts_del(opts); - g_free(buf); - return ret; -} - -static int sd_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, - Error **errp) -{ - BDRVSheepdogState *s = state->bs->opaque; - BDRVSheepdogReopenState *re_s; - int ret = 0; - - re_s = state->opaque = g_new0(BDRVSheepdogReopenState, 1); - - re_s->cache_flags = SD_FLAG_CMD_CACHE; - if (state->flags & BDRV_O_NOCACHE) { - re_s->cache_flags = SD_FLAG_CMD_DIRECT; - } - - re_s->fd = get_sheep_fd(s, errp); - if (re_s->fd < 0) { - ret = re_s->fd; - return ret; - } - - return ret; -} - -static void sd_reopen_commit(BDRVReopenState *state) -{ - BDRVSheepdogReopenState *re_s = state->opaque; - BDRVSheepdogState *s = state->bs->opaque; - - if (s->fd) { - aio_set_fd_handler(s->aio_context, s->fd, false, - NULL, NULL, NULL, NULL); - closesocket(s->fd); - } - - s->fd = re_s->fd; - s->cache_flags = re_s->cache_flags; - - g_free(state->opaque); - state->opaque = NULL; - - return; -} - -static void sd_reopen_abort(BDRVReopenState *state) -{ - BDRVSheepdogReopenState *re_s = state->opaque; - BDRVSheepdogState *s = state->bs->opaque; - - if (re_s == NULL) { - return; - } - - if (re_s->fd) { - aio_set_fd_handler(s->aio_context, re_s->fd, false, - NULL, NULL, NULL, NULL); - closesocket(re_s->fd); - } - - g_free(state->opaque); - state->opaque = NULL; - - return; -} - -static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot, - Error **errp) -{ - SheepdogVdiReq hdr; - SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; - int fd, ret; - unsigned int wlen, rlen = 0; - char buf[SD_MAX_VDI_LEN]; - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - return fd; - } - - /* FIXME: would it be better to fail (e.g., return -EIO) when filename - * does not fit in buf? For now, just truncate and avoid buffer overrun. - */ - memset(buf, 0, sizeof(buf)); - pstrcpy(buf, sizeof(buf), s->name); - - memset(&hdr, 0, sizeof(hdr)); - hdr.opcode = SD_OP_NEW_VDI; - hdr.base_vdi_id = s->inode.vdi_id; - - wlen = SD_MAX_VDI_LEN; - - hdr.flags = SD_FLAG_CMD_WRITE; - hdr.snapid = snapshot; - - hdr.data_length = wlen; - hdr.vdi_size = s->inode.vdi_size; - hdr.copy_policy = s->inode.copy_policy; - hdr.copies = s->inode.nr_copies; - hdr.block_size_shift = s->inode.block_size_shift; - - ret = do_req(fd, NULL, (SheepdogReq *)&hdr, buf, &wlen, &rlen); - - closesocket(fd); - - if (ret) { - error_setg_errno(errp, -ret, "create failed"); - return ret; - } - - if (rsp->result != SD_RES_SUCCESS) { - error_setg(errp, "%s, %s", sd_strerror(rsp->result), s->inode.name); - return -EIO; - } - - if (vdi_id) { - *vdi_id = rsp->vdi_id; - } - - return 0; -} - -static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size, - Error **errp) -{ - BlockBackend *blk = NULL; - BDRVSheepdogState *base = bs->opaque; - unsigned long buf_size; - uint32_t idx, max_idx; - uint32_t object_size; - void *buf = NULL; - int ret; - - blk = blk_new_with_bs(bs, - BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, - BLK_PERM_ALL, errp); - - if (!blk) { - ret = -EPERM; - goto out_with_err_set; - } - - blk_set_allow_write_beyond_eof(blk, true); - - object_size = (UINT32_C(1) << base->inode.block_size_shift); - buf_size = MIN(object_size, SD_DATA_OBJ_SIZE); - buf = g_malloc0(buf_size); - - max_idx = DIV_ROUND_UP(new_size, buf_size); - - for (idx = old_size / buf_size; idx < max_idx; idx++) { - /* - * The created image can be a cloned image, so we need to read - * a data from the source image. - */ - ret = blk_pread(blk, idx * buf_size, buf, buf_size); - if (ret < 0) { - goto out; - } - ret = blk_pwrite(blk, idx * buf_size, buf, buf_size, 0); - if (ret < 0) { - goto out; - } - } - - ret = 0; -out: - if (ret < 0) { - error_setg_errno(errp, -ret, "Can't pre-allocate"); - } -out_with_err_set: - blk_unref(blk); - g_free(buf); - - return ret; -} - -static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t size, - Error **errp) -{ - BlockDriverState *bs; - Visitor *v; - QObject *obj = NULL; - QDict *qdict; - int ret; - - v = qobject_output_visitor_new(&obj); - visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &error_abort); - visit_free(v); - - qdict = qobject_to(QDict, obj); - qdict_flatten(qdict); - - qdict_put_str(qdict, "driver", "sheepdog"); - - bs = bdrv_open(NULL, NULL, qdict, BDRV_O_PROTOCOL | BDRV_O_RDWR, errp); - if (bs == NULL) { - ret = -EIO; - goto fail; - } - - ret = sd_prealloc(bs, 0, size, errp); -fail: - bdrv_unref(bs); - qobject_unref(qdict); - return ret; -} - -static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt) -{ - struct SheepdogInode *inode = &s->inode; - - switch (opt->type) { - case SHEEPDOG_REDUNDANCY_TYPE_FULL: - if (opt->u.full.copies > SD_MAX_COPIES || opt->u.full.copies < 1) { - return -EINVAL; - } - inode->copy_policy = 0; - inode->nr_copies = opt->u.full.copies; - return 0; - - case SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED: - { - int64_t copy = opt->u.erasure_coded.data_strips; - int64_t parity = opt->u.erasure_coded.parity_strips; - - if (copy != 2 && copy != 4 && copy != 8 && copy != 16) { - return -EINVAL; - } - - if (parity >= SD_EC_MAX_STRIP || parity < 1) { - return -EINVAL; - } - - /* - * 4 bits for parity and 4 bits for data. - * We have to compress upper data bits because it can't represent 16 - */ - inode->copy_policy = ((copy / 2) << 4) + parity; - inode->nr_copies = copy + parity; - return 0; - } - - default: - g_assert_not_reached(); - } - - return -EINVAL; -} - -/* - * Sheepdog support two kinds of redundancy, full replication and erasure - * coding. - * - * # create a fully replicated vdi with x copies - * -o redundancy=x (1 <= x <= SD_MAX_COPIES) - * - * # create a erasure coded vdi with x data strips and y parity strips - * -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP) - */ -static SheepdogRedundancy *parse_redundancy_str(const char *opt) -{ - SheepdogRedundancy *redundancy; - const char *n1, *n2; - long copy, parity; - char p[10]; - int ret; - - pstrcpy(p, sizeof(p), opt); - n1 = strtok(p, ":"); - n2 = strtok(NULL, ":"); - - if (!n1) { - return NULL; - } - - ret = qemu_strtol(n1, NULL, 10, ©); - if (ret < 0) { - return NULL; - } - - redundancy = g_new0(SheepdogRedundancy, 1); - if (!n2) { - *redundancy = (SheepdogRedundancy) { - .type = SHEEPDOG_REDUNDANCY_TYPE_FULL, - .u.full.copies = copy, - }; - } else { - ret = qemu_strtol(n2, NULL, 10, &parity); - if (ret < 0) { - g_free(redundancy); - return NULL; - } - - *redundancy = (SheepdogRedundancy) { - .type = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED, - .u.erasure_coded = { - .data_strips = copy, - .parity_strips = parity, - }, - }; - } - - return redundancy; -} - -static int parse_block_size_shift(BDRVSheepdogState *s, - BlockdevCreateOptionsSheepdog *opts) -{ - struct SheepdogInode *inode = &s->inode; - uint64_t object_size; - int obj_order; - - if (opts->has_object_size) { - object_size = opts->object_size; - - if ((object_size - 1) & object_size) { /* not a power of 2? */ - return -EINVAL; - } - obj_order = ctz32(object_size); - if (obj_order < 20 || obj_order > 31) { - return -EINVAL; - } - inode->block_size_shift = (uint8_t)obj_order; - } - - return 0; -} - -static int sd_co_create(BlockdevCreateOptions *options, Error **errp) -{ - BlockdevCreateOptionsSheepdog *opts = &options->u.sheepdog; - int ret = 0; - uint32_t vid = 0; - char *backing_file = NULL; - char *buf = NULL; - BDRVSheepdogState *s; - uint64_t max_vdi_size; - bool prealloc = false; - - assert(options->driver == BLOCKDEV_DRIVER_SHEEPDOG); - - deprecation_warning(); - - s = g_new0(BDRVSheepdogState, 1); - - /* Steal SocketAddress from QAPI, set NULL to prevent double free */ - s->addr = opts->location->server; - opts->location->server = NULL; - - if (strlen(opts->location->vdi) >= sizeof(s->name)) { - error_setg(errp, "'vdi' string too long"); - ret = -EINVAL; - goto out; - } - pstrcpy(s->name, sizeof(s->name), opts->location->vdi); - - s->inode.vdi_size = opts->size; - backing_file = opts->backing_file; - - if (!opts->has_preallocation) { - opts->preallocation = PREALLOC_MODE_OFF; - } - switch (opts->preallocation) { - case PREALLOC_MODE_OFF: - prealloc = false; - break; - case PREALLOC_MODE_FULL: - prealloc = true; - break; - default: - error_setg(errp, "Preallocation mode not supported for Sheepdog"); - ret = -EINVAL; - goto out; - } - - if (opts->has_redundancy) { - ret = parse_redundancy(s, opts->redundancy); - if (ret < 0) { - error_setg(errp, "Invalid redundancy mode"); - goto out; - } - } - ret = parse_block_size_shift(s, opts); - if (ret < 0) { - error_setg(errp, "Invalid object_size." - " obect_size needs to be power of 2" - " and be limited from 2^20 to 2^31"); - goto out; - } - - if (opts->has_backing_file) { - BlockBackend *blk; - BDRVSheepdogState *base; - BlockDriver *drv; - - /* Currently, only Sheepdog backing image is supported. */ - drv = bdrv_find_protocol(opts->backing_file, true, NULL); - if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { - error_setg(errp, "backing_file must be a sheepdog image"); - ret = -EINVAL; - goto out; - } - - blk = blk_new_open(opts->backing_file, NULL, NULL, - BDRV_O_PROTOCOL, errp); - if (blk == NULL) { - ret = -EIO; - goto out; - } - - base = blk_bs(blk)->opaque; - - if (!is_snapshot(&base->inode)) { - error_setg(errp, "cannot clone from a non snapshot vdi"); - blk_unref(blk); - ret = -EINVAL; - goto out; - } - s->inode.vdi_id = base->inode.vdi_id; - blk_unref(blk); - } - - s->aio_context = qemu_get_aio_context(); - - /* if block_size_shift is not specified, get cluster default value */ - if (s->inode.block_size_shift == 0) { - SheepdogVdiReq hdr; - SheepdogClusterRsp *rsp = (SheepdogClusterRsp *)&hdr; - int fd; - unsigned int wlen = 0, rlen = 0; - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - ret = fd; - goto out; - } - - memset(&hdr, 0, sizeof(hdr)); - hdr.opcode = SD_OP_GET_CLUSTER_DEFAULT; - hdr.proto_ver = SD_PROTO_VER; - - ret = do_req(fd, NULL, (SheepdogReq *)&hdr, - NULL, &wlen, &rlen); - closesocket(fd); - if (ret) { - error_setg_errno(errp, -ret, "failed to get cluster default"); - goto out; - } - if (rsp->result == SD_RES_SUCCESS) { - s->inode.block_size_shift = rsp->block_size_shift; - } else { - s->inode.block_size_shift = SD_DEFAULT_BLOCK_SIZE_SHIFT; - } - } - - max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS; - - if (s->inode.vdi_size > max_vdi_size) { - error_setg(errp, "An image is too large." - " The maximum image size is %"PRIu64 "GB", - max_vdi_size / 1024 / 1024 / 1024); - ret = -EINVAL; - goto out; - } - - ret = do_sd_create(s, &vid, 0, errp); - if (ret) { - goto out; - } - - if (prealloc) { - ret = sd_create_prealloc(opts->location, opts->size, errp); - } -out: - g_free(backing_file); - g_free(buf); - g_free(s->addr); - g_free(s); - return ret; -} - -static int coroutine_fn sd_co_create_opts(BlockDriver *drv, - const char *filename, - QemuOpts *opts, - Error **errp) -{ - BlockdevCreateOptions *create_options = NULL; - QDict *qdict = NULL, *location_qdict; - Visitor *v; - 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"); - - location_qdict = qdict_new(); - qdict_put(qdict, "location", location_qdict); - - sd_parse_filename(filename, location_qdict, &local_err); - if (local_err) { - error_propagate(errp, local_err); - ret = -EINVAL; - goto fail; - } - - qdict_flatten(qdict); - - /* Change legacy command line options into QMP ones */ - static const QDictRenames opt_renames[] = { - { BLOCK_OPT_BACKING_FILE, "backing-file" }, - { BLOCK_OPT_OBJECT_SIZE, "object-size" }, - { NULL, NULL }, - }; - - if (!qdict_rename_keys(qdict, opt_renames, errp)) { - ret = -EINVAL; - goto fail; - } - - /* Get the QAPI object */ - v = qobject_input_visitor_new_flat_confused(qdict, errp); - if (!v) { - ret = -EINVAL; - goto fail; - } - - visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp); - visit_free(v); - if (!create_options) { - ret = -EINVAL; - goto fail; - } - - assert(create_options->driver == BLOCKDEV_DRIVER_SHEEPDOG); - create_options->u.sheepdog.size = - ROUND_UP(create_options->u.sheepdog.size, BDRV_SECTOR_SIZE); - - if (redundancy) { - create_options->u.sheepdog.has_redundancy = true; - create_options->u.sheepdog.redundancy = - parse_redundancy_str(redundancy); - if (create_options->u.sheepdog.redundancy == NULL) { - error_setg(errp, "Invalid redundancy mode"); - ret = -EINVAL; - goto fail; - } - } - - ret = sd_co_create(create_options, errp); -fail: - qapi_free_BlockdevCreateOptions(create_options); - qobject_unref(qdict); - g_free(redundancy); - g_free(backing_fmt); - return ret; -} - -static void sd_close(BlockDriverState *bs) -{ - Error *local_err = NULL; - BDRVSheepdogState *s = bs->opaque; - SheepdogVdiReq hdr; - SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; - unsigned int wlen, rlen = 0; - int fd, ret; - - trace_sheepdog_close(s->name); - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - return; - } - - memset(&hdr, 0, sizeof(hdr)); - - hdr.opcode = SD_OP_RELEASE_VDI; - hdr.type = LOCK_TYPE_NORMAL; - hdr.base_vdi_id = s->inode.vdi_id; - wlen = strlen(s->name) + 1; - hdr.data_length = wlen; - hdr.flags = SD_FLAG_CMD_WRITE; - - ret = do_req(fd, s->bs, (SheepdogReq *)&hdr, - s->name, &wlen, &rlen); - - closesocket(fd); - - if (!ret && rsp->result != SD_RES_SUCCESS && - rsp->result != SD_RES_VDI_NOT_LOCKED) { - error_report("%s, %s", sd_strerror(rsp->result), s->name); - } - - aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, - false, NULL, NULL, NULL, NULL); - closesocket(s->fd); - qapi_free_SocketAddress(s->addr); -} - -static int64_t sd_getlength(BlockDriverState *bs) -{ - BDRVSheepdogState *s = bs->opaque; - - return s->inode.vdi_size; -} - -static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset, - bool exact, PreallocMode prealloc, - BdrvRequestFlags flags, Error **errp) -{ - BDRVSheepdogState *s = bs->opaque; - int ret, fd; - unsigned int datalen; - uint64_t max_vdi_size; - int64_t old_size = s->inode.vdi_size; - - if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_FULL) { - error_setg(errp, "Unsupported preallocation mode '%s'", - PreallocMode_str(prealloc)); - return -ENOTSUP; - } - - max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS; - if (offset < old_size) { - error_setg(errp, "shrinking is not supported"); - return -EINVAL; - } else if (offset > max_vdi_size) { - error_setg(errp, "too big image size"); - return -EINVAL; - } - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - return fd; - } - - /* we don't need to update entire object */ - datalen = SD_INODE_HEADER_SIZE; - s->inode.vdi_size = offset; - ret = write_object(fd, s->bs, (char *)&s->inode, - vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies, - datalen, 0, false, s->cache_flags); - close(fd); - - if (ret < 0) { - error_setg_errno(errp, -ret, "failed to update an inode"); - return ret; - } - - if (prealloc == PREALLOC_MODE_FULL) { - ret = sd_prealloc(bs, old_size, offset, errp); - if (ret < 0) { - return ret; - } - } - - return 0; -} - -/* - * This function is called after writing data objects. If we need to - * update metadata, this sends a write request to the vdi object. - */ -static void coroutine_fn sd_write_done(SheepdogAIOCB *acb) -{ - BDRVSheepdogState *s = acb->s; - struct iovec iov; - AIOReq *aio_req; - uint32_t offset, data_len, mn, mx; - - mn = acb->min_dirty_data_idx; - mx = acb->max_dirty_data_idx; - if (mn <= mx) { - /* we need to update the vdi object. */ - ++acb->nr_pending; - offset = sizeof(s->inode) - sizeof(s->inode.data_vdi_id) + - mn * sizeof(s->inode.data_vdi_id[0]); - data_len = (mx - mn + 1) * sizeof(s->inode.data_vdi_id[0]); - - acb->min_dirty_data_idx = UINT32_MAX; - acb->max_dirty_data_idx = 0; - - iov.iov_base = &s->inode; - iov.iov_len = sizeof(s->inode); - aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id), - data_len, offset, 0, false, 0, offset); - add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA); - if (--acb->nr_pending) { - qemu_coroutine_yield(); - } - } -} - -/* Delete current working VDI on the snapshot chain */ -static bool sd_delete(BDRVSheepdogState *s) -{ - Error *local_err = NULL; - unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0; - SheepdogVdiReq hdr = { - .opcode = SD_OP_DEL_VDI, - .base_vdi_id = s->inode.vdi_id, - .data_length = wlen, - .flags = SD_FLAG_CMD_WRITE, - }; - SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; - int fd, ret; - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - return false; - } - - ret = do_req(fd, s->bs, (SheepdogReq *)&hdr, - s->name, &wlen, &rlen); - closesocket(fd); - if (ret) { - return false; - } - switch (rsp->result) { - case SD_RES_NO_VDI: - error_report("%s was already deleted", s->name); - /* fall through */ - case SD_RES_SUCCESS: - break; - default: - error_report("%s, %s", sd_strerror(rsp->result), s->name); - return false; - } - - return true; -} - -/* - * Create a writable VDI from a snapshot - */ -static int sd_create_branch(BDRVSheepdogState *s) -{ - Error *local_err = NULL; - int ret, fd; - uint32_t vid; - char *buf; - bool deleted; - - trace_sheepdog_create_branch_snapshot(s->inode.vdi_id); - - buf = g_malloc(SD_INODE_SIZE); - - /* - * Even If deletion fails, we will just create extra snapshot based on - * the working VDI which was supposed to be deleted. So no need to - * false bail out. - */ - deleted = sd_delete(s); - ret = do_sd_create(s, &vid, !deleted, &local_err); - if (ret) { - error_report_err(local_err); - goto out; - } - - trace_sheepdog_create_branch_created(vid); - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - ret = fd; - goto out; - } - - ret = read_object(fd, s->bs, buf, vid_to_vdi_oid(vid), - s->inode.nr_copies, SD_INODE_SIZE, 0, s->cache_flags); - - closesocket(fd); - - if (ret < 0) { - goto out; - } - - memcpy(&s->inode, buf, sizeof(s->inode)); - - s->is_snapshot = false; - ret = 0; - trace_sheepdog_create_branch_new(s->inode.vdi_id); - -out: - g_free(buf); - - return ret; -} - -/* - * Send I/O requests to the server. - * - * This function sends requests to the server, links the requests to - * the inflight_list in BDRVSheepdogState, and exits without - * waiting the response. The responses are received in the - * `aio_read_response' function which is called from the main loop as - * a fd handler. - * - * Returns 1 when we need to wait a response, 0 when there is no sent - * request and -errno in error cases. - */ -static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb) -{ - int ret = 0; - unsigned long len, done = 0, total = acb->nb_sectors * BDRV_SECTOR_SIZE; - unsigned long idx; - uint32_t object_size; - uint64_t oid; - uint64_t offset; - BDRVSheepdogState *s = acb->s; - SheepdogInode *inode = &s->inode; - AIOReq *aio_req; - - if (acb->aiocb_type == AIOCB_WRITE_UDATA && s->is_snapshot) { - /* - * In the case we open the snapshot VDI, Sheepdog creates the - * writable VDI when we do a write operation first. - */ - ret = sd_create_branch(s); - if (ret) { - acb->ret = -EIO; - return; - } - } - - object_size = (UINT32_C(1) << inode->block_size_shift); - idx = acb->sector_num * BDRV_SECTOR_SIZE / object_size; - offset = (acb->sector_num * BDRV_SECTOR_SIZE) % object_size; - - /* - * Make sure we don't free the aiocb before we are done with all requests. - * This additional reference is dropped at the end of this function. - */ - acb->nr_pending++; - - while (done != total) { - uint8_t flags = 0; - uint64_t old_oid = 0; - bool create = false; - - oid = vid_to_data_oid(inode->data_vdi_id[idx], idx); - - len = MIN(total - done, object_size - offset); - - switch (acb->aiocb_type) { - case AIOCB_READ_UDATA: - if (!inode->data_vdi_id[idx]) { - qemu_iovec_memset(acb->qiov, done, 0, len); - goto done; - } - break; - case AIOCB_WRITE_UDATA: - if (!inode->data_vdi_id[idx]) { - create = true; - } else if (!is_data_obj_writable(inode, idx)) { - /* Copy-On-Write */ - create = true; - old_oid = oid; - flags = SD_FLAG_CMD_COW; - } - break; - case AIOCB_DISCARD_OBJ: - /* - * We discard the object only when the whole object is - * 1) allocated 2) trimmed. Otherwise, simply skip it. - */ - if (len != object_size || inode->data_vdi_id[idx] == 0) { - goto done; - } - break; - default: - break; - } - - if (create) { - trace_sheepdog_co_rw_vector_update(inode->vdi_id, oid, - vid_to_data_oid(inode->data_vdi_id[idx], idx), - idx); - oid = vid_to_data_oid(inode->vdi_id, idx); - trace_sheepdog_co_rw_vector_new(oid); - } - - aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, create, - old_oid, - acb->aiocb_type == AIOCB_DISCARD_OBJ ? - 0 : done); - add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, - acb->aiocb_type); - done: - offset = 0; - idx++; - done += len; - } - if (--acb->nr_pending) { - qemu_coroutine_yield(); - } -} - -static void sd_aio_complete(SheepdogAIOCB *acb) -{ - BDRVSheepdogState *s; - if (acb->aiocb_type == AIOCB_FLUSH_CACHE) { - return; - } - - s = acb->s; - qemu_co_mutex_lock(&s->queue_lock); - QLIST_REMOVE(acb, aiocb_siblings); - qemu_co_queue_restart_all(&s->overlapping_queue); - qemu_co_mutex_unlock(&s->queue_lock); -} - -static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov, - int flags) -{ - SheepdogAIOCB acb; - int ret; - int64_t offset = (sector_num + nb_sectors) * BDRV_SECTOR_SIZE; - BDRVSheepdogState *s = bs->opaque; - - assert(!flags); - if (offset > s->inode.vdi_size) { - ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL); - if (ret < 0) { - return ret; - } - } - - sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_WRITE_UDATA); - sd_co_rw_vector(&acb); - sd_write_done(&acb); - sd_aio_complete(&acb); - - return acb.ret; -} - -static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, QEMUIOVector *qiov) -{ - SheepdogAIOCB acb; - BDRVSheepdogState *s = bs->opaque; - - sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_READ_UDATA); - sd_co_rw_vector(&acb); - sd_aio_complete(&acb); - - return acb.ret; -} - -static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs) -{ - BDRVSheepdogState *s = bs->opaque; - SheepdogAIOCB acb; - AIOReq *aio_req; - - if (s->cache_flags != SD_FLAG_CMD_CACHE) { - return 0; - } - - sd_aio_setup(&acb, s, NULL, 0, 0, AIOCB_FLUSH_CACHE); - - acb.nr_pending++; - aio_req = alloc_aio_req(s, &acb, vid_to_vdi_oid(s->inode.vdi_id), - 0, 0, 0, false, 0, 0); - add_aio_request(s, aio_req, NULL, 0, acb.aiocb_type); - - if (--acb.nr_pending) { - qemu_coroutine_yield(); - } - - sd_aio_complete(&acb); - return acb.ret; -} - -static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) -{ - Error *local_err = NULL; - BDRVSheepdogState *s = bs->opaque; - int ret, fd; - uint32_t new_vid; - SheepdogInode *inode; - unsigned int datalen; - - trace_sheepdog_snapshot_create_info(sn_info->name, sn_info->id_str, s->name, - sn_info->vm_state_size, s->is_snapshot); - - if (s->is_snapshot) { - error_report("You can't create a snapshot of a snapshot VDI, " - "%s (%" PRIu32 ").", s->name, s->inode.vdi_id); - - return -EINVAL; - } - - trace_sheepdog_snapshot_create(sn_info->name, sn_info->id_str); - - s->inode.vm_state_size = sn_info->vm_state_size; - s->inode.vm_clock_nsec = sn_info->vm_clock_nsec; - /* It appears that inode.tag does not require a NUL terminator, - * which means this use of strncpy is ok. - */ - strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag)); - /* we don't need to update entire object */ - datalen = SD_INODE_HEADER_SIZE; - inode = g_malloc(datalen); - - /* refresh inode. */ - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - ret = fd; - goto cleanup; - } - - ret = write_object(fd, s->bs, (char *)&s->inode, - vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies, - datalen, 0, false, s->cache_flags); - if (ret < 0) { - error_report("failed to write snapshot's inode."); - goto cleanup; - } - - ret = do_sd_create(s, &new_vid, 1, &local_err); - if (ret < 0) { - error_reportf_err(local_err, - "failed to create inode for snapshot: "); - goto cleanup; - } - - ret = read_object(fd, s->bs, (char *)inode, - vid_to_vdi_oid(new_vid), s->inode.nr_copies, datalen, 0, - s->cache_flags); - - if (ret < 0) { - error_report("failed to read new inode info. %s", strerror(errno)); - goto cleanup; - } - - memcpy(&s->inode, inode, datalen); - trace_sheepdog_snapshot_create_inode(s->inode.name, s->inode.snap_id, - s->inode.vdi_id); - -cleanup: - g_free(inode); - closesocket(fd); - return ret; -} - -/* - * We implement rollback(loadvm) operation to the specified snapshot by - * 1) switch to the snapshot - * 2) rely on sd_create_branch to delete working VDI and - * 3) create a new working VDI based on the specified snapshot - */ -static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) -{ - BDRVSheepdogState *s = bs->opaque; - BDRVSheepdogState *old_s; - char tag[SD_MAX_VDI_TAG_LEN]; - uint32_t snapid = 0; - int ret; - - if (!sd_parse_snapid_or_tag(snapshot_id, &snapid, tag)) { - return -EINVAL; - } - - old_s = g_new(BDRVSheepdogState, 1); - - memcpy(old_s, s, sizeof(BDRVSheepdogState)); - - ret = reload_inode(s, snapid, tag); - if (ret) { - goto out; - } - - ret = sd_create_branch(s); - if (ret) { - goto out; - } - - g_free(old_s); - - return 0; -out: - /* recover bdrv_sd_state */ - memcpy(s, old_s, sizeof(BDRVSheepdogState)); - g_free(old_s); - - error_report("failed to open. recover old bdrv_sd_state."); - - return ret; -} - -#define NR_BATCHED_DISCARD 128 - -static int remove_objects(BDRVSheepdogState *s, Error **errp) -{ - int fd, i = 0, nr_objs = 0; - int ret; - SheepdogInode *inode = &s->inode; - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - return fd; - } - - nr_objs = count_data_objs(inode); - while (i < nr_objs) { - int start_idx, nr_filled_idx; - - while (i < nr_objs && !inode->data_vdi_id[i]) { - i++; - } - start_idx = i; - - nr_filled_idx = 0; - while (i < nr_objs && nr_filled_idx < NR_BATCHED_DISCARD) { - if (inode->data_vdi_id[i]) { - inode->data_vdi_id[i] = 0; - nr_filled_idx++; - } - - i++; - } - - ret = write_object(fd, s->bs, - (char *)&inode->data_vdi_id[start_idx], - vid_to_vdi_oid(s->inode.vdi_id), inode->nr_copies, - (i - start_idx) * sizeof(uint32_t), - offsetof(struct SheepdogInode, - data_vdi_id[start_idx]), - false, s->cache_flags); - if (ret < 0) { - error_setg(errp, "Failed to discard snapshot inode"); - goto out; - } - } - - ret = 0; -out: - closesocket(fd); - return ret; -} - -static int sd_snapshot_delete(BlockDriverState *bs, - const char *snapshot_id, - const char *name, - Error **errp) -{ - /* - * FIXME should delete the snapshot matching both @snapshot_id and - * @name, but @name not used here - */ - unsigned long snap_id = 0; - char snap_tag[SD_MAX_VDI_TAG_LEN]; - int fd, ret; - char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN]; - BDRVSheepdogState *s = bs->opaque; - unsigned int wlen = SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN, rlen = 0; - uint32_t vid; - SheepdogVdiReq hdr = { - .opcode = SD_OP_DEL_VDI, - .data_length = wlen, - .flags = SD_FLAG_CMD_WRITE, - }; - SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr; - - ret = remove_objects(s, errp); - if (ret) { - return ret; - } - - memset(buf, 0, sizeof(buf)); - memset(snap_tag, 0, sizeof(snap_tag)); - pstrcpy(buf, SD_MAX_VDI_LEN, s->name); - /* TODO Use sd_parse_snapid() once this mess is cleaned up */ - ret = qemu_strtoul(snapshot_id, NULL, 10, &snap_id); - if (ret || snap_id > UINT32_MAX) { - /* - * FIXME Since qemu_strtoul() returns -EINVAL when - * @snapshot_id is null, @snapshot_id is mandatory. Correct - * would be to require at least one of @snapshot_id and @name. - */ - error_setg(errp, "Invalid snapshot ID: %s", - snapshot_id ? snapshot_id : "<null>"); - return -EINVAL; - } - - if (snap_id) { - hdr.snapid = (uint32_t) snap_id; - } else { - /* FIXME I suspect we should use @name here */ - /* FIXME don't truncate silently */ - pstrcpy(snap_tag, sizeof(snap_tag), snapshot_id); - pstrcpy(buf + SD_MAX_VDI_LEN, SD_MAX_VDI_TAG_LEN, snap_tag); - } - - ret = find_vdi_name(s, s->name, snap_id, snap_tag, &vid, true, errp); - if (ret) { - return ret; - } - - fd = connect_to_sdog(s, errp); - if (fd < 0) { - return fd; - } - - ret = do_req(fd, s->bs, (SheepdogReq *)&hdr, - buf, &wlen, &rlen); - closesocket(fd); - if (ret) { - error_setg_errno(errp, -ret, "Couldn't send request to server"); - return ret; - } - - switch (rsp->result) { - case SD_RES_NO_VDI: - error_setg(errp, "Can't find the snapshot"); - return -ENOENT; - case SD_RES_SUCCESS: - break; - default: - error_setg(errp, "%s", sd_strerror(rsp->result)); - return -EIO; - } - - return 0; -} - -static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) -{ - Error *local_err = NULL; - BDRVSheepdogState *s = bs->opaque; - SheepdogReq req; - int fd, nr = 1024, ret, max = BITS_TO_LONGS(SD_NR_VDIS) * sizeof(long); - QEMUSnapshotInfo *sn_tab = NULL; - unsigned wlen, rlen; - int found = 0; - SheepdogInode *inode; - unsigned long *vdi_inuse; - unsigned int start_nr; - uint64_t hval; - uint32_t vid; - - vdi_inuse = g_malloc(max); - inode = g_malloc(SD_INODE_HEADER_SIZE); - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - ret = fd; - goto out; - } - - rlen = max; - wlen = 0; - - memset(&req, 0, sizeof(req)); - - req.opcode = SD_OP_READ_VDIS; - req.data_length = max; - - ret = do_req(fd, s->bs, &req, vdi_inuse, &wlen, &rlen); - - closesocket(fd); - if (ret) { - goto out; - } - - sn_tab = g_new0(QEMUSnapshotInfo, nr); - - /* calculate a vdi id with hash function */ - hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT); - start_nr = hval & (SD_NR_VDIS - 1); - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - ret = fd; - goto out; - } - - for (vid = start_nr; found < nr; vid = (vid + 1) % SD_NR_VDIS) { - if (!test_bit(vid, vdi_inuse)) { - break; - } - - /* we don't need to read entire object */ - ret = read_object(fd, s->bs, (char *)inode, - vid_to_vdi_oid(vid), - 0, SD_INODE_HEADER_SIZE, 0, - s->cache_flags); - - if (ret) { - continue; - } - - if (!strcmp(inode->name, s->name) && is_snapshot(inode)) { - sn_tab[found].date_sec = inode->snap_ctime >> 32; - sn_tab[found].date_nsec = inode->snap_ctime & 0xffffffff; - sn_tab[found].vm_state_size = inode->vm_state_size; - sn_tab[found].vm_clock_nsec = inode->vm_clock_nsec; - - snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), - "%" PRIu32, inode->snap_id); - pstrcpy(sn_tab[found].name, - MIN(sizeof(sn_tab[found].name), sizeof(inode->tag)), - inode->tag); - found++; - } - } - - closesocket(fd); -out: - *psn_tab = sn_tab; - - g_free(vdi_inuse); - g_free(inode); - - if (ret < 0) { - return ret; - } - - return found; -} - -static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data, - int64_t pos, int size, int load) -{ - Error *local_err = NULL; - bool create; - int fd, ret = 0, remaining = size; - unsigned int data_len; - uint64_t vmstate_oid; - uint64_t offset; - uint32_t vdi_index; - uint32_t vdi_id = load ? s->inode.parent_vdi_id : s->inode.vdi_id; - uint32_t object_size = (UINT32_C(1) << s->inode.block_size_shift); - - fd = connect_to_sdog(s, &local_err); - if (fd < 0) { - error_report_err(local_err); - return fd; - } - - while (remaining) { - vdi_index = pos / object_size; - offset = pos % object_size; - - data_len = MIN(remaining, object_size - offset); - - vmstate_oid = vid_to_vmstate_oid(vdi_id, vdi_index); - - create = (offset == 0); - if (load) { - ret = read_object(fd, s->bs, (char *)data, vmstate_oid, - s->inode.nr_copies, data_len, offset, - s->cache_flags); - } else { - ret = write_object(fd, s->bs, (char *)data, vmstate_oid, - s->inode.nr_copies, data_len, offset, create, - s->cache_flags); - } - - if (ret < 0) { - error_report("failed to save vmstate %s", strerror(errno)); - goto cleanup; - } - - pos += data_len; - data += data_len; - remaining -= data_len; - } - ret = size; -cleanup: - closesocket(fd); - return ret; -} - -static int sd_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, - int64_t pos) -{ - BDRVSheepdogState *s = bs->opaque; - void *buf; - int ret; - - buf = qemu_blockalign(bs, qiov->size); - qemu_iovec_to_buf(qiov, 0, buf, qiov->size); - ret = do_load_save_vmstate(s, (uint8_t *) buf, pos, qiov->size, 0); - qemu_vfree(buf); - - return ret; -} - -static int sd_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, - int64_t pos) -{ - BDRVSheepdogState *s = bs->opaque; - void *buf; - int ret; - - buf = qemu_blockalign(bs, qiov->size); - ret = do_load_save_vmstate(s, buf, pos, qiov->size, 1); - qemu_iovec_from_buf(qiov, 0, buf, qiov->size); - qemu_vfree(buf); - - return ret; -} - - -static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset, - int bytes) -{ - SheepdogAIOCB acb; - BDRVSheepdogState *s = bs->opaque; - QEMUIOVector discard_iov; - struct iovec iov; - uint32_t zero = 0; - - if (!s->discard_supported) { - return 0; - } - - memset(&discard_iov, 0, sizeof(discard_iov)); - memset(&iov, 0, sizeof(iov)); - iov.iov_base = &zero; - iov.iov_len = sizeof(zero); - discard_iov.iov = &iov; - discard_iov.niov = 1; - if (!QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE)) { - return -ENOTSUP; - } - sd_aio_setup(&acb, s, &discard_iov, offset >> BDRV_SECTOR_BITS, - bytes >> BDRV_SECTOR_BITS, AIOCB_DISCARD_OBJ); - sd_co_rw_vector(&acb); - sd_aio_complete(&acb); - - return acb.ret; -} - -static coroutine_fn int -sd_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, - int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file) -{ - BDRVSheepdogState *s = bs->opaque; - SheepdogInode *inode = &s->inode; - uint32_t object_size = (UINT32_C(1) << inode->block_size_shift); - unsigned long start = offset / object_size, - end = DIV_ROUND_UP(offset + bytes, object_size); - unsigned long idx; - *map = offset; - int ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID; - - for (idx = start; idx < end; idx++) { - if (inode->data_vdi_id[idx] == 0) { - break; - } - } - if (idx == start) { - /* Get the longest length of unallocated sectors */ - ret = 0; - for (idx = start + 1; idx < end; idx++) { - if (inode->data_vdi_id[idx] != 0) { - break; - } - } - } - - *pnum = (idx - start) * object_size; - if (*pnum > bytes) { - *pnum = bytes; - } - if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID) { - *file = bs; - } - return ret; -} - -static int64_t sd_get_allocated_file_size(BlockDriverState *bs) -{ - BDRVSheepdogState *s = bs->opaque; - SheepdogInode *inode = &s->inode; - uint32_t object_size = (UINT32_C(1) << inode->block_size_shift); - unsigned long i, last = DIV_ROUND_UP(inode->vdi_size, object_size); - uint64_t size = 0; - - for (i = 0; i < last; i++) { - if (inode->data_vdi_id[i] == 0) { - continue; - } - size += object_size; - } - return size; -} - -static QemuOptsList sd_create_opts = { - .name = "sheepdog-create-opts", - .head = QTAILQ_HEAD_INITIALIZER(sd_create_opts.head), - .desc = { - { - .name = BLOCK_OPT_SIZE, - .type = QEMU_OPT_SIZE, - .help = "Virtual disk size" - }, - { - .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 = "Must be 'sheepdog' if present", - }, - { - .name = BLOCK_OPT_PREALLOC, - .type = QEMU_OPT_STRING, - .help = "Preallocation mode (allowed values: off, full)" - }, - { - .name = BLOCK_OPT_REDUNDANCY, - .type = QEMU_OPT_STRING, - .help = "Redundancy of the image" - }, - { - .name = BLOCK_OPT_OBJECT_SIZE, - .type = QEMU_OPT_SIZE, - .help = "Object size of the image" - }, - { /* end of list */ } - } -}; - -static const char *const sd_strong_runtime_opts[] = { - "vdi", - "snap-id", - "tag", - "server.", - - NULL -}; - -static BlockDriver bdrv_sheepdog = { - .format_name = "sheepdog", - .protocol_name = "sheepdog", - .instance_size = sizeof(BDRVSheepdogState), - .bdrv_parse_filename = sd_parse_filename, - .bdrv_file_open = sd_open, - .bdrv_reopen_prepare = sd_reopen_prepare, - .bdrv_reopen_commit = sd_reopen_commit, - .bdrv_reopen_abort = sd_reopen_abort, - .bdrv_close = sd_close, - .bdrv_co_create = sd_co_create, - .bdrv_co_create_opts = sd_co_create_opts, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - .bdrv_getlength = sd_getlength, - .bdrv_get_allocated_file_size = sd_get_allocated_file_size, - .bdrv_co_truncate = sd_co_truncate, - - .bdrv_co_readv = sd_co_readv, - .bdrv_co_writev = sd_co_writev, - .bdrv_co_flush_to_disk = sd_co_flush_to_disk, - .bdrv_co_pdiscard = sd_co_pdiscard, - .bdrv_co_block_status = sd_co_block_status, - - .bdrv_snapshot_create = sd_snapshot_create, - .bdrv_snapshot_goto = sd_snapshot_goto, - .bdrv_snapshot_delete = sd_snapshot_delete, - .bdrv_snapshot_list = sd_snapshot_list, - - .bdrv_save_vmstate = sd_save_vmstate, - .bdrv_load_vmstate = sd_load_vmstate, - - .bdrv_detach_aio_context = sd_detach_aio_context, - .bdrv_attach_aio_context = sd_attach_aio_context, - - .create_opts = &sd_create_opts, - .strong_runtime_opts = sd_strong_runtime_opts, -}; - -static BlockDriver bdrv_sheepdog_tcp = { - .format_name = "sheepdog", - .protocol_name = "sheepdog+tcp", - .instance_size = sizeof(BDRVSheepdogState), - .bdrv_parse_filename = sd_parse_filename, - .bdrv_file_open = sd_open, - .bdrv_reopen_prepare = sd_reopen_prepare, - .bdrv_reopen_commit = sd_reopen_commit, - .bdrv_reopen_abort = sd_reopen_abort, - .bdrv_close = sd_close, - .bdrv_co_create = sd_co_create, - .bdrv_co_create_opts = sd_co_create_opts, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - .bdrv_getlength = sd_getlength, - .bdrv_get_allocated_file_size = sd_get_allocated_file_size, - .bdrv_co_truncate = sd_co_truncate, - - .bdrv_co_readv = sd_co_readv, - .bdrv_co_writev = sd_co_writev, - .bdrv_co_flush_to_disk = sd_co_flush_to_disk, - .bdrv_co_pdiscard = sd_co_pdiscard, - .bdrv_co_block_status = sd_co_block_status, - - .bdrv_snapshot_create = sd_snapshot_create, - .bdrv_snapshot_goto = sd_snapshot_goto, - .bdrv_snapshot_delete = sd_snapshot_delete, - .bdrv_snapshot_list = sd_snapshot_list, - - .bdrv_save_vmstate = sd_save_vmstate, - .bdrv_load_vmstate = sd_load_vmstate, - - .bdrv_detach_aio_context = sd_detach_aio_context, - .bdrv_attach_aio_context = sd_attach_aio_context, - - .create_opts = &sd_create_opts, - .strong_runtime_opts = sd_strong_runtime_opts, -}; - -static BlockDriver bdrv_sheepdog_unix = { - .format_name = "sheepdog", - .protocol_name = "sheepdog+unix", - .instance_size = sizeof(BDRVSheepdogState), - .bdrv_parse_filename = sd_parse_filename, - .bdrv_file_open = sd_open, - .bdrv_reopen_prepare = sd_reopen_prepare, - .bdrv_reopen_commit = sd_reopen_commit, - .bdrv_reopen_abort = sd_reopen_abort, - .bdrv_close = sd_close, - .bdrv_co_create = sd_co_create, - .bdrv_co_create_opts = sd_co_create_opts, - .bdrv_has_zero_init = bdrv_has_zero_init_1, - .bdrv_getlength = sd_getlength, - .bdrv_get_allocated_file_size = sd_get_allocated_file_size, - .bdrv_co_truncate = sd_co_truncate, - - .bdrv_co_readv = sd_co_readv, - .bdrv_co_writev = sd_co_writev, - .bdrv_co_flush_to_disk = sd_co_flush_to_disk, - .bdrv_co_pdiscard = sd_co_pdiscard, - .bdrv_co_block_status = sd_co_block_status, - - .bdrv_snapshot_create = sd_snapshot_create, - .bdrv_snapshot_goto = sd_snapshot_goto, - .bdrv_snapshot_delete = sd_snapshot_delete, - .bdrv_snapshot_list = sd_snapshot_list, - - .bdrv_save_vmstate = sd_save_vmstate, - .bdrv_load_vmstate = sd_load_vmstate, - - .bdrv_detach_aio_context = sd_detach_aio_context, - .bdrv_attach_aio_context = sd_attach_aio_context, - - .create_opts = &sd_create_opts, - .strong_runtime_opts = sd_strong_runtime_opts, -}; - -static void bdrv_sheepdog_init(void) -{ - bdrv_register(&bdrv_sheepdog); - bdrv_register(&bdrv_sheepdog_tcp); - bdrv_register(&bdrv_sheepdog_unix); -} -block_init(bdrv_sheepdog_init); diff --git a/block/trace-events b/block/trace-events index 1a12d634e2..31062ed437 100644 --- a/block/trace-events +++ b/block/trace-events @@ -207,19 +207,5 @@ 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" -# sheepdog.c -sheepdog_reconnect_to_sdog(void) "Wait for connection to be established" -sheepdog_aio_read_response(void) "disable cache since the server doesn't support it" -sheepdog_open(uint32_t vid) "0x%" PRIx32 " snapshot inode was open" -sheepdog_close(const char *name) "%s" -sheepdog_create_branch_snapshot(uint32_t vdi) "0x%" PRIx32 " is snapshot" -sheepdog_create_branch_created(uint32_t vdi) "0x%" PRIx32 " is created" -sheepdog_create_branch_new(uint32_t vdi) "0x%" PRIx32 " was newly created" -sheepdog_co_rw_vector_update(uint32_t vdi, uint64_t oid, uint64_t data, long idx) "update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld" -sheepdog_co_rw_vector_new(uint64_t oid) "new oid 0x%" PRIx64 -sheepdog_snapshot_create_info(const char *sn_name, const char *id, const char *name, int64_t size, int is_snapshot) "sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " " "is_snapshot %d" -sheepdog_snapshot_create(const char *sn_name, const char *id) "%s %s" -sheepdog_snapshot_create_inode(const char *name, uint32_t snap, uint32_t vdi) "s->inode: name %s snap_id 0x%" PRIx32 " vdi 0x%" PRIx32 - # ssh.c sftp_error(const char *op, const char *ssh_err, int ssh_err_code, int sftp_err_code) "%s failed: %s (libssh error code: %d, sftp error code: %d)" diff --git a/block/write-threshold.c b/block/write-threshold.c index 85b78dc2a9..35cafbc22d 100644 --- a/block/write-threshold.c +++ b/block/write-threshold.c @@ -12,9 +12,7 @@ #include "qemu/osdep.h" #include "block/block_int.h" -#include "qemu/coroutine.h" #include "block/write-threshold.h" -#include "qemu/notify.h" #include "qapi/error.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-events-block-core.h" @@ -24,82 +22,9 @@ uint64_t bdrv_write_threshold_get(const BlockDriverState *bs) return bs->write_threshold_offset; } -bool bdrv_write_threshold_is_set(const BlockDriverState *bs) -{ - return bs->write_threshold_offset > 0; -} - -static void write_threshold_disable(BlockDriverState *bs) -{ - if (bdrv_write_threshold_is_set(bs)) { - notifier_with_return_remove(&bs->write_threshold_notifier); - bs->write_threshold_offset = 0; - } -} - -uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs, - const BdrvTrackedRequest *req) -{ - if (bdrv_write_threshold_is_set(bs)) { - if (req->offset > bs->write_threshold_offset) { - return (req->offset - bs->write_threshold_offset) + req->bytes; - } - if ((req->offset + req->bytes) > bs->write_threshold_offset) { - return (req->offset + req->bytes) - bs->write_threshold_offset; - } - } - return 0; -} - -static int coroutine_fn before_write_notify(NotifierWithReturn *notifier, - void *opaque) -{ - BdrvTrackedRequest *req = opaque; - BlockDriverState *bs = req->bs; - uint64_t amount = 0; - - amount = bdrv_write_threshold_exceeded(bs, req); - if (amount > 0) { - qapi_event_send_block_write_threshold( - bs->node_name, - amount, - bs->write_threshold_offset); - - /* autodisable to avoid flooding the monitor */ - write_threshold_disable(bs); - } - - return 0; /* should always let other notifiers run */ -} - -static void write_threshold_register_notifier(BlockDriverState *bs) -{ - bs->write_threshold_notifier.notify = before_write_notify; - bdrv_add_before_write_notifier(bs, &bs->write_threshold_notifier); -} - -static void write_threshold_update(BlockDriverState *bs, - int64_t threshold_bytes) -{ - bs->write_threshold_offset = threshold_bytes; -} - void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes) { - if (bdrv_write_threshold_is_set(bs)) { - if (threshold_bytes > 0) { - write_threshold_update(bs, threshold_bytes); - } else { - write_threshold_disable(bs); - } - } else { - if (threshold_bytes > 0) { - /* avoid multiple registration */ - write_threshold_register_notifier(bs); - write_threshold_update(bs, threshold_bytes); - } - /* discard bogus disable request */ - } + bs->write_threshold_offset = threshold_bytes; } void qmp_block_set_write_threshold(const char *node_name, @@ -122,3 +47,17 @@ void qmp_block_set_write_threshold(const char *node_name, aio_context_release(aio_context); } + +void bdrv_write_threshold_check_write(BlockDriverState *bs, int64_t offset, + int64_t bytes) +{ + int64_t end = offset + bytes; + uint64_t wtr = bs->write_threshold_offset; + + if (wtr > 0 && end > wtr) { + qapi_event_send_block_write_threshold(bs->node_name, end - wtr, wtr); + + /* autodisable to avoid flooding the monitor */ + bdrv_write_threshold_set(bs, 0); + } +} @@ -447,7 +447,6 @@ vdi=${default_feature:-yes} vvfat=${default_feature:-yes} qed=${default_feature:-yes} parallels=${default_feature:-yes} -sheepdog="no" libxml2="$default_feature" debug_mutex="no" libpmem="$default_feature" @@ -1478,10 +1477,6 @@ for opt do ;; --enable-parallels) parallels="yes" ;; - --disable-sheepdog) sheepdog="no" - ;; - --enable-sheepdog) sheepdog="yes" - ;; --disable-vhost-user) vhost_user="no" ;; --enable-vhost-user) vhost_user="yes" @@ -1668,7 +1663,7 @@ if [ "$ARCH" = "unknown" ]; then fi default_target_list="" -deprecated_targets_list=ppc64abi32-linux-user,lm32-softmmu,unicore32-softmmu +deprecated_targets_list=ppc64abi32-linux-user deprecated_features="" mak_wilds="" @@ -1916,7 +1911,6 @@ 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 (deprecated) crypto-afalg Linux AF_ALG crypto backend driver capstone capstone disassembler support debug-mutex mutex debugging support @@ -3623,7 +3617,7 @@ case "$fdt" in esac ########################################## -# opengl probe (for sdl2, gtk, milkymist-tmu2) +# opengl probe (for sdl2, gtk) gbm="no" if $pkg_config gbm; then @@ -6108,10 +6102,6 @@ fi 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 "$have_mlockall" = "yes" ; then echo "HAVE_MLOCKALL=y" >> $config_host_mak fi @@ -6286,14 +6276,13 @@ fi # 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="tests tests/tcg 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" DIRS="$DIRS contrib/plugins/" LINKS="Makefile" -LINKS="$LINKS tests/tcg/lm32/Makefile" LINKS="$LINKS tests/tcg/Makefile.target" LINKS="$LINKS pc-bios/optionrom/Makefile" LINKS="$LINKS pc-bios/s390-ccw/Makefile" @@ -6484,6 +6473,13 @@ if test -n "${deprecated_features}"; then echo " features: ${deprecated_features}" fi +# Create list of config switches that should be poisoned in common code... +# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special. +sed -n -e '/CONFIG_TCG/d' -e '/CONFIG_USER_ONLY/d' \ + -e '/^#define / { s///; s/ .*//; s/^/#pragma GCC poison /p; }' \ + *-config-devices.h *-config-target.h | \ + sort -u > config-poison.h + # Save the configure command line for later reuse. cat <<EOD >config.status #!/bin/sh diff --git a/contrib/vhost-user-input/main.c b/contrib/vhost-user-input/main.c index c15d18c33f..081230da54 100644 --- a/contrib/vhost-user-input/main.c +++ b/contrib/vhost-user-input/main.c @@ -6,12 +6,13 @@ #include "qemu/osdep.h" -#include <linux/input.h> +#include <sys/ioctl.h> #include "qemu/iov.h" #include "qemu/bswap.h" #include "qemu/sockets.h" #include "libvhost-user-glib.h" +#include "standard-headers/linux/input.h" #include "standard-headers/linux/virtio_input.h" #include "qapi/error.h" @@ -113,13 +114,16 @@ vi_evdev_watch(VuDev *dev, int condition, void *data) static void vi_handle_status(VuInput *vi, virtio_input_event *event) { struct input_event evdev; + struct timeval tval; int rc; - if (gettimeofday(&evdev.time, NULL)) { + if (gettimeofday(&tval, NULL)) { perror("vi_handle_status: gettimeofday"); return; } + evdev.input_event_sec = tval.tv_sec; + evdev.input_event_usec = tval.tv_usec; evdev.type = le16toh(event->type); evdev.code = le16toh(event->code); evdev.value = le32toh(event->value); diff --git a/default-configs/devices/lm32-softmmu.mak b/default-configs/devices/lm32-softmmu.mak deleted file mode 100644 index 1bce3f6e8b..0000000000 --- a/default-configs/devices/lm32-softmmu.mak +++ /dev/null @@ -1,12 +0,0 @@ -# Default configuration for lm32-softmmu - -# Uncomment the following lines to disable these optional devices: -# -#CONFIG_MILKYMIST_TMU2=n # disabling it actually causes compile-time failures - -CONFIG_SEMIHOSTING=y - -# Boards: -# -CONFIG_LM32_EVR=y -CONFIG_MILKYMIST=y diff --git a/default-configs/devices/moxie-softmmu.mak b/default-configs/devices/moxie-softmmu.mak deleted file mode 100644 index bd50da3c58..0000000000 --- a/default-configs/devices/moxie-softmmu.mak +++ /dev/null @@ -1,5 +0,0 @@ -# Default configuration for moxie-softmmu - -# Boards: -# -CONFIG_MOXIESIM=y diff --git a/default-configs/devices/unicore32-softmmu.mak b/default-configs/devices/unicore32-softmmu.mak deleted file mode 100644 index 899288e3d7..0000000000 --- a/default-configs/devices/unicore32-softmmu.mak +++ /dev/null @@ -1,6 +0,0 @@ -# Default configuration for unicore32-softmmu - -# Boards: -# -CONFIG_PUV3=y -CONFIG_SEMIHOSTING=y diff --git a/default-configs/targets/lm32-softmmu.mak b/default-configs/targets/lm32-softmmu.mak deleted file mode 100644 index 55e7184a3d..0000000000 --- a/default-configs/targets/lm32-softmmu.mak +++ /dev/null @@ -1,2 +0,0 @@ -TARGET_ARCH=lm32 -TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/moxie-softmmu.mak b/default-configs/targets/moxie-softmmu.mak deleted file mode 100644 index 183e6b0ebd..0000000000 --- a/default-configs/targets/moxie-softmmu.mak +++ /dev/null @@ -1,2 +0,0 @@ -TARGET_ARCH=moxie -TARGET_WORDS_BIGENDIAN=y diff --git a/default-configs/targets/unicore32-softmmu.mak b/default-configs/targets/unicore32-softmmu.mak deleted file mode 100644 index 57331e94fe..0000000000 --- a/default-configs/targets/unicore32-softmmu.mak +++ /dev/null @@ -1 +0,0 @@ -TARGET_ARCH=unicore32 diff --git a/disas/lm32.c b/disas/lm32.c deleted file mode 100644 index 4fbb124534..0000000000 --- a/disas/lm32.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Simple LatticeMico32 disassembler. - * - * Copyright (c) 2012 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - */ - -#include "qemu/osdep.h" -#include "disas/dis-asm.h" - -typedef enum { - LM32_OP_SRUI = 0, LM32_OP_NORI, LM32_OP_MULI, LM32_OP_SH, LM32_OP_LB, - LM32_OP_SRI, LM32_OP_XORI, LM32_OP_LH, LM32_OP_ANDI, LM32_OP_XNORI, - LM32_OP_LW, LM32_OP_LHU, LM32_OP_SB, LM32_OP_ADDI, LM32_OP_ORI, - LM32_OP_SLI, LM32_OP_LBU, LM32_OP_BE, LM32_OP_BG, LM32_OP_BGE, - LM32_OP_BGEU, LM32_OP_BGU, LM32_OP_SW, LM32_OP_BNE, LM32_OP_ANDHI, - LM32_OP_CMPEI, LM32_OP_CMPGI, LM32_OP_CMPGEI, LM32_OP_CMPGEUI, - LM32_OP_CMPGUI, LM32_OP_ORHI, LM32_OP_CMPNEI, LM32_OP_SRU, LM32_OP_NOR, - LM32_OP_MUL, LM32_OP_DIVU, LM32_OP_RCSR, LM32_OP_SR, LM32_OP_XOR, - LM32_OP_ILL0, LM32_OP_AND, LM32_OP_XNOR, LM32_OP_ILL1, LM32_OP_SCALL, - LM32_OP_SEXTB, LM32_OP_ADD, LM32_OP_OR, LM32_OP_SL, LM32_OP_B, - LM32_OP_MODU, LM32_OP_SUB, LM32_OP_ILL2, LM32_OP_WCSR, LM32_OP_ILL3, - LM32_OP_CALL, LM32_OP_SEXTH, LM32_OP_BI, LM32_OP_CMPE, LM32_OP_CMPG, - LM32_OP_CMPGE, LM32_OP_CMPGEU, LM32_OP_CMPGU, LM32_OP_CALLI, LM32_OP_CMPNE, -} Lm32Opcode; - -typedef enum { - FMT_INVALID = 0, FMT_RRI5, FMT_RRI16, FMT_IMM26, FMT_LOAD, FMT_STORE, - FMT_RRR, FMT_R, FMT_RNR, FMT_CRN, FMT_CNR, FMT_BREAK, -} Lm32OpcodeFmt; - -typedef enum { - LM32_CSR_IE = 0, LM32_CSR_IM, LM32_CSR_IP, LM32_CSR_ICC, LM32_CSR_DCC, - LM32_CSR_CC, LM32_CSR_CFG, LM32_CSR_EBA, LM32_CSR_DC, LM32_CSR_DEBA, - LM32_CSR_CFG2, LM32_CSR_JTX = 0xe, LM32_CSR_JRX, LM32_CSR_BP0, - LM32_CSR_BP1, LM32_CSR_BP2, LM32_CSR_BP3, LM32_CSR_WP0 = 0x18, - LM32_CSR_WP1, LM32_CSR_WP2, LM32_CSR_WP3, -} Lm32CsrNum; - -typedef struct { - int csr; - const char *name; -} Lm32CsrInfo; - -static const Lm32CsrInfo lm32_csr_info[] = { - {LM32_CSR_IE, "ie", }, - {LM32_CSR_IM, "im", }, - {LM32_CSR_IP, "ip", }, - {LM32_CSR_ICC, "icc", }, - {LM32_CSR_DCC, "dcc", }, - {LM32_CSR_CC, "cc", }, - {LM32_CSR_CFG, "cfg", }, - {LM32_CSR_EBA, "eba", }, - {LM32_CSR_DC, "dc", }, - {LM32_CSR_DEBA, "deba", }, - {LM32_CSR_CFG2, "cfg2", }, - {LM32_CSR_JTX, "jtx", }, - {LM32_CSR_JRX, "jrx", }, - {LM32_CSR_BP0, "bp0", }, - {LM32_CSR_BP1, "bp1", }, - {LM32_CSR_BP2, "bp2", }, - {LM32_CSR_BP3, "bp3", }, - {LM32_CSR_WP0, "wp0", }, - {LM32_CSR_WP1, "wp1", }, - {LM32_CSR_WP2, "wp2", }, - {LM32_CSR_WP3, "wp3", }, -}; - -static const Lm32CsrInfo *find_csr_info(int csr) -{ - const Lm32CsrInfo *info; - int i; - - for (i = 0; i < ARRAY_SIZE(lm32_csr_info); i++) { - info = &lm32_csr_info[i]; - if (csr == info->csr) { - return info; - } - } - - return NULL; -} - -typedef struct { - int reg; - const char *name; -} Lm32RegInfo; - -typedef enum { - LM32_REG_R0 = 0, LM32_REG_R1, LM32_REG_R2, LM32_REG_R3, LM32_REG_R4, - LM32_REG_R5, LM32_REG_R6, LM32_REG_R7, LM32_REG_R8, LM32_REG_R9, - LM32_REG_R10, LM32_REG_R11, LM32_REG_R12, LM32_REG_R13, LM32_REG_R14, - LM32_REG_R15, LM32_REG_R16, LM32_REG_R17, LM32_REG_R18, LM32_REG_R19, - LM32_REG_R20, LM32_REG_R21, LM32_REG_R22, LM32_REG_R23, LM32_REG_R24, - LM32_REG_R25, LM32_REG_GP, LM32_REG_FP, LM32_REG_SP, LM32_REG_RA, - LM32_REG_EA, LM32_REG_BA, -} Lm32RegNum; - -static const Lm32RegInfo lm32_reg_info[] = { - {LM32_REG_R0, "r0", }, - {LM32_REG_R1, "r1", }, - {LM32_REG_R2, "r2", }, - {LM32_REG_R3, "r3", }, - {LM32_REG_R4, "r4", }, - {LM32_REG_R5, "r5", }, - {LM32_REG_R6, "r6", }, - {LM32_REG_R7, "r7", }, - {LM32_REG_R8, "r8", }, - {LM32_REG_R9, "r9", }, - {LM32_REG_R10, "r10", }, - {LM32_REG_R11, "r11", }, - {LM32_REG_R12, "r12", }, - {LM32_REG_R13, "r13", }, - {LM32_REG_R14, "r14", }, - {LM32_REG_R15, "r15", }, - {LM32_REG_R16, "r16", }, - {LM32_REG_R17, "r17", }, - {LM32_REG_R18, "r18", }, - {LM32_REG_R19, "r19", }, - {LM32_REG_R20, "r20", }, - {LM32_REG_R21, "r21", }, - {LM32_REG_R22, "r22", }, - {LM32_REG_R23, "r23", }, - {LM32_REG_R24, "r24", }, - {LM32_REG_R25, "r25", }, - {LM32_REG_GP, "gp", }, - {LM32_REG_FP, "fp", }, - {LM32_REG_SP, "sp", }, - {LM32_REG_RA, "ra", }, - {LM32_REG_EA, "ea", }, - {LM32_REG_BA, "ba", }, -}; - -static const Lm32RegInfo *find_reg_info(int reg) -{ - assert(ARRAY_SIZE(lm32_reg_info) == 32); - return &lm32_reg_info[reg & 0x1f]; -} - -typedef struct { - struct { - uint32_t code; - uint32_t mask; - } op; - const char *name; - const char *args_fmt; -} Lm32OpcodeInfo; - -static const Lm32OpcodeInfo lm32_opcode_info[] = { - /* pseudo instructions */ - {{0x34000000, 0xffffffff}, "nop", NULL}, - {{0xac000002, 0xffffffff}, "break", NULL}, - {{0xac000003, 0xffffffff}, "scall", NULL}, - {{0xc3e00000, 0xffffffff}, "bret", NULL}, - {{0xc3c00000, 0xffffffff}, "eret", NULL}, - {{0xc3a00000, 0xffffffff}, "ret", NULL}, - {{0xa4000000, 0xfc1f07ff}, "not", "%2, %0"}, - {{0xb8000000, 0xfc1f07ff}, "mv", "%2, %0"}, - {{0x71e00000, 0xffe00000}, "mvhi", "%1, %u"}, - {{0x34000000, 0xffe00000}, "mvi", "%1, %s"}, - -#define _O(op) {op << 26, 0x3f << 26} - /* regular opcodes */ - {_O(LM32_OP_ADD), "add", "%2, %0, %1" }, - {_O(LM32_OP_ADDI), "addi", "%1, %0, %s" }, - {_O(LM32_OP_AND), "and", "%2, %0, %1" }, - {_O(LM32_OP_ANDHI), "andhi", "%1, %0, %u" }, - {_O(LM32_OP_ANDI), "andi", "%1, %0, %u" }, - {_O(LM32_OP_B), "b", "%0", }, - {_O(LM32_OP_BE), "be", "%1, %0, %r" }, - {_O(LM32_OP_BG), "bg", "%1, %0, %r" }, - {_O(LM32_OP_BGE), "bge", "%1, %0, %r" }, - {_O(LM32_OP_BGEU), "bgeu", "%1, %0, %r" }, - {_O(LM32_OP_BGU), "bgu", "%1, %0, %r" }, - {_O(LM32_OP_BI), "bi", "%R", }, - {_O(LM32_OP_BNE), "bne", "%1, %0, %r" }, - {_O(LM32_OP_CALL), "call", "%0", }, - {_O(LM32_OP_CALLI), "calli", "%R", }, - {_O(LM32_OP_CMPE), "cmpe", "%2, %0, %1" }, - {_O(LM32_OP_CMPEI), "cmpei", "%1, %0, %s" }, - {_O(LM32_OP_CMPG), "cmpg", "%2, %0, %1" }, - {_O(LM32_OP_CMPGE), "cmpge", "%2, %0, %1" }, - {_O(LM32_OP_CMPGEI), "cmpgei", "%1, %0, %s" }, - {_O(LM32_OP_CMPGEU), "cmpgeu", "%2, %0, %1" }, - {_O(LM32_OP_CMPGEUI), "cmpgeui", "%1, %0, %s" }, - {_O(LM32_OP_CMPGI), "cmpgi", "%1, %0, %s" }, - {_O(LM32_OP_CMPGU), "cmpgu", "%2, %0, %1" }, - {_O(LM32_OP_CMPGUI), "cmpgui", "%1, %0, %s" }, - {_O(LM32_OP_CMPNE), "cmpne", "%2, %0, %1" }, - {_O(LM32_OP_CMPNEI), "cmpnei", "%1, %0, %s" }, - {_O(LM32_OP_DIVU), "divu", "%2, %0, %1" }, - {_O(LM32_OP_LB), "lb", "%1, (%0+%s)" }, - {_O(LM32_OP_LBU), "lbu", "%1, (%0+%s)" }, - {_O(LM32_OP_LH), "lh", "%1, (%0+%s)" }, - {_O(LM32_OP_LHU), "lhu", "%1, (%0+%s)" }, - {_O(LM32_OP_LW), "lw", "%1, (%0+%s)" }, - {_O(LM32_OP_MODU), "modu", "%2, %0, %1" }, - {_O(LM32_OP_MULI), "muli", "%1, %0, %s" }, - {_O(LM32_OP_MUL), "mul", "%2, %0, %1" }, - {_O(LM32_OP_NORI), "nori", "%1, %0, %u" }, - {_O(LM32_OP_NOR), "nor", "%2, %0, %1" }, - {_O(LM32_OP_ORHI), "orhi", "%1, %0, %u" }, - {_O(LM32_OP_ORI), "ori", "%1, %0, %u" }, - {_O(LM32_OP_OR), "or", "%2, %0, %1" }, - {_O(LM32_OP_RCSR), "rcsr", "%2, %c", }, - {_O(LM32_OP_SB), "sb", "(%0+%s), %1" }, - {_O(LM32_OP_SEXTB), "sextb", "%2, %0", }, - {_O(LM32_OP_SEXTH), "sexth", "%2, %0", }, - {_O(LM32_OP_SH), "sh", "(%0+%s), %1" }, - {_O(LM32_OP_SLI), "sli", "%1, %0, %h" }, - {_O(LM32_OP_SL), "sl", "%2, %0, %1" }, - {_O(LM32_OP_SRI), "sri", "%1, %0, %h" }, - {_O(LM32_OP_SR), "sr", "%2, %0, %1" }, - {_O(LM32_OP_SRUI), "srui", "%1, %0, %d" }, - {_O(LM32_OP_SRU), "sru", "%2, %0, %s" }, - {_O(LM32_OP_SUB), "sub", "%2, %0, %s" }, - {_O(LM32_OP_SW), "sw", "(%0+%s), %1" }, - {_O(LM32_OP_WCSR), "wcsr", "%c, %1", }, - {_O(LM32_OP_XNORI), "xnori", "%1, %0, %u" }, - {_O(LM32_OP_XNOR), "xnor", "%2, %0, %1" }, - {_O(LM32_OP_XORI), "xori", "%1, %0, %u" }, - {_O(LM32_OP_XOR), "xor", "%2, %0, %1" }, -#undef _O -}; - -static const Lm32OpcodeInfo *find_opcode_info(uint32_t opcode) -{ - const Lm32OpcodeInfo *info; - int i; - for (i = 0; i < ARRAY_SIZE(lm32_opcode_info); i++) { - info = &lm32_opcode_info[i]; - if ((opcode & info->op.mask) == info->op.code) { - return info; - } - } - - return NULL; -} - -int print_insn_lm32(bfd_vma memaddr, struct disassemble_info *info) -{ - fprintf_function fprintf_fn = info->fprintf_func; - void *stream = info->stream; - int rc; - uint8_t insn[4]; - const Lm32OpcodeInfo *opc_info; - uint32_t op; - const char *args_fmt; - - rc = info->read_memory_func(memaddr, insn, 4, info); - if (rc != 0) { - info->memory_error_func(rc, memaddr, info); - return -1; - } - - fprintf_fn(stream, "%02x %02x %02x %02x ", - insn[0], insn[1], insn[2], insn[3]); - - op = bfd_getb32(insn); - opc_info = find_opcode_info(op); - if (opc_info) { - fprintf_fn(stream, "%-8s ", opc_info->name); - args_fmt = opc_info->args_fmt; - while (args_fmt && *args_fmt) { - if (*args_fmt == '%') { - switch (*(++args_fmt)) { - case '0': { - uint8_t r0; - const char *r0_name; - r0 = (op >> 21) & 0x1f; - r0_name = find_reg_info(r0)->name; - fprintf_fn(stream, "%s", r0_name); - break; - } - case '1': { - uint8_t r1; - const char *r1_name; - r1 = (op >> 16) & 0x1f; - r1_name = find_reg_info(r1)->name; - fprintf_fn(stream, "%s", r1_name); - break; - } - case '2': { - uint8_t r2; - const char *r2_name; - r2 = (op >> 11) & 0x1f; - r2_name = find_reg_info(r2)->name; - fprintf_fn(stream, "%s", r2_name); - break; - } - case 'c': { - uint8_t csr; - const Lm32CsrInfo *info; - csr = (op >> 21) & 0x1f; - info = find_csr_info(csr); - if (info) { - fprintf_fn(stream, "%s", info->name); - } else { - fprintf_fn(stream, "0x%x", csr); - } - break; - } - case 'u': { - uint16_t u16; - u16 = op & 0xffff; - fprintf_fn(stream, "0x%x", u16); - break; - } - case 's': { - int16_t s16; - s16 = (int16_t)(op & 0xffff); - fprintf_fn(stream, "%d", s16); - break; - } - case 'r': { - uint32_t rela; - rela = memaddr + (((int16_t)(op & 0xffff)) << 2); - fprintf_fn(stream, "%x", rela); - break; - } - case 'R': { - uint32_t rela; - int32_t imm26; - imm26 = (int32_t)((op & 0x3ffffff) << 6) >> 4; - rela = memaddr + imm26; - fprintf_fn(stream, "%x", rela); - break; - } - case 'h': { - uint8_t u5; - u5 = (op & 0x1f); - fprintf_fn(stream, "%d", u5); - break; - } - default: - break; - } - } else { - fprintf_fn(stream, "%c", *args_fmt); - } - args_fmt++; - } - } else { - fprintf_fn(stream, ".word 0x%x", op); - } - - return 4; -} diff --git a/disas/meson.build b/disas/meson.build index 4c8da01877..449f99e1de 100644 --- a/disas/meson.build +++ b/disas/meson.build @@ -9,11 +9,9 @@ common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c')) common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.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')) diff --git a/disas/moxie.c b/disas/moxie.c deleted file mode 100644 index e94ab4c33d..0000000000 --- a/disas/moxie.c +++ /dev/null @@ -1,360 +0,0 @@ -/* Disassemble moxie instructions. - Copyright (c) 2009 Free Software Foundation, 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 <http://www.gnu.org/licenses/>. */ - -#include "qemu/osdep.h" -#define STATIC_TABLE -#define DEFINE_TABLE - -#include "disas/dis-asm.h" - -static void *stream; - -/* Form 1 instructions come in different flavors: - - Some have no arguments (MOXIE_F1_NARG) - Some only use the A operand (MOXIE_F1_A) - Some use A and B registers (MOXIE_F1_AB) - Some use A and consume a 4 byte immediate value (MOXIE_F1_A4) - Some use just a 4 byte immediate value (MOXIE_F1_4) - Some use just a 4 byte memory address (MOXIE_F1_M) - Some use B and an indirect A (MOXIE_F1_AiB) - Some use A and an indirect B (MOXIE_F1_ABi) - Some consume a 4 byte immediate value and use X (MOXIE_F1_4A) - Some use B and an indirect A plus 4 bytes (MOXIE_F1_AiB4) - Some use A and an indirect B plus 4 bytes (MOXIE_F1_ABi4) - - Form 2 instructions also come in different flavors: - - Some have no arguments (MOXIE_F2_NARG) - Some use the A register and an 8-bit value (MOXIE_F2_A8V) - - Form 3 instructions also come in different flavors: - - Some have no arguments (MOXIE_F3_NARG) - Some have a 10-bit PC relative operand (MOXIE_F3_PCREL). */ - -#define MOXIE_F1_NARG 0x100 -#define MOXIE_F1_A 0x101 -#define MOXIE_F1_AB 0x102 -/* #define MOXIE_F1_ABC 0x103 */ -#define MOXIE_F1_A4 0x104 -#define MOXIE_F1_4 0x105 -#define MOXIE_F1_AiB 0x106 -#define MOXIE_F1_ABi 0x107 -#define MOXIE_F1_4A 0x108 -#define MOXIE_F1_AiB4 0x109 -#define MOXIE_F1_ABi4 0x10a -#define MOXIE_F1_M 0x10b - -#define MOXIE_F2_NARG 0x200 -#define MOXIE_F2_A8V 0x201 - -#define MOXIE_F3_NARG 0x300 -#define MOXIE_F3_PCREL 0x301 - -typedef struct moxie_opc_info_t { - short opcode; - unsigned itype; - const char * name; -} moxie_opc_info_t; - -extern const moxie_opc_info_t moxie_form1_opc_info[64]; -extern const moxie_opc_info_t moxie_form2_opc_info[4]; -extern const moxie_opc_info_t moxie_form3_opc_info[16]; - -/* The moxie processor's 16-bit instructions come in two forms: - - FORM 1 instructions start with a 0 bit... - - 0oooooooaaaabbbb - 0 F - - ooooooo - form 1 opcode number - aaaa - operand A - bbbb - operand B - - FORM 2 instructions start with bits "10"... - - 10ooaaaavvvvvvvv - 0 F - - oo - form 2 opcode number - aaaa - operand A - vvvvvvvv - 8-bit immediate value - - FORM 3 instructions start with a bits "11"... - - 11oooovvvvvvvvvv - 0 F - - oooo - form 3 opcode number - vvvvvvvvvv - 10-bit immediate value. */ - -const moxie_opc_info_t moxie_form1_opc_info[64] = - { - { 0x00, MOXIE_F1_NARG, "nop" }, - { 0x01, MOXIE_F1_A4, "ldi.l" }, - { 0x02, MOXIE_F1_AB, "mov" }, - { 0x03, MOXIE_F1_M, "jsra" }, - { 0x04, MOXIE_F1_NARG, "ret" }, - { 0x05, MOXIE_F1_AB, "add.l" }, - { 0x06, MOXIE_F1_AB, "push" }, - { 0x07, MOXIE_F1_AB, "pop" }, - { 0x08, MOXIE_F1_A4, "lda.l" }, - { 0x09, MOXIE_F1_4A, "sta.l" }, - { 0x0a, MOXIE_F1_ABi, "ld.l" }, - { 0x0b, MOXIE_F1_AiB, "st.l" }, - { 0x0c, MOXIE_F1_ABi4, "ldo.l" }, - { 0x0d, MOXIE_F1_AiB4, "sto.l" }, - { 0x0e, MOXIE_F1_AB, "cmp" }, - { 0x0f, MOXIE_F1_NARG, "bad" }, - { 0x10, MOXIE_F1_NARG, "bad" }, - { 0x11, MOXIE_F1_NARG, "bad" }, - { 0x12, MOXIE_F1_NARG, "bad" }, - { 0x13, MOXIE_F1_NARG, "bad" }, - { 0x14, MOXIE_F1_NARG, "bad" }, - { 0x15, MOXIE_F1_NARG, "bad" }, - { 0x16, MOXIE_F1_NARG, "bad" }, - { 0x17, MOXIE_F1_NARG, "bad" }, - { 0x18, MOXIE_F1_NARG, "bad" }, - { 0x19, MOXIE_F1_A, "jsr" }, - { 0x1a, MOXIE_F1_M, "jmpa" }, - { 0x1b, MOXIE_F1_A4, "ldi.b" }, - { 0x1c, MOXIE_F1_ABi, "ld.b" }, - { 0x1d, MOXIE_F1_A4, "lda.b" }, - { 0x1e, MOXIE_F1_AiB, "st.b" }, - { 0x1f, MOXIE_F1_4A, "sta.b" }, - { 0x20, MOXIE_F1_A4, "ldi.s" }, - { 0x21, MOXIE_F1_ABi, "ld.s" }, - { 0x22, MOXIE_F1_A4, "lda.s" }, - { 0x23, MOXIE_F1_AiB, "st.s" }, - { 0x24, MOXIE_F1_4A, "sta.s" }, - { 0x25, MOXIE_F1_A, "jmp" }, - { 0x26, MOXIE_F1_AB, "and" }, - { 0x27, MOXIE_F1_AB, "lshr" }, - { 0x28, MOXIE_F1_AB, "ashl" }, - { 0x29, MOXIE_F1_AB, "sub.l" }, - { 0x2a, MOXIE_F1_AB, "neg" }, - { 0x2b, MOXIE_F1_AB, "or" }, - { 0x2c, MOXIE_F1_AB, "not" }, - { 0x2d, MOXIE_F1_AB, "ashr" }, - { 0x2e, MOXIE_F1_AB, "xor" }, - { 0x2f, MOXIE_F1_AB, "mul.l" }, - { 0x30, MOXIE_F1_4, "swi" }, - { 0x31, MOXIE_F1_AB, "div.l" }, - { 0x32, MOXIE_F1_AB, "udiv.l" }, - { 0x33, MOXIE_F1_AB, "mod.l" }, - { 0x34, MOXIE_F1_AB, "umod.l" }, - { 0x35, MOXIE_F1_NARG, "brk" }, - { 0x36, MOXIE_F1_ABi4, "ldo.b" }, - { 0x37, MOXIE_F1_AiB4, "sto.b" }, - { 0x38, MOXIE_F1_ABi4, "ldo.s" }, - { 0x39, MOXIE_F1_AiB4, "sto.s" }, - { 0x3a, MOXIE_F1_NARG, "bad" }, - { 0x3b, MOXIE_F1_NARG, "bad" }, - { 0x3c, MOXIE_F1_NARG, "bad" }, - { 0x3d, MOXIE_F1_NARG, "bad" }, - { 0x3e, MOXIE_F1_NARG, "bad" }, - { 0x3f, MOXIE_F1_NARG, "bad" } - }; - -const moxie_opc_info_t moxie_form2_opc_info[4] = - { - { 0x00, MOXIE_F2_A8V, "inc" }, - { 0x01, MOXIE_F2_A8V, "dec" }, - { 0x02, MOXIE_F2_A8V, "gsr" }, - { 0x03, MOXIE_F2_A8V, "ssr" } - }; - -const moxie_opc_info_t moxie_form3_opc_info[16] = - { - { 0x00, MOXIE_F3_PCREL,"beq" }, - { 0x01, MOXIE_F3_PCREL,"bne" }, - { 0x02, MOXIE_F3_PCREL,"blt" }, - { 0x03, MOXIE_F3_PCREL,"bgt" }, - { 0x04, MOXIE_F3_PCREL,"bltu" }, - { 0x05, MOXIE_F3_PCREL,"bgtu" }, - { 0x06, MOXIE_F3_PCREL,"bge" }, - { 0x07, MOXIE_F3_PCREL,"ble" }, - { 0x08, MOXIE_F3_PCREL,"bgeu" }, - { 0x09, MOXIE_F3_PCREL,"bleu" }, - { 0x0a, MOXIE_F3_NARG, "bad" }, - { 0x0b, MOXIE_F3_NARG, "bad" }, - { 0x0c, MOXIE_F3_NARG, "bad" }, - { 0x0d, MOXIE_F3_NARG, "bad" }, - { 0x0e, MOXIE_F3_NARG, "bad" }, - { 0x0f, MOXIE_F3_NARG, "bad" } - }; - -/* Macros to extract operands from the instruction word. */ -#define OP_A(i) ((i >> 4) & 0xf) -#define OP_B(i) (i & 0xf) -#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) - -static const char * reg_names[16] = - { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", - "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; - -int -print_insn_moxie(bfd_vma addr, struct disassemble_info * info) -{ - int length = 2; - int status; - stream = info->stream; - const moxie_opc_info_t * opcode; - bfd_byte buffer[4]; - unsigned short iword; - fprintf_function fpr = info->fprintf_func; - - if ((status = info->read_memory_func(addr, buffer, 2, info))) - goto fail; - iword = (bfd_getb16(buffer) >> 16); - - /* Form 1 instructions have the high bit set to 0. */ - if ((iword & (1<<15)) == 0) { - /* Extract the Form 1 opcode. */ - opcode = &moxie_form1_opc_info[iword >> 8]; - switch (opcode->itype) { - case MOXIE_F1_NARG: - fpr(stream, "%s", opcode->name); - break; - case MOXIE_F1_A: - fpr(stream, "%s\t%s", opcode->name, - reg_names[OP_A(iword)]); - break; - case MOXIE_F1_AB: - fpr(stream, "%s\t%s, %s", opcode->name, - reg_names[OP_A(iword)], - reg_names[OP_B(iword)]); - break; - case MOXIE_F1_A4: - { - unsigned imm; - if ((status = info->read_memory_func(addr + 2, buffer, 4, info))) - goto fail; - imm = bfd_getb32(buffer); - fpr(stream, "%s\t%s, 0x%x", opcode->name, - reg_names[OP_A(iword)], imm); - length = 6; - } - break; - case MOXIE_F1_4: - { - unsigned imm; - if ((status = info->read_memory_func(addr + 2, buffer, 4, info))) - goto fail; - imm = bfd_getb32(buffer); - fpr(stream, "%s\t0x%x", opcode->name, imm); - length = 6; - } - break; - case MOXIE_F1_M: - { - unsigned imm; - if ((status = info->read_memory_func(addr + 2, buffer, 4, info))) - goto fail; - imm = bfd_getb32(buffer); - fpr(stream, "%s\t", opcode->name); - info->print_address_func((bfd_vma) imm, info); - length = 6; - } - break; - case MOXIE_F1_AiB: - fpr (stream, "%s\t(%s), %s", opcode->name, - reg_names[OP_A(iword)], reg_names[OP_B(iword)]); - break; - case MOXIE_F1_ABi: - fpr(stream, "%s\t%s, (%s)", opcode->name, - reg_names[OP_A(iword)], reg_names[OP_B(iword)]); - break; - case MOXIE_F1_4A: - { - unsigned imm; - if ((status = info->read_memory_func(addr + 2, buffer, 4, info))) - goto fail; - imm = bfd_getb32(buffer); - fpr(stream, "%s\t0x%x, %s", - opcode->name, imm, reg_names[OP_A(iword)]); - length = 6; - } - break; - case MOXIE_F1_AiB4: - { - unsigned imm; - if ((status = info->read_memory_func(addr+2, buffer, 4, info))) - goto fail; - imm = bfd_getb32(buffer); - fpr(stream, "%s\t0x%x(%s), %s", opcode->name, - imm, - reg_names[OP_A(iword)], - reg_names[OP_B(iword)]); - length = 6; - } - break; - case MOXIE_F1_ABi4: - { - unsigned imm; - if ((status = info->read_memory_func(addr+2, buffer, 4, info))) - goto fail; - imm = bfd_getb32(buffer); - fpr(stream, "%s\t%s, 0x%x(%s)", - opcode->name, - reg_names[OP_A(iword)], - imm, - reg_names[OP_B(iword)]); - length = 6; - } - break; - default: - abort(); - } - } - else if ((iword & (1<<14)) == 0) { - /* Extract the Form 2 opcode. */ - opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; - switch (opcode->itype) { - case MOXIE_F2_A8V: - fpr(stream, "%s\t%s, 0x%x", - opcode->name, - reg_names[(iword >> 8) & 0xf], - iword & ((1 << 8) - 1)); - break; - case MOXIE_F2_NARG: - fpr(stream, "%s", opcode->name); - break; - default: - abort(); - } - } else { - /* Extract the Form 3 opcode. */ - opcode = &moxie_form3_opc_info[(iword >> 10) & 15]; - switch (opcode->itype) { - case MOXIE_F3_PCREL: - fpr(stream, "%s\t", opcode->name); - info->print_address_func((bfd_vma) (addr + INST2OFFSET(iword) + 2), - info); - break; - default: - abort(); - } - } - - return length; - - fail: - info->memory_error_func(status, addr, info); - return -1; -} diff --git a/docs/_templates/editpage.html b/docs/_templates/editpage.html deleted file mode 100644 index 4319b0f5ac..0000000000 --- a/docs/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/docs/conf.py b/docs/conf.py index 2ee6111872..00cf66ab54 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,6 +29,7 @@ import os import sys import sphinx +from distutils.version import LooseVersion from sphinx.errors import ConfigError # Make Sphinx fail cleanly if using an old Python, rather than obscurely @@ -150,38 +151,47 @@ with open(os.path.join(qemu_docdir, 'defs.rst.inc')) as f: # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +try: + import sphinx_rtd_theme +except ImportError: + raise ConfigError( + 'The Sphinx \'sphinx_rtd_theme\' HTML theme was not found.\n' + ) + +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -# We initialize this to empty here, so the per-manual conf.py can just -# add individual key/value entries. -html_theme_options = { -} +if LooseVersion(sphinx_rtd_theme.__version__) >= LooseVersion("0.4.3"): + html_theme_options = { + "style_nav_header_background": "#802400", + } + +html_logo = os.path.join(qemu_docdir, "../ui/icons/qemu_128x128.png") + +html_favicon = os.path.join(qemu_docdir, "../ui/icons/qemu_32x32.png") # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -# QEMU doesn't yet have any static files, so comment this out so we don't -# get a warning about a missing directory. -# If we do ever add this then it would probably be better to call the -# subdirectory sphinx_static, as the Linux kernel does. -# html_static_path = ['_static'] +html_static_path = [os.path.join(qemu_docdir, "sphinx-static")] + +html_css_files = [ + 'theme_overrides.css', +] + +html_context = { + "display_gitlab": True, + "gitlab_user": "qemu-project", + "gitlab_repo": "qemu", + "gitlab_version": "master", + "conf_py_path": "/docs/", # Path in the checkout to the docs root +} # Custom sidebar templates, must be a dictionary that maps document names # to template names. -# -# This is required for the alabaster theme -# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'about.html', - 'editpage.html', - 'navigation.html', - 'searchbox.html', - ] -} +#html_sidebars = {} # Don't copy the rST source files to the HTML output directory, # and don't put links to the sources into the output HTML. diff --git a/docs/devel/_templates/editpage.html b/docs/devel/_templates/editpage.html deleted file mode 100644 index a86d22bca8..0000000000 --- a/docs/devel/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/devel/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/docs/devel/qgraph.rst b/docs/devel/qgraph.rst index a9aff167ad..318534d4b0 100644 --- a/docs/devel/qgraph.rst +++ b/docs/devel/qgraph.rst @@ -92,6 +92,64 @@ The basic framework steps are the following: Depending on the QEMU binary used, only some drivers/machines will be available and only test that are reached by them will be executed. +Troubleshooting unavailable tests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If there is no path from an available machine to a test then that test will be +unavailable and won't execute. This can happen if a test or driver did not set +up its qgraph node correctly. It can also happen if the necessary machine type +or device is missing from the QEMU binary because it was compiled out or +otherwise. + +It is possible to troubleshoot unavailable tests by running:: + + $ QTEST_QEMU_BINARY=build/qemu-system-x86_64 build/tests/qtest/qos-test --verbose + # ALL QGRAPH EDGES: { + # src='virtio-net' + # |-> dest='virtio-net-tests/vhost-user/multiqueue' type=2 (node=0x559142109e30) + # |-> dest='virtio-net-tests/vhost-user/migrate' type=2 (node=0x559142109d00) + # src='virtio-net-pci' + # |-> dest='virtio-net' type=1 (node=0x55914210d740) + # src='pci-bus' + # |-> dest='virtio-net-pci' type=2 (node=0x55914210d880) + # src='pci-bus-pc' + # |-> dest='pci-bus' type=1 (node=0x559142103f40) + # src='i440FX-pcihost' + # |-> dest='pci-bus-pc' type=0 (node=0x55914210ac70) + # src='x86_64/pc' + # |-> dest='i440FX-pcihost' type=0 (node=0x5591421117f0) + # src='' + # |-> dest='x86_64/pc' type=0 (node=0x559142111600) + # |-> dest='arm/raspi2' type=0 (node=0x559142110740) + ... + # } + # ALL QGRAPH NODES: { + # name='virtio-net-tests/announce-self' type=3 cmd_line='(null)' [available] + # name='arm/raspi2' type=0 cmd_line='-M raspi2 ' [UNAVAILABLE] + ... + # } + +The ``virtio-net-tests/announce-self`` test is listed as "available" in the +"ALL QGRAPH NODES" output. This means the test will execute. We can follow the +qgraph path in the "ALL QGRAPH EDGES" output as follows: '' -> 'x86_64/pc' -> +'i440FX-pcihost' -> 'pci-bus-pc' -> 'pci-bus' -> 'virtio-net-pci' -> +'virtio-net'. The root of the qgraph is '' and the depth first search begins +there. + +The ``arm/raspi`` machine node is listed as "UNAVAILABLE". Although it is +reachable from the root via '' -> 'arm/raspi2' the node is unavailable because +the QEMU binary did not list it when queried by the framework. This is expected +because we used the ``qemu-system-x86_64`` binary which does not support ARM +machine types. + +If a test is unexpectedly listed as "UNAVAILABLE", first check that the "ALL +QGRAPH EDGES" output reports edge connectivity from the root ('') to the test. +If there is no connectivity then the qgraph nodes were not set up correctly and +the driver or test code is incorrect. If there is connectivity, check the +availability of each node in the path in the "ALL QGRAPH NODES" output. The +first unavailable node in the path is the reason why the test is unavailable. +Typically this is because the QEMU binary lacks support for the necessary +machine type or device. + Creating a new driver and its interface """"""""""""""""""""""""""""""""""""""""" diff --git a/docs/interop/_templates/editpage.html b/docs/interop/_templates/editpage.html deleted file mode 100644 index 215e562681..0000000000 --- a/docs/interop/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/interop/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/docs/meson.build b/docs/meson.build index f84306ba7e..855e3916e9 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -27,10 +27,9 @@ if sphinx_build.found() 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())) + warning('@0@: @1@'.format(sphinx_build.full_path(), sphinx_build_test_out.stderr())) if get_option('docs').enabled() - error('Install a Python 3 version of python-sphinx') + error('Install a Python 3 version of python-sphinx and the readthedoc theme') endif endif endif diff --git a/docs/specs/_templates/editpage.html b/docs/specs/_templates/editpage.html deleted file mode 100644 index aaa468aa98..0000000000 --- a/docs/specs/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/specs/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/docs/sphinx-static/theme_overrides.css b/docs/sphinx-static/theme_overrides.css new file mode 100644 index 0000000000..c70ef95128 --- /dev/null +++ b/docs/sphinx-static/theme_overrides.css @@ -0,0 +1,161 @@ +/* -*- coding: utf-8; mode: css -*- + * + * Sphinx HTML theme customization: read the doc + * Based on Linux Documentation/sphinx-static/theme_overrides.css + */ + +/* Improve contrast and increase size for easier reading. */ + +body { + font-family: serif; + color: black; + font-size: 100%; +} + +h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend { + font-family: sans-serif; +} + +.rst-content dl:not(.docutils) dt { + border-top: none; + border-left: solid 3px #ccc; + background-color: #f0f0f0; + color: black; +} + +.wy-nav-top { + background: #802400; +} + +.wy-side-nav-search input[type="text"] { + border-color: #f60; +} + +.wy-menu-vertical p.caption { + color: white; +} + +.wy-menu-vertical li.current a { + color: #505050; +} + +.wy-menu-vertical li.on a, .wy-menu-vertical li.current > a { + color: #303030; +} + +.fa-gitlab { + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 3px 10px 0 rgba(0,0,0,0.19); + border-radius: 5px; +} + +div[class^="highlight"] pre { + font-family: monospace; + color: black; + font-size: 100%; +} + +.wy-menu-vertical { + font-family: sans-serif; +} + +.c { + font-style: normal; +} + +p { + font-size: 100%; +} + +/* Interim: Code-blocks with line nos - lines and line numbers don't line up. + * see: https://github.com/rtfd/sphinx_rtd_theme/issues/419 + */ + +div[class^="highlight"] pre { + line-height: normal; +} +.rst-content .highlight > pre { + line-height: normal; +} + +/* Keep fields from being strangely far apart due to inheirited table CSS. */ +.rst-content table.field-list th.field-name { + padding-top: 1px; + padding-bottom: 1px; +} +.rst-content table.field-list td.field-body { + padding-top: 1px; + padding-bottom: 1px; +} + +@media screen { + + /* content column + * + * RTD theme's default is 800px as max width for the content, but we have + * tables with tons of columns, which need the full width of the view-port. + */ + + .wy-nav-content{max-width: none; } + + /* table: + * + * - Sequences of whitespace should collapse into a single whitespace. + * - make the overflow auto (scrollbar if needed) + * - align caption "left" ("center" is unsuitable on vast tables) + */ + + .wy-table-responsive table td { white-space: normal; } + .wy-table-responsive { overflow: auto; } + .rst-content table.docutils caption { text-align: left; font-size: 100%; } + + /* captions: + * + * - captions should have 100% (not 85%) font size + * - hide the permalink symbol as long as link is not hovered + */ + + .toc-title { + font-size: 150%; + font-weight: bold; + } + + caption, .wy-table caption, .rst-content table.field-list caption { + font-size: 100%; + } + caption a.headerlink { opacity: 0; } + caption a.headerlink:hover { opacity: 1; } + + /* Menu selection and keystrokes */ + + span.menuselection { + color: blue; + font-family: "Courier New", Courier, monospace + } + + code.kbd, code.kbd span { + color: white; + background-color: darkblue; + font-weight: bold; + font-family: "Courier New", Courier, monospace + } + + /* fix bottom margin of lists items */ + + .rst-content .section ul li:last-child, .rst-content .section ul li p:last-child { + margin-bottom: 12px; + } + + /* inline literal: drop the borderbox, padding and red color */ + + code, .rst-content tt, .rst-content code { + color: inherit; + border: none; + padding: unset; + background: inherit; + font-size: 85%; + } + + .rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal { + color: inherit; + } +} diff --git a/docs/system/_templates/editpage.html b/docs/system/_templates/editpage.html deleted file mode 100644 index 6586b2e257..0000000000 --- a/docs/system/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/system/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index f9169077ae..abbf8243a3 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -198,30 +198,6 @@ from Linux upstream kernel, declare it deprecated. System emulator CPUS -------------------- -``moxie`` CPU (since 5.2.0) -''''''''''''''''''''''''''' - -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. - -``lm32`` CPUs (since 5.2.0) -''''''''''''''''''''''''''' - -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) '''''''''''''''''''''''''''''''''''''''''' @@ -293,15 +269,6 @@ 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 -------------------- diff --git a/docs/system/device-url-syntax.rst.inc b/docs/system/device-url-syntax.rst.inc index 6f6ec8366b..d15a021508 100644 --- a/docs/system/device-url-syntax.rst.inc +++ b/docs/system/device-url-syntax.rst.inc @@ -85,24 +85,6 @@ These are specified using a special URL syntax. Currently authentication must be done using ssh-agent. Other authentication methods may be supported in future. -``Sheepdog`` - Sheepdog is a distributed storage system for QEMU. QEMU supports - using either local sheepdog devices or remote networked devices. - - Syntax for specifying a sheepdog device - - :: - - sheepdog[+tcp|+unix]://[host:port]/vdiname[?socket=path][#snapid|#tag] - - Example - - .. parsed-literal:: - - |qemu_system| --drive file=sheepdog://192.0.2.1:30000/MyVirtualMachine - - See also https://sheepdog.github.io/sheepdog/. - ``GlusterFS`` GlusterFS is a user space distributed file system. QEMU supports the use of GlusterFS volumes for hosting VM disk images using TCP, Unix diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc index 60a064b232..16225710eb 100644 --- a/docs/system/qemu-block-drivers.rst.inc +++ b/docs/system/qemu-block-drivers.rst.inc @@ -547,75 +547,6 @@ also available. Here are some example of the older syntax: |qemu_system| linux2.img -hdb nbd:unix:/tmp/my_socket |qemu_system| -cdrom nbd:localhost:10809:exportname=debian-500-ppc-netinst - - -Sheepdog disk images -~~~~~~~~~~~~~~~~~~~~ - -Sheepdog is a distributed storage system for QEMU. It provides highly -available block level storage volumes that can be attached to -QEMU-based virtual machines. - -You can create a Sheepdog disk image with the command: - -.. parsed-literal:: - - qemu-img create sheepdog:///IMAGE SIZE - -where *IMAGE* is the Sheepdog image name and *SIZE* is its -size. - -To import the existing *FILENAME* to Sheepdog, you can use a -convert command. - -.. parsed-literal:: - - qemu-img convert FILENAME sheepdog:///IMAGE - -You can boot from the Sheepdog disk image with the command: - -.. parsed-literal:: - - |qemu_system| sheepdog:///IMAGE - -You can also create a snapshot of the Sheepdog image like qcow2. - -.. parsed-literal:: - - qemu-img snapshot -c TAG sheepdog:///IMAGE - -where *TAG* is a tag name of the newly created snapshot. - -To boot from the Sheepdog snapshot, specify the tag name of the -snapshot. - -.. parsed-literal:: - - |qemu_system| sheepdog:///IMAGE#TAG - -You can create a cloned image from the existing snapshot. - -.. parsed-literal:: - - qemu-img create -b sheepdog:///BASE#TAG sheepdog:///IMAGE - -where *BASE* is an image name of the source snapshot and *TAG* -is its tag name. - -You can use an unix socket instead of an inet socket: - -.. parsed-literal:: - - |qemu_system| sheepdog+unix:///IMAGE?socket=PATH - -If the Sheepdog daemon doesn't run on the local host, you need to -specify one of the Sheepdog servers to connect to. - -.. parsed-literal:: - - qemu-img create sheepdog://HOSTNAME:PORT/IMAGE SIZE - |qemu_system| sheepdog://HOSTNAME:PORT/IMAGE - iSCSI LUNs ~~~~~~~~~~ diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst index c21e6fa5ee..5a462ac568 100644 --- a/docs/system/removed-features.rst +++ b/docs/system/removed-features.rst @@ -291,6 +291,27 @@ via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. The ``max-cpu-compat`` property of the ``pseries`` machine type should be used instead. +``moxie`` CPU (removed in 6.1) +'''''''''''''''''''''''''''''' + +Nobody was using this CPU emulation in QEMU, and there were no test images +available to make sure that the code is still working, so it has been removed +without replacement. + +``lm32`` CPUs (removed in 6.1.0) +'''''''''''''''''''''''''''''''' + +The only public user of this architecture was the milkymist project, +which has been dead for years; there was never an upstream Linux +port. Removed without replacement. + +``unicore32`` CPUs (since 6.1.0) +'''''''''''''''''''''''''''''''' + +Support for this CPU was removed from the upstream Linux kernel, and +there is no available upstream toolchain to build binaries for it. +Removed without replacement. + System emulator machines ------------------------ @@ -467,3 +488,10 @@ VXHS backend (removed in 5.1) ''''''''''''''''''''''''''''' The VXHS code did not compile since v2.12.0. It was removed in 5.1. + +``sheepdog`` driver (removed in 6.0) +'''''''''''''''''''''''''''''''''''' + +The corresponding upstream server project is no longer maintained. +Users are recommended to switch to an alternative distributed block +device driver such as RBD. diff --git a/docs/tools/_templates/editpage.html b/docs/tools/_templates/editpage.html deleted file mode 100644 index 2a9c8fc92b..0000000000 --- a/docs/tools/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/tools/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index c9efcfaefc..cfe1147879 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -866,6 +866,37 @@ Supported image file formats: issue ``lsattr filename`` to check if the NOCOW flag is set or not (Capital 'C' is NOCOW flag). + ``data_file`` + Filename where all guest data will be stored. If this option is used, + the qcow2 file will only contain the image's metadata. + + Note: Data loss will occur if the given filename already exists when + using this option with ``qemu-img create`` since ``qemu-img`` will create + the data file anew, overwriting the file's original contents. To simply + update the reference to point to the given pre-existing file, use + ``qemu-img amend``. + + ``data_file_raw`` + If this option is set to ``on``, QEMU will always keep the external data + file consistent as a standalone read-only raw image. + + It does this by forwarding all write accesses to the qcow2 file through to + the raw data file, including their offsets. Therefore, data that is visible + on the qcow2 node (i.e., to the guest) at some offset is visible at the same + offset in the raw data file. This results in a read-only raw image. Writes + that bypass the qcow2 metadata may corrupt the qcow2 metadata because the + out-of-band writes may result in the metadata falling out of sync with the + raw image. + + If this option is ``off``, QEMU will use the data file to store data in an + arbitrary manner. The file’s content will not make sense without the + accompanying qcow2 metadata. Where data is written will have no relation to + its offset as seen by the guest, and some writes (specifically zero writes) + may not be forwarded to the data file at all, but will only be handled by + modifying qcow2 metadata. + + This option can only be enabled if ``data_file`` is set. + ``Other`` QEMU also supports various other image file formats for diff --git a/docs/user/_templates/editpage.html b/docs/user/_templates/editpage.html deleted file mode 100644 index 1f5ee01e60..0000000000 --- a/docs/user/_templates/editpage.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="editpage"> - <ul> - <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/user/{{pagename}}.rst">Page source</a></li> - </ul> -</div> diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc index 78f699d6f8..e19809c04b 100644 --- a/fpu/softfloat-specialize.c.inc +++ b/fpu/softfloat-specialize.c.inc @@ -103,7 +103,7 @@ static inline bool snan_bit_is_one(float_status *status) { #if defined(TARGET_MIPS) return status->snan_bit_is_one; -#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4) +#elif defined(TARGET_HPPA) || defined(TARGET_SH4) return 1; #else return 0; @@ -149,11 +149,10 @@ static FloatParts parts_default_nan(float_status *status) sign = 1; frac = ~0ULL; #else - /* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V, - * S390, SH4, TriCore, and Xtensa. I cannot find documentation - * for Unicore32; the choice from the original commit is unchanged. - * Our other supported targets, CRIS, LM32, Moxie, Nios2, and Tile, - * do not have floating-point. + /* + * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V, + * S390, SH4, TriCore, and Xtensa. Our other supported targets, + * CRIS, Nios2, and Tile, do not have floating-point. */ if (snan_bit_is_one(status)) { /* set all bits other than msb */ diff --git a/hw/Kconfig b/hw/Kconfig index ff40bd3f7b..aa10357adf 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -47,11 +47,9 @@ source avr/Kconfig source cris/Kconfig source hppa/Kconfig source i386/Kconfig -source lm32/Kconfig source m68k/Kconfig source microblaze/Kconfig source mips/Kconfig -source moxie/Kconfig source nios2/Kconfig source openrisc/Kconfig source ppc/Kconfig @@ -62,7 +60,6 @@ source sh4/Kconfig source sparc/Kconfig source sparc64/Kconfig source tricore/Kconfig -source unicore32/Kconfig source xtensa/Kconfig # Symbols used by multiple targets diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index d33ce8954a..f0035d2b4a 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1830,6 +1830,7 @@ build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, int i; unsigned rsdt_entries_offset; AcpiRsdtDescriptorRev1 *rsdt; + int rsdt_start = table_data->len; const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len); const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]); const size_t rsdt_len = sizeof(*rsdt) + table_data_len; @@ -1846,7 +1847,8 @@ build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, ACPI_BUILD_TABLE_FILE, ref_tbl_offset); } build_header(linker, table_data, - (void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id); + (void *)(table_data->data + rsdt_start), + "RSDT", rsdt_len, 1, oem_id, oem_table_id); } /* Build xsdt table */ @@ -1857,6 +1859,7 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, int i; unsigned xsdt_entries_offset; AcpiXsdtDescriptorRev2 *xsdt; + int xsdt_start = table_data->len; const unsigned table_data_len = (sizeof(uint64_t) * table_offsets->len); const unsigned xsdt_entry_size = sizeof(xsdt->table_offset_entry[0]); const size_t xsdt_len = sizeof(*xsdt) + table_data_len; @@ -1873,7 +1876,8 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, ACPI_BUILD_TABLE_FILE, ref_tbl_offset); } build_header(linker, table_data, - (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id); + (void *)(table_data->data + xsdt_start), + "XSDT", xsdt_len, 1, oem_id, oem_table_id); } void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, @@ -2053,10 +2057,9 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, 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)); + acpi_data_push(table_data, sizeof(AcpiTableHeader)); /* Platform Class */ build_append_int_noprefix(table_data, TPM2_ACPI_CLASS_CLIENT, 2); @@ -2095,8 +2098,8 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, log_addr_offset, 8, ACPI_BUILD_TPMLOG_FILE, 0); build_header(linker, table_data, - tpm2_ptr, "TPM2", table_data->len - tpm2_start, 4, oem_id, - oem_table_id); + (void *)(table_data->data + tpm2_start), + "TPM2", table_data->len - tpm2_start, 4, oem_id, oem_table_id); } Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset, diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 0a78532018..840758666d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -50,6 +50,7 @@ #include "sysemu/tpm.h" #include "sysemu/kvm.h" #include "hw/loader.h" +#include "qapi/error.h" #include "qemu/bitops.h" #include "qemu/error-report.h" #include "qemu/module.h" @@ -1521,8 +1522,10 @@ static void virt_build_smbios(VirtMachineState *vms) vmc->smbios_old_sys_ver ? "1.0" : mc->name, false, true, SMBIOS_ENTRY_POINT_30); - smbios_get_tables(MACHINE(vms), NULL, 0, &smbios_tables, &smbios_tables_len, - &smbios_anchor, &smbios_anchor_len); + smbios_get_tables(MACHINE(vms), NULL, 0, + &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len, + &error_fatal); if (smbios_anchor) { fw_cfg_add_file(vms->fw_cfg, "etc/smbios/smbios-tables", diff --git a/hw/audio/meson.build b/hw/audio/meson.build index 32c42bdebe..e48a9fc73d 100644 --- a/hw/audio/meson.build +++ b/hw/audio/meson.build @@ -7,7 +7,6 @@ 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')) diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c deleted file mode 100644 index 7d2e057038..0000000000 --- a/hw/audio/milkymist-ac97.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * QEMU model of the Milkymist System Controller. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/ac97.pdf - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "audio/audio.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -enum { - R_AC97_CTRL = 0, - R_AC97_ADDR, - R_AC97_DATAOUT, - R_AC97_DATAIN, - R_D_CTRL, - R_D_ADDR, - R_D_REMAINING, - R_RESERVED, - R_U_CTRL, - R_U_ADDR, - R_U_REMAINING, - R_MAX -}; - -enum { - AC97_CTRL_RQEN = (1<<0), - AC97_CTRL_WRITE = (1<<1), -}; - -enum { - CTRL_EN = (1<<0), -}; - -#define TYPE_MILKYMIST_AC97 "milkymist-ac97" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistAC97State, MILKYMIST_AC97) - -struct MilkymistAC97State { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - - QEMUSoundCard card; - SWVoiceIn *voice_in; - SWVoiceOut *voice_out; - - uint32_t regs[R_MAX]; - - qemu_irq crrequest_irq; - qemu_irq crreply_irq; - qemu_irq dmar_irq; - qemu_irq dmaw_irq; -}; - -static void update_voices(MilkymistAC97State *s) -{ - if (s->regs[R_D_CTRL] & CTRL_EN) { - AUD_set_active_out(s->voice_out, 1); - } else { - AUD_set_active_out(s->voice_out, 0); - } - - if (s->regs[R_U_CTRL] & CTRL_EN) { - AUD_set_active_in(s->voice_in, 1); - } else { - AUD_set_active_in(s->voice_in, 0); - } -} - -static uint64_t ac97_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistAC97State *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_AC97_CTRL: - case R_AC97_ADDR: - case R_AC97_DATAOUT: - case R_AC97_DATAIN: - case R_D_CTRL: - case R_D_ADDR: - case R_D_REMAINING: - case R_U_CTRL: - case R_U_ADDR: - case R_U_REMAINING: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_ac97: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_ac97_memory_read(addr << 2, r); - - return r; -} - -static void ac97_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistAC97State *s = opaque; - - trace_milkymist_ac97_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_AC97_CTRL: - /* always raise an IRQ according to the direction */ - if (value & AC97_CTRL_RQEN) { - if (value & AC97_CTRL_WRITE) { - trace_milkymist_ac97_pulse_irq_crrequest(); - qemu_irq_pulse(s->crrequest_irq); - } else { - trace_milkymist_ac97_pulse_irq_crreply(); - qemu_irq_pulse(s->crreply_irq); - } - } - - /* RQEN is self clearing */ - s->regs[addr] = value & ~AC97_CTRL_RQEN; - break; - case R_D_CTRL: - case R_U_CTRL: - s->regs[addr] = value; - update_voices(s); - break; - case R_AC97_ADDR: - case R_AC97_DATAOUT: - case R_AC97_DATAIN: - case R_D_ADDR: - case R_D_REMAINING: - case R_U_ADDR: - case R_U_REMAINING: - s->regs[addr] = value; - break; - - default: - error_report("milkymist_ac97: write access to unknown register 0x" - TARGET_FMT_plx, addr); - break; - } - -} - -static const MemoryRegionOps ac97_mmio_ops = { - .read = ac97_read, - .write = ac97_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void ac97_in_cb(void *opaque, int avail_b) -{ - MilkymistAC97State *s = opaque; - uint8_t buf[4096]; - uint32_t remaining = s->regs[R_U_REMAINING]; - int temp = MIN(remaining, avail_b); - uint32_t addr = s->regs[R_U_ADDR]; - int transferred = 0; - - trace_milkymist_ac97_in_cb(avail_b, remaining); - - /* prevent from raising an IRQ */ - if (temp == 0) { - return; - } - - while (temp) { - int acquired, to_copy; - - to_copy = MIN(temp, sizeof(buf)); - acquired = AUD_read(s->voice_in, buf, to_copy); - if (!acquired) { - break; - } - - cpu_physical_memory_write(addr, buf, acquired); - - temp -= acquired; - addr += acquired; - transferred += acquired; - } - - trace_milkymist_ac97_in_cb_transferred(transferred); - - s->regs[R_U_ADDR] = addr; - s->regs[R_U_REMAINING] -= transferred; - - if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) { - trace_milkymist_ac97_pulse_irq_dmaw(); - qemu_irq_pulse(s->dmaw_irq); - } -} - -static void ac97_out_cb(void *opaque, int free_b) -{ - MilkymistAC97State *s = opaque; - uint8_t buf[4096]; - uint32_t remaining = s->regs[R_D_REMAINING]; - int temp = MIN(remaining, free_b); - uint32_t addr = s->regs[R_D_ADDR]; - int transferred = 0; - - trace_milkymist_ac97_out_cb(free_b, remaining); - - /* prevent from raising an IRQ */ - if (temp == 0) { - return; - } - - while (temp) { - int copied, to_copy; - - to_copy = MIN(temp, sizeof(buf)); - cpu_physical_memory_read(addr, buf, to_copy); - copied = AUD_write(s->voice_out, buf, to_copy); - if (!copied) { - break; - } - temp -= copied; - addr += copied; - transferred += copied; - } - - trace_milkymist_ac97_out_cb_transferred(transferred); - - s->regs[R_D_ADDR] = addr; - s->regs[R_D_REMAINING] -= transferred; - - if ((s->regs[R_D_CTRL] & CTRL_EN) && (s->regs[R_D_REMAINING] == 0)) { - trace_milkymist_ac97_pulse_irq_dmar(); - qemu_irq_pulse(s->dmar_irq); - } -} - -static void milkymist_ac97_reset(DeviceState *d) -{ - MilkymistAC97State *s = MILKYMIST_AC97(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - AUD_set_active_in(s->voice_in, 0); - AUD_set_active_out(s->voice_out, 0); -} - -static int ac97_post_load(void *opaque, int version_id) -{ - MilkymistAC97State *s = opaque; - - update_voices(s); - - return 0; -} - -static void milkymist_ac97_init(Object *obj) -{ - MilkymistAC97State *s = MILKYMIST_AC97(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - - sysbus_init_irq(dev, &s->crrequest_irq); - sysbus_init_irq(dev, &s->crreply_irq); - sysbus_init_irq(dev, &s->dmar_irq); - sysbus_init_irq(dev, &s->dmaw_irq); - - memory_region_init_io(&s->regs_region, obj, &ac97_mmio_ops, s, - "milkymist-ac97", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); -} - -static void milkymist_ac97_realize(DeviceState *dev, Error **errp) -{ - MilkymistAC97State *s = MILKYMIST_AC97(dev); - struct audsettings as; - - AUD_register_card("Milkymist AC'97", &s->card); - - as.freq = 48000; - as.nchannels = 2; - as.fmt = AUDIO_FORMAT_S16; - as.endianness = 1; - - s->voice_in = AUD_open_in(&s->card, s->voice_in, - "mm_ac97.in", s, ac97_in_cb, &as); - s->voice_out = AUD_open_out(&s->card, s->voice_out, - "mm_ac97.out", s, ac97_out_cb, &as); -} - -static const VMStateDescription vmstate_milkymist_ac97 = { - .name = "milkymist-ac97", - .version_id = 1, - .minimum_version_id = 1, - .post_load = ac97_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_ac97_properties[] = { - DEFINE_AUDIO_PROPERTIES(MilkymistAC97State, card), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_ac97_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_ac97_realize; - dc->reset = milkymist_ac97_reset; - dc->vmsd = &vmstate_milkymist_ac97; - device_class_set_props(dc, milkymist_ac97_properties); -} - -static const TypeInfo milkymist_ac97_info = { - .name = TYPE_MILKYMIST_AC97, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistAC97State), - .instance_init = milkymist_ac97_init, - .class_init = milkymist_ac97_class_init, -}; - -static void milkymist_ac97_register_types(void) -{ - type_register_static(&milkymist_ac97_info); -} - -type_init(milkymist_ac97_register_types) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 60556b4a97..432e10712f 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -6,18 +6,6 @@ cs4231_mem_readl_reg(uint32_t reg, uint32_t ret) "read reg %d: 0x%08x" cs4231_mem_writel_reg(uint32_t reg, uint32_t old, uint32_t val) "write reg %d: 0x%08x -> 0x%08x" cs4231_mem_writel_dreg(uint32_t reg, uint32_t old, uint32_t val) "write dreg %d: 0x%02x -> 0x%02x" -# milkymist-ac97.c -milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" -milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply" -milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write" -milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read" -milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u" -milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" -milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u" -milkymist_ac97_out_cb_transferred(int transferred) "transferred %d" - # hda-codec.c hda_audio_running(const char *stream, int nr, bool running) "st %s, nr %d, run %d" hda_audio_format(const char *stream, int chan, const char *fmt, int freq) "st %s, %d x %s @ %d Hz" diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index e9050c8987..cd81893d1d 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -198,19 +198,30 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) goto fail_guest_notifiers; } + memory_region_transaction_begin(); + /* Set up virtqueue notify */ for (i = 0; i < nvqs; i++) { r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, true); if (r != 0) { + int j = i; + fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r); while (i--) { virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false); + } + + memory_region_transaction_commit(); + + while (j--) { virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); } - goto fail_guest_notifiers; + goto fail_host_notifiers; } } + memory_region_transaction_commit(); + s->starting = false; vblk->dataplane_started = true; trace_virtio_blk_data_plane_start(s); @@ -221,7 +232,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) aio_context_release(old_context); if (r < 0) { error_report_err(local_err); - goto fail_guest_notifiers; + goto fail_aio_context; } /* Process queued requests before the ones in vring */ @@ -245,6 +256,20 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) aio_context_release(s->ctx); return 0; + fail_aio_context: + memory_region_transaction_begin(); + + for (i = 0; i < nvqs; i++) { + virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false); + } + + memory_region_transaction_commit(); + + for (i = 0; i < nvqs; i++) { + virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); + } + fail_host_notifiers: + k->set_guest_notifiers(qbus->parent, nvqs, false); fail_guest_notifiers: /* * If we failed to set up the guest notifiers queued requests will be @@ -305,8 +330,15 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev) aio_context_release(s->ctx); + memory_region_transaction_begin(); + for (i = 0; i < nvqs; i++) { virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false); + } + + memory_region_transaction_commit(); + + for (i = 0; i < nvqs; i++) { virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); } diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 25c053693c..02c514fb6e 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -173,7 +173,6 @@ static void pflash_setup_mappings(PFlashCFI02 *pfl) "pflash-alias", &pfl->orig_mem, 0, size); memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]); } - pfl->rom_mode = true; } static void pflash_reset_state_machine(PFlashCFI02 *pfl) @@ -917,8 +916,13 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) /* Allocate memory for a bitmap for sectors being erased. */ pfl->sector_erase_map = bitmap_new(pfl->total_sectors); - pflash_setup_mappings(pfl); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); + pfl->rom_mode = true; + if (pfl->mappings > 1) { + pflash_setup_mappings(pfl); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); + } else { + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->orig_mem); + } timer_init_ns(&pfl->timer, QEMU_CLOCK_VIRTUAL, pflash_timer, pfl); pfl->status = 0; diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c deleted file mode 100644 index ce30279650..0000000000 --- a/hw/char/lm32_juart.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * LatticeMico32 JTAG UART model. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "qemu/module.h" -#include "trace.h" -#include "chardev/char-fe.h" - -#include "hw/char/lm32_juart.h" -#include "hw/qdev-properties.h" -#include "hw/qdev-properties-system.h" -#include "qom/object.h" - -enum { - LM32_JUART_MIN_SAVE_VERSION = 0, - LM32_JUART_CURRENT_SAVE_VERSION = 0, - LM32_JUART_MAX_SAVE_VERSION = 0, -}; - -enum { - JTX_FULL = (1<<8), -}; - -enum { - JRX_FULL = (1<<8), -}; - -OBJECT_DECLARE_SIMPLE_TYPE(LM32JuartState, LM32_JUART) - -struct LM32JuartState { - SysBusDevice parent_obj; - - CharBackend chr; - - uint32_t jtx; - uint32_t jrx; -}; - -uint32_t lm32_juart_get_jtx(DeviceState *d) -{ - LM32JuartState *s = LM32_JUART(d); - - trace_lm32_juart_get_jtx(s->jtx); - return s->jtx; -} - -uint32_t lm32_juart_get_jrx(DeviceState *d) -{ - LM32JuartState *s = LM32_JUART(d); - - trace_lm32_juart_get_jrx(s->jrx); - return s->jrx; -} - -void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx) -{ - LM32JuartState *s = LM32_JUART(d); - unsigned char ch = jtx & 0xff; - - trace_lm32_juart_set_jtx(s->jtx); - - s->jtx = jtx; - /* XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks */ - qemu_chr_fe_write_all(&s->chr, &ch, 1); -} - -void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx) -{ - LM32JuartState *s = LM32_JUART(d); - - trace_lm32_juart_set_jrx(s->jrx); - s->jrx &= ~JRX_FULL; -} - -static void juart_rx(void *opaque, const uint8_t *buf, int size) -{ - LM32JuartState *s = opaque; - - s->jrx = *buf | JRX_FULL; -} - -static int juart_can_rx(void *opaque) -{ - LM32JuartState *s = opaque; - - return !(s->jrx & JRX_FULL); -} - -static void juart_event(void *opaque, QEMUChrEvent event) -{ -} - -static void juart_reset(DeviceState *d) -{ - LM32JuartState *s = LM32_JUART(d); - - s->jtx = 0; - s->jrx = 0; -} - -static void lm32_juart_realize(DeviceState *dev, Error **errp) -{ - LM32JuartState *s = LM32_JUART(dev); - - qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx, - juart_event, NULL, s, NULL, true); -} - -static const VMStateDescription vmstate_lm32_juart = { - .name = "lm32-juart", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(jtx, LM32JuartState), - VMSTATE_UINT32(jrx, LM32JuartState), - VMSTATE_END_OF_LIST() - } -}; - -static Property lm32_juart_properties[] = { - DEFINE_PROP_CHR("chardev", LM32JuartState, chr), - DEFINE_PROP_END_OF_LIST(), -}; - -static void lm32_juart_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = juart_reset; - dc->vmsd = &vmstate_lm32_juart; - device_class_set_props(dc, lm32_juart_properties); - dc->realize = lm32_juart_realize; -} - -static const TypeInfo lm32_juart_info = { - .name = TYPE_LM32_JUART, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LM32JuartState), - .class_init = lm32_juart_class_init, -}; - -static void lm32_juart_register_types(void) -{ - type_register_static(&lm32_juart_info); -} - -type_init(lm32_juart_register_types) diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c deleted file mode 100644 index d8e0331311..0000000000 --- a/hw/char/lm32_uart.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * QEMU model of the LatticeMico32 UART block. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://www.latticesemi.com/documents/mico32uart.pdf - */ - - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "hw/qdev-properties-system.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "chardev/char-fe.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -enum { - R_RXTX = 0, - R_IER, - R_IIR, - R_LCR, - R_MCR, - R_LSR, - R_MSR, - R_DIV, - R_MAX -}; - -enum { - IER_RBRI = (1<<0), - IER_THRI = (1<<1), - IER_RLSI = (1<<2), - IER_MSI = (1<<3), -}; - -enum { - IIR_STAT = (1<<0), - IIR_ID0 = (1<<1), - IIR_ID1 = (1<<2), -}; - -enum { - LCR_WLS0 = (1<<0), - LCR_WLS1 = (1<<1), - LCR_STB = (1<<2), - LCR_PEN = (1<<3), - LCR_EPS = (1<<4), - LCR_SP = (1<<5), - LCR_SB = (1<<6), -}; - -enum { - MCR_DTR = (1<<0), - MCR_RTS = (1<<1), -}; - -enum { - LSR_DR = (1<<0), - LSR_OE = (1<<1), - LSR_PE = (1<<2), - LSR_FE = (1<<3), - LSR_BI = (1<<4), - LSR_THRE = (1<<5), - LSR_TEMT = (1<<6), -}; - -enum { - MSR_DCTS = (1<<0), - MSR_DDSR = (1<<1), - MSR_TERI = (1<<2), - MSR_DDCD = (1<<3), - MSR_CTS = (1<<4), - MSR_DSR = (1<<5), - MSR_RI = (1<<6), - MSR_DCD = (1<<7), -}; - -#define TYPE_LM32_UART "lm32-uart" -OBJECT_DECLARE_SIMPLE_TYPE(LM32UartState, LM32_UART) - -struct LM32UartState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - CharBackend chr; - qemu_irq irq; - - uint32_t regs[R_MAX]; -}; - -static void uart_update_irq(LM32UartState *s) -{ - unsigned int irq; - - if ((s->regs[R_LSR] & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) - && (s->regs[R_IER] & IER_RLSI)) { - irq = 1; - s->regs[R_IIR] = IIR_ID1 | IIR_ID0; - } else if ((s->regs[R_LSR] & LSR_DR) && (s->regs[R_IER] & IER_RBRI)) { - irq = 1; - s->regs[R_IIR] = IIR_ID1; - } else if ((s->regs[R_LSR] & LSR_THRE) && (s->regs[R_IER] & IER_THRI)) { - irq = 1; - s->regs[R_IIR] = IIR_ID0; - } else if ((s->regs[R_MSR] & 0x0f) && (s->regs[R_IER] & IER_MSI)) { - irq = 1; - s->regs[R_IIR] = 0; - } else { - irq = 0; - s->regs[R_IIR] = IIR_STAT; - } - - trace_lm32_uart_irq_state(irq); - qemu_set_irq(s->irq, irq); -} - -static uint64_t uart_read(void *opaque, hwaddr addr, - unsigned size) -{ - LM32UartState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_RXTX: - r = s->regs[R_RXTX]; - s->regs[R_LSR] &= ~LSR_DR; - uart_update_irq(s); - qemu_chr_fe_accept_input(&s->chr); - break; - case R_IIR: - case R_LSR: - case R_MSR: - r = s->regs[addr]; - break; - case R_IER: - case R_LCR: - case R_MCR: - case R_DIV: - error_report("lm32_uart: read access to write only register 0x" - TARGET_FMT_plx, addr << 2); - break; - default: - error_report("lm32_uart: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_lm32_uart_memory_read(addr << 2, r); - return r; -} - -static void uart_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - LM32UartState *s = opaque; - unsigned char ch = value; - - trace_lm32_uart_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_RXTX: - /* XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks */ - qemu_chr_fe_write_all(&s->chr, &ch, 1); - break; - case R_IER: - case R_LCR: - case R_MCR: - case R_DIV: - s->regs[addr] = value; - break; - case R_IIR: - case R_LSR: - case R_MSR: - error_report("lm32_uart: write access to read only register 0x" - TARGET_FMT_plx, addr << 2); - break; - default: - error_report("lm32_uart: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - uart_update_irq(s); -} - -static const MemoryRegionOps uart_ops = { - .read = uart_read, - .write = uart_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void uart_rx(void *opaque, const uint8_t *buf, int size) -{ - LM32UartState *s = opaque; - - if (s->regs[R_LSR] & LSR_DR) { - s->regs[R_LSR] |= LSR_OE; - } - - s->regs[R_LSR] |= LSR_DR; - s->regs[R_RXTX] = *buf; - - uart_update_irq(s); -} - -static int uart_can_rx(void *opaque) -{ - LM32UartState *s = opaque; - - return !(s->regs[R_LSR] & LSR_DR); -} - -static void uart_event(void *opaque, QEMUChrEvent event) -{ -} - -static void uart_reset(DeviceState *d) -{ - LM32UartState *s = LM32_UART(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - /* defaults */ - s->regs[R_LSR] = LSR_THRE | LSR_TEMT; -} - -static void lm32_uart_init(Object *obj) -{ - LM32UartState *s = LM32_UART(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->iomem, obj, &uart_ops, s, - "uart", R_MAX * 4); - sysbus_init_mmio(dev, &s->iomem); -} - -static void lm32_uart_realize(DeviceState *dev, Error **errp) -{ - LM32UartState *s = LM32_UART(dev); - - qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, - uart_event, NULL, s, NULL, true); -} - -static const VMStateDescription vmstate_lm32_uart = { - .name = "lm32-uart", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static Property lm32_uart_properties[] = { - DEFINE_PROP_CHR("chardev", LM32UartState, chr), - DEFINE_PROP_END_OF_LIST(), -}; - -static void lm32_uart_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = uart_reset; - dc->vmsd = &vmstate_lm32_uart; - device_class_set_props(dc, lm32_uart_properties); - dc->realize = lm32_uart_realize; -} - -static const TypeInfo lm32_uart_info = { - .name = TYPE_LM32_UART, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LM32UartState), - .instance_init = lm32_uart_init, - .class_init = lm32_uart_class_init, -}; - -static void lm32_uart_register_types(void) -{ - type_register_static(&lm32_uart_info); -} - -type_init(lm32_uart_register_types) diff --git a/hw/char/meson.build b/hw/char/meson.build index 014833dded..8361d0ab28 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -8,9 +8,6 @@ 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_DEVICES', if_true: files('lm32_juart.c')) -softmmu_ss.add(when: 'CONFIG_LM32_DEVICES', 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')) diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c deleted file mode 100644 index cb1b3470ad..0000000000 --- a/hw/char/milkymist-uart.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * QEMU model of the Milkymist UART block. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/uart.pdf - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "hw/qdev-properties-system.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "chardev/char-fe.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -enum { - R_RXTX = 0, - R_DIV, - R_STAT, - R_CTRL, - R_DBG, - R_MAX -}; - -enum { - STAT_THRE = (1<<0), - STAT_RX_EVT = (1<<1), - STAT_TX_EVT = (1<<2), -}; - -enum { - CTRL_RX_IRQ_EN = (1<<0), - CTRL_TX_IRQ_EN = (1<<1), - CTRL_THRU_EN = (1<<2), -}; - -enum { - DBG_BREAK_EN = (1<<0), -}; - -#define TYPE_MILKYMIST_UART "milkymist-uart" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistUartState, MILKYMIST_UART) - -struct MilkymistUartState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - CharBackend chr; - qemu_irq irq; - - uint32_t regs[R_MAX]; -}; - -static void uart_update_irq(MilkymistUartState *s) -{ - int rx_event = s->regs[R_STAT] & STAT_RX_EVT; - int tx_event = s->regs[R_STAT] & STAT_TX_EVT; - int rx_irq_en = s->regs[R_CTRL] & CTRL_RX_IRQ_EN; - int tx_irq_en = s->regs[R_CTRL] & CTRL_TX_IRQ_EN; - - if ((rx_irq_en && rx_event) || (tx_irq_en && tx_event)) { - trace_milkymist_uart_raise_irq(); - qemu_irq_raise(s->irq); - } else { - trace_milkymist_uart_lower_irq(); - qemu_irq_lower(s->irq); - } -} - -static uint64_t uart_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistUartState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_RXTX: - r = s->regs[addr]; - break; - case R_DIV: - case R_STAT: - case R_CTRL: - case R_DBG: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_uart: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_uart_memory_read(addr << 2, r); - - return r; -} - -static void uart_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistUartState *s = opaque; - unsigned char ch = value; - - trace_milkymist_uart_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_RXTX: - qemu_chr_fe_write_all(&s->chr, &ch, 1); - s->regs[R_STAT] |= STAT_TX_EVT; - break; - case R_DIV: - case R_CTRL: - case R_DBG: - s->regs[addr] = value; - break; - - case R_STAT: - /* write one to clear bits */ - s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT)); - qemu_chr_fe_accept_input(&s->chr); - break; - - default: - error_report("milkymist_uart: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - uart_update_irq(s); -} - -static const MemoryRegionOps uart_mmio_ops = { - .read = uart_read, - .write = uart_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void uart_rx(void *opaque, const uint8_t *buf, int size) -{ - MilkymistUartState *s = opaque; - - assert(!(s->regs[R_STAT] & STAT_RX_EVT)); - - s->regs[R_STAT] |= STAT_RX_EVT; - s->regs[R_RXTX] = *buf; - - uart_update_irq(s); -} - -static int uart_can_rx(void *opaque) -{ - MilkymistUartState *s = opaque; - - return !(s->regs[R_STAT] & STAT_RX_EVT); -} - -static void uart_event(void *opaque, QEMUChrEvent event) -{ -} - -static void milkymist_uart_reset(DeviceState *d) -{ - MilkymistUartState *s = MILKYMIST_UART(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - /* THRE is always set */ - s->regs[R_STAT] = STAT_THRE; -} - -static void milkymist_uart_realize(DeviceState *dev, Error **errp) -{ - MilkymistUartState *s = MILKYMIST_UART(dev); - - qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, - uart_event, NULL, s, NULL, true); -} - -static void milkymist_uart_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - MilkymistUartState *s = MILKYMIST_UART(obj); - - sysbus_init_irq(sbd, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s, - "milkymist-uart", R_MAX * 4); - sysbus_init_mmio(sbd, &s->regs_region); -} - -static const VMStateDescription vmstate_milkymist_uart = { - .name = "milkymist-uart", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistUartState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_uart_properties[] = { - DEFINE_PROP_CHR("chardev", MilkymistUartState, chr), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_uart_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_uart_realize; - dc->reset = milkymist_uart_reset; - dc->vmsd = &vmstate_milkymist_uart; - device_class_set_props(dc, milkymist_uart_properties); -} - -static const TypeInfo milkymist_uart_info = { - .name = TYPE_MILKYMIST_UART, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistUartState), - .instance_init = milkymist_uart_init, - .class_init = milkymist_uart_class_init, -}; - -static void milkymist_uart_register_types(void) -{ - type_register_static(&milkymist_uart_info); -} - -type_init(milkymist_uart_register_types) diff --git a/hw/char/trace-events b/hw/char/trace-events index c8dcade104..2e6e6b119a 100644 --- a/hw/char/trace-events +++ b/hw/char/trace-events @@ -35,23 +35,6 @@ grlib_apbuart_event(int event) "event:%d" grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64 -# lm32_juart.c -lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x" -lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x" -lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x" -lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x" - -# lm32_uart.c -lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -lm32_uart_irq_state(int level) "irq state %d" - -# milkymist-uart.c -milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_uart_raise_irq(void) "Raise IRQ" -milkymist_uart_lower_irq(void) "Lower IRQ" - # escc.c escc_put_queue(char channel, int b) "channel %c put: 0x%02x" escc_get_queue(char channel, int val) "channel %c get 0x%02x" diff --git a/hw/core/numa.c b/hw/core/numa.c index ac6bed5817..1058d3697b 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -802,9 +802,27 @@ void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms) } } +static int ram_block_notify_add_single(RAMBlock *rb, void *opaque) +{ + const ram_addr_t max_size = qemu_ram_get_max_length(rb); + const ram_addr_t size = qemu_ram_get_used_length(rb); + void *host = qemu_ram_get_host_addr(rb); + RAMBlockNotifier *notifier = opaque; + + if (host) { + notifier->ram_block_added(notifier, host, size, max_size); + } + return 0; +} + void ram_block_notifier_add(RAMBlockNotifier *n) { QLIST_INSERT_HEAD(&ram_list.ramblock_notifiers, n, next); + + /* Notify about all existing ram blocks. */ + if (n->ram_block_added) { + qemu_ram_foreach_block(ram_block_notify_add_single, n); + } } void ram_block_notifier_remove(RAMBlockNotifier *n) @@ -812,20 +830,35 @@ void ram_block_notifier_remove(RAMBlockNotifier *n) QLIST_REMOVE(n, next); } -void ram_block_notify_add(void *host, size_t size) +void ram_block_notify_add(void *host, size_t size, size_t max_size) +{ + RAMBlockNotifier *notifier; + + QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) { + if (notifier->ram_block_added) { + notifier->ram_block_added(notifier, host, size, max_size); + } + } +} + +void ram_block_notify_remove(void *host, size_t size, size_t max_size) { RAMBlockNotifier *notifier; QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) { - notifier->ram_block_added(notifier, host, size); + if (notifier->ram_block_removed) { + notifier->ram_block_removed(notifier, host, size, max_size); + } } } -void ram_block_notify_remove(void *host, size_t size) +void ram_block_notify_resize(void *host, size_t old_size, size_t new_size) { RAMBlockNotifier *notifier; QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) { - notifier->ram_block_removed(notifier, host, size); + if (notifier->ram_block_resized) { + notifier->ram_block_resized(notifier, host, old_size, new_size); + } } } diff --git a/hw/display/Kconfig b/hw/display/Kconfig index ca46b5830e..a2306b67d8 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -72,10 +72,6 @@ config BLIZZARD config FRAMEBUFFER bool -config MILKYMIST_TMU2 - bool - depends on OPENGL && X11 - config SM501 bool select I2C diff --git a/hw/display/meson.build b/hw/display/meson.build index 612cd6582d..aaf797c5e9 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -48,7 +48,6 @@ 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')) @@ -94,7 +93,6 @@ if config_all_devices.has_key('CONFIG_VIRTIO_VGA') hw_display_modules += {'virtio-vga-gl': virtio_vga_gl_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 deleted file mode 100644 index 02a28c807b..0000000000 --- a/hw/display/milkymist-tmu2.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * QEMU model of the Milkymist texture mapping unit. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * Copyright (c) 2010 Sebastien Bourdeauducq - * <sebastien.bourdeauducq@lekernel.net> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/tmu2.pdf - * - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "qapi/error.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qapi/error.h" -#include "hw/display/milkymist_tmu2.h" - -#include <X11/Xlib.h> -#include <epoxy/gl.h> -#include <epoxy/glx.h> -#include "qom/object.h" - -enum { - R_CTL = 0, - R_HMESHLAST, - R_VMESHLAST, - R_BRIGHTNESS, - R_CHROMAKEY, - R_VERTICESADDR, - R_TEXFBUF, - R_TEXHRES, - R_TEXVRES, - R_TEXHMASK, - R_TEXVMASK, - R_DSTFBUF, - R_DSTHRES, - R_DSTVRES, - R_DSTHOFFSET, - R_DSTVOFFSET, - R_DSTSQUAREW, - R_DSTSQUAREH, - R_ALPHA, - R_MAX -}; - -enum { - CTL_START_BUSY = (1<<0), - CTL_CHROMAKEY = (1<<1), -}; - -enum { - MAX_BRIGHTNESS = 63, - MAX_ALPHA = 63, -}; - -enum { - MESH_MAXSIZE = 128, -}; - -struct vertex { - int x; - int y; -} QEMU_PACKED; - -#define TYPE_MILKYMIST_TMU2 "milkymist-tmu2" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistTMU2State, MILKYMIST_TMU2) - -struct MilkymistTMU2State { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - Chardev *chr; - qemu_irq irq; - - uint32_t regs[R_MAX]; - - Display *dpy; - GLXFBConfig glx_fb_config; - GLXContext glx_context; -}; - -static const int glx_fbconfig_attr[] = { - GLX_GREEN_SIZE, 5, - GLX_GREEN_SIZE, 6, - GLX_BLUE_SIZE, 5, - None -}; - -static int tmu2_glx_init(MilkymistTMU2State *s) -{ - GLXFBConfig *configs; - int nelements; - - s->dpy = XOpenDisplay(NULL); /* FIXME: call XCloseDisplay() */ - if (s->dpy == NULL) { - return 1; - } - - configs = glXChooseFBConfig(s->dpy, 0, glx_fbconfig_attr, &nelements); - if (configs == NULL) { - return 1; - } - - s->glx_fb_config = *configs; - XFree(configs); - - /* FIXME: call glXDestroyContext() */ - s->glx_context = glXCreateNewContext(s->dpy, s->glx_fb_config, - GLX_RGBA_TYPE, NULL, 1); - if (s->glx_context == NULL) { - return 1; - } - - return 0; -} - -static void tmu2_gl_map(struct vertex *mesh, int texhres, int texvres, - int hmeshlast, int vmeshlast, int ho, int vo, int sw, int sh) -{ - int x, y; - int x0, y0, x1, y1; - int u0, v0, u1, v1, u2, v2, u3, v3; - double xscale = 1.0 / ((double)(64 * texhres)); - double yscale = 1.0 / ((double)(64 * texvres)); - - glLoadIdentity(); - glTranslatef(ho, vo, 0); - glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - - for (y = 0; y < vmeshlast; y++) { - y0 = y * sh; - y1 = y0 + sh; - for (x = 0; x < hmeshlast; x++) { - x0 = x * sw; - x1 = x0 + sw; - - u0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].x); - v0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].y); - u1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].x); - v1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].y); - u2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].x); - v2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].y); - u3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].x); - v3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].y); - - glTexCoord2d(((double)u0) * xscale, ((double)v0) * yscale); - glVertex3i(x0, y0, 0); - glTexCoord2d(((double)u1) * xscale, ((double)v1) * yscale); - glVertex3i(x1, y0, 0); - glTexCoord2d(((double)u2) * xscale, ((double)v2) * yscale); - glVertex3i(x1, y1, 0); - glTexCoord2d(((double)u3) * xscale, ((double)v3) * yscale); - glVertex3i(x0, y1, 0); - } - } - - glEnd(); -} - -static void tmu2_start(MilkymistTMU2State *s) -{ - int pbuffer_attrib[6] = { - GLX_PBUFFER_WIDTH, - 0, - GLX_PBUFFER_HEIGHT, - 0, - GLX_PRESERVED_CONTENTS, - True - }; - - GLXPbuffer pbuffer; - GLuint texture; - void *fb; - hwaddr fb_len; - void *mesh; - hwaddr mesh_len; - float m; - - trace_milkymist_tmu2_start(); - - /* Create and set up a suitable OpenGL context */ - pbuffer_attrib[1] = s->regs[R_DSTHRES]; - pbuffer_attrib[3] = s->regs[R_DSTVRES]; - pbuffer = glXCreatePbuffer(s->dpy, s->glx_fb_config, pbuffer_attrib); - glXMakeContextCurrent(s->dpy, pbuffer, pbuffer, s->glx_context); - - /* Fixup endianness. TODO: would it work on BE hosts? */ - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); - glPixelStorei(GL_PACK_SWAP_BYTES, 1); - - /* Row alignment */ - glPixelStorei(GL_UNPACK_ALIGNMENT, 2); - glPixelStorei(GL_PACK_ALIGNMENT, 2); - - /* Read the QEMU source framebuffer into an OpenGL texture */ - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - fb_len = 2ULL * s->regs[R_TEXHRES] * s->regs[R_TEXVRES]; - fb = cpu_physical_memory_map(s->regs[R_TEXFBUF], &fb_len, false); - if (fb == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - glTexImage2D(GL_TEXTURE_2D, 0, 3, s->regs[R_TEXHRES], s->regs[R_TEXVRES], - 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb); - cpu_physical_memory_unmap(fb, fb_len, 0, fb_len); - - /* Set up texturing options */ - /* WARNING: - * Many cases of TMU2 masking are not supported by OpenGL. - * We only implement the most common ones: - * - full bilinear filtering vs. nearest texel - * - texture clamping vs. texture wrapping - */ - if ((s->regs[R_TEXHMASK] & 0x3f) > 0x20) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - if ((s->regs[R_TEXHMASK] >> 6) & s->regs[R_TEXHRES]) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - } - if ((s->regs[R_TEXVMASK] >> 6) & s->regs[R_TEXVRES]) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - - /* Translucency and decay */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - m = (float)(s->regs[R_BRIGHTNESS] + 1) / 64.0f; - glColor4f(m, m, m, (float)(s->regs[R_ALPHA] + 1) / 64.0f); - - /* Read the QEMU dest. framebuffer into the OpenGL framebuffer */ - fb_len = 2ULL * s->regs[R_DSTHRES] * s->regs[R_DSTVRES]; - fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, false); - if (fb == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - - glDrawPixels(s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, fb); - cpu_physical_memory_unmap(fb, fb_len, 0, fb_len); - glViewport(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES]); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, s->regs[R_DSTHRES], 0.0, s->regs[R_DSTVRES], -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - - /* Map the texture */ - mesh_len = MESH_MAXSIZE*MESH_MAXSIZE*sizeof(struct vertex); - mesh = cpu_physical_memory_map(s->regs[R_VERTICESADDR], &mesh_len, false); - if (mesh == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - - tmu2_gl_map((struct vertex *)mesh, - s->regs[R_TEXHRES], s->regs[R_TEXVRES], - s->regs[R_HMESHLAST], s->regs[R_VMESHLAST], - s->regs[R_DSTHOFFSET], s->regs[R_DSTVOFFSET], - s->regs[R_DSTSQUAREW], s->regs[R_DSTSQUAREH]); - cpu_physical_memory_unmap(mesh, mesh_len, 0, mesh_len); - - /* Write back the OpenGL framebuffer to the QEMU framebuffer */ - fb_len = 2ULL * s->regs[R_DSTHRES] * s->regs[R_DSTVRES]; - fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, true); - if (fb == NULL) { - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - return; - } - - glReadPixels(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, fb); - cpu_physical_memory_unmap(fb, fb_len, 1, fb_len); - - /* Free OpenGL allocs */ - glDeleteTextures(1, &texture); - glXMakeContextCurrent(s->dpy, None, None, NULL); - glXDestroyPbuffer(s->dpy, pbuffer); - - s->regs[R_CTL] &= ~CTL_START_BUSY; - - trace_milkymist_tmu2_pulse_irq(); - qemu_irq_pulse(s->irq); -} - -static uint64_t tmu2_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistTMU2State *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTL: - case R_HMESHLAST: - case R_VMESHLAST: - case R_BRIGHTNESS: - case R_CHROMAKEY: - case R_VERTICESADDR: - case R_TEXFBUF: - case R_TEXHRES: - case R_TEXVRES: - case R_TEXHMASK: - case R_TEXVMASK: - case R_DSTFBUF: - case R_DSTHRES: - case R_DSTVRES: - case R_DSTHOFFSET: - case R_DSTVOFFSET: - case R_DSTSQUAREW: - case R_DSTSQUAREH: - case R_ALPHA: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_tmu2: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_tmu2_memory_read(addr << 2, r); - - return r; -} - -static void tmu2_check_registers(MilkymistTMU2State *s) -{ - if (s->regs[R_BRIGHTNESS] > MAX_BRIGHTNESS) { - error_report("milkymist_tmu2: max brightness is %d", MAX_BRIGHTNESS); - } - - if (s->regs[R_ALPHA] > MAX_ALPHA) { - error_report("milkymist_tmu2: max alpha is %d", MAX_ALPHA); - } - - if (s->regs[R_VERTICESADDR] & 0x07) { - error_report("milkymist_tmu2: vertex mesh address has to be 64-bit " - "aligned"); - } - - if (s->regs[R_TEXFBUF] & 0x01) { - error_report("milkymist_tmu2: texture buffer address has to be " - "16-bit aligned"); - } -} - -static void tmu2_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistTMU2State *s = opaque; - - trace_milkymist_tmu2_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTL: - s->regs[addr] = value; - if (value & CTL_START_BUSY) { - tmu2_start(s); - } - break; - case R_BRIGHTNESS: - case R_HMESHLAST: - case R_VMESHLAST: - case R_CHROMAKEY: - case R_VERTICESADDR: - case R_TEXFBUF: - case R_TEXHRES: - case R_TEXVRES: - case R_TEXHMASK: - case R_TEXVMASK: - case R_DSTFBUF: - case R_DSTHRES: - case R_DSTVRES: - case R_DSTHOFFSET: - case R_DSTVOFFSET: - case R_DSTSQUAREW: - case R_DSTSQUAREH: - case R_ALPHA: - s->regs[addr] = value; - break; - - default: - error_report("milkymist_tmu2: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - tmu2_check_registers(s); -} - -static const MemoryRegionOps tmu2_mmio_ops = { - .read = tmu2_read, - .write = tmu2_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_tmu2_reset(DeviceState *d) -{ - MilkymistTMU2State *s = MILKYMIST_TMU2(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } -} - -static void milkymist_tmu2_init(Object *obj) -{ - MilkymistTMU2State *s = MILKYMIST_TMU2(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->regs_region, obj, &tmu2_mmio_ops, s, - "milkymist-tmu2", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); -} - -static void milkymist_tmu2_realize(DeviceState *dev, Error **errp) -{ - MilkymistTMU2State *s = MILKYMIST_TMU2(dev); - - if (tmu2_glx_init(s)) { - error_setg(errp, "tmu2_glx_init failed"); - } -} - -static const VMStateDescription vmstate_milkymist_tmu2 = { - .name = "milkymist-tmu2", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistTMU2State, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_tmu2_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_tmu2_realize; - dc->reset = milkymist_tmu2_reset; - dc->vmsd = &vmstate_milkymist_tmu2; -} - -static const TypeInfo milkymist_tmu2_info = { - .name = TYPE_MILKYMIST_TMU2, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistTMU2State), - .instance_init = milkymist_tmu2_init, - .class_init = milkymist_tmu2_class_init, -}; - -static void milkymist_tmu2_register_types(void) -{ - type_register_static(&milkymist_tmu2_info); -} - -type_init(milkymist_tmu2_register_types) - -DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq) -{ - DeviceState *dev; - Display *d; - GLXFBConfig *configs; - int nelements; - int ver_major, ver_minor; - - /* check that GLX will work */ - d = XOpenDisplay(NULL); - if (d == NULL) { - return NULL; - } - - if (!glXQueryVersion(d, &ver_major, &ver_minor)) { - /* - * Yeah, sometimes getting the GLX version can fail. - * Isn't X beautiful? - */ - XCloseDisplay(d); - return NULL; - } - - if ((ver_major < 1) || ((ver_major == 1) && (ver_minor < 3))) { - printf("Your GLX version is %d.%d," - "but TMU emulation needs at least 1.3. TMU disabled.\n", - ver_major, ver_minor); - XCloseDisplay(d); - return NULL; - } - - configs = glXChooseFBConfig(d, 0, glx_fbconfig_attr, &nelements); - if (configs == NULL) { - XCloseDisplay(d); - return NULL; - } - - XFree(configs); - XCloseDisplay(d); - - 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); - - return dev; -} diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c deleted file mode 100644 index e2c587e2df..0000000000 --- a/hw/display/milkymist-vgafb.c +++ /dev/null @@ -1,360 +0,0 @@ - -/* - * QEMU model of the Milkymist VGA framebuffer. - * - * Copyright (c) 2010-2012 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/vgafb.pdf - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/qdev-properties.h" -#include "hw/sysbus.h" -#include "trace.h" -#include "ui/console.h" -#include "framebuffer.h" -#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" -#include "milkymist-vgafb_template.h" -#define BITS 15 -#include "milkymist-vgafb_template.h" -#define BITS 16 -#include "milkymist-vgafb_template.h" -#define BITS 24 -#include "milkymist-vgafb_template.h" -#define BITS 32 -#include "milkymist-vgafb_template.h" - -enum { - R_CTRL = 0, - R_HRES, - R_HSYNC_START, - R_HSYNC_END, - R_HSCAN, - R_VRES, - R_VSYNC_START, - R_VSYNC_END, - R_VSCAN, - R_BASEADDRESS, - R_BASEADDRESS_ACT, - R_BURST_COUNT, - R_DDC, - R_SOURCE_CLOCK, - R_MAX -}; - -enum { - CTRL_RESET = (1<<0), -}; - -#define TYPE_MILKYMIST_VGAFB "milkymist-vgafb" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistVgafbState, MILKYMIST_VGAFB) - -struct MilkymistVgafbState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - MemoryRegionSection fbsection; - QemuConsole *con; - - int invalidate; - uint32_t fb_offset; - uint32_t fb_mask; - - uint32_t regs[R_MAX]; -}; - -static int vgafb_enabled(MilkymistVgafbState *s) -{ - return !(s->regs[R_CTRL] & CTRL_RESET); -} - -static void vgafb_update_display(void *opaque) -{ - MilkymistVgafbState *s = opaque; - SysBusDevice *sbd; - DisplaySurface *surface = qemu_console_surface(s->con); - int src_width; - int first = 0; - int last = 0; - drawfn fn; - - if (!vgafb_enabled(s)) { - return; - } - - sbd = SYS_BUS_DEVICE(s); - int dest_width = s->regs[R_HRES]; - - switch (surface_bits_per_pixel(surface)) { - case 0: - return; - case 8: - fn = draw_line_8; - break; - case 15: - fn = draw_line_15; - dest_width *= 2; - break; - case 16: - fn = draw_line_16; - dest_width *= 2; - break; - case 24: - fn = draw_line_24; - dest_width *= 3; - break; - case 32: - fn = draw_line_32; - dest_width *= 4; - break; - default: - hw_error("milkymist_vgafb: bad color depth\n"); - break; - } - - src_width = s->regs[R_HRES] * 2; - if (s->invalidate) { - framebuffer_update_memory_section(&s->fbsection, - sysbus_address_space(sbd), - s->regs[R_BASEADDRESS] + s->fb_offset, - s->regs[R_VRES], src_width); - } - - framebuffer_update_display(surface, &s->fbsection, - s->regs[R_HRES], - s->regs[R_VRES], - src_width, - dest_width, - 0, - s->invalidate, - fn, - NULL, - &first, &last); - - if (first >= 0) { - dpy_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1); - } - s->invalidate = 0; -} - -static void vgafb_invalidate_display(void *opaque) -{ - MilkymistVgafbState *s = opaque; - s->invalidate = 1; -} - -static void vgafb_resize(MilkymistVgafbState *s) -{ - if (!vgafb_enabled(s)) { - return; - } - - qemu_console_resize(s->con, s->regs[R_HRES], s->regs[R_VRES]); - s->invalidate = 1; -} - -static uint64_t vgafb_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistVgafbState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTRL: - case R_HRES: - case R_HSYNC_START: - case R_HSYNC_END: - case R_HSCAN: - case R_VRES: - case R_VSYNC_START: - case R_VSYNC_END: - case R_VSCAN: - case R_BASEADDRESS: - case R_BURST_COUNT: - case R_DDC: - case R_SOURCE_CLOCK: - r = s->regs[addr]; - break; - case R_BASEADDRESS_ACT: - r = s->regs[R_BASEADDRESS]; - break; - - default: - error_report("milkymist_vgafb: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_vgafb_memory_read(addr << 2, r); - - return r; -} - -static void vgafb_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistVgafbState *s = opaque; - - trace_milkymist_vgafb_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTRL: - s->regs[addr] = value; - vgafb_resize(s); - break; - case R_HSYNC_START: - case R_HSYNC_END: - case R_HSCAN: - case R_VSYNC_START: - case R_VSYNC_END: - case R_VSCAN: - case R_BURST_COUNT: - case R_DDC: - case R_SOURCE_CLOCK: - s->regs[addr] = value; - break; - case R_BASEADDRESS: - if (value & 0x1f) { - error_report("milkymist_vgafb: framebuffer base address have to " - "be 32 byte aligned"); - break; - } - s->regs[addr] = value & s->fb_mask; - s->invalidate = 1; - break; - case R_HRES: - case R_VRES: - s->regs[addr] = value; - vgafb_resize(s); - break; - case R_BASEADDRESS_ACT: - error_report("milkymist_vgafb: write to read-only register 0x" - TARGET_FMT_plx, addr << 2); - break; - - default: - error_report("milkymist_vgafb: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps vgafb_mmio_ops = { - .read = vgafb_read, - .write = vgafb_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_vgafb_reset(DeviceState *d) -{ - MilkymistVgafbState *s = MILKYMIST_VGAFB(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - /* defaults */ - s->regs[R_CTRL] = CTRL_RESET; - s->regs[R_HRES] = 640; - s->regs[R_VRES] = 480; - s->regs[R_BASEADDRESS] = 0; -} - -static const GraphicHwOps vgafb_ops = { - .invalidate = vgafb_invalidate_display, - .gfx_update = vgafb_update_display, -}; - -static void milkymist_vgafb_init(Object *obj) -{ - MilkymistVgafbState *s = MILKYMIST_VGAFB(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - - memory_region_init_io(&s->regs_region, OBJECT(s), &vgafb_mmio_ops, s, - "milkymist-vgafb", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); -} - -static void milkymist_vgafb_realize(DeviceState *dev, Error **errp) -{ - MilkymistVgafbState *s = MILKYMIST_VGAFB(dev); - - s->con = graphic_console_init(dev, 0, &vgafb_ops, s); -} - -static int vgafb_post_load(void *opaque, int version_id) -{ - vgafb_invalidate_display(opaque); - return 0; -} - -static const VMStateDescription vmstate_milkymist_vgafb = { - .name = "milkymist-vgafb", - .version_id = 1, - .minimum_version_id = 1, - .post_load = vgafb_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistVgafbState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_vgafb_properties[] = { - DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0), - DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_vgafb_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = milkymist_vgafb_reset; - dc->vmsd = &vmstate_milkymist_vgafb; - device_class_set_props(dc, milkymist_vgafb_properties); - dc->realize = milkymist_vgafb_realize; -} - -static const TypeInfo milkymist_vgafb_info = { - .name = TYPE_MILKYMIST_VGAFB, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistVgafbState), - .instance_init = milkymist_vgafb_init, - .class_init = milkymist_vgafb_class_init, -}; - -static void milkymist_vgafb_register_types(void) -{ - type_register_static(&milkymist_vgafb_info); -} - -type_init(milkymist_vgafb_register_types) diff --git a/hw/display/milkymist-vgafb_template.h b/hw/display/milkymist-vgafb_template.h deleted file mode 100644 index 96137f9709..0000000000 --- a/hw/display/milkymist-vgafb_template.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * QEMU model of the Milkymist VGA framebuffer. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - */ - -#if BITS == 8 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *to = rgb_to_pixel8(r, g, b); \ - to += 1; \ - } while (0) -#elif BITS == 15 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *(uint16_t *)to = rgb_to_pixel15(r, g, b); \ - to += 2; \ - } while (0) -#elif BITS == 16 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *(uint16_t *)to = rgb_to_pixel16(r, g, b); \ - to += 2; \ - } while (0) -#elif BITS == 24 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - uint32_t tmp = rgb_to_pixel24(r, g, b); \ - *(to++) = tmp & 0xff; \ - *(to++) = (tmp >> 8) & 0xff; \ - *(to++) = (tmp >> 16) & 0xff; \ - } while (0) -#elif BITS == 32 -#define COPY_PIXEL(to, r, g, b) \ - do { \ - *(uint32_t *)to = rgb_to_pixel32(r, g, b); \ - to += 4; \ - } while (0) -#else -#error unknown bit depth -#endif - -static void glue(draw_line_, BITS)(void *opaque, uint8_t *d, const uint8_t *s, - int width, int deststep) -{ - uint16_t rgb565; - uint8_t r, g, b; - - while (width--) { - rgb565 = lduw_be_p(s); - r = ((rgb565 >> 11) & 0x1f) << 3; - g = ((rgb565 >> 5) & 0x3f) << 2; - b = ((rgb565 >> 0) & 0x1f) << 3; - COPY_PIXEL(d, r, g, b); - s += 2; - } -} - -#undef BITS -#undef COPY_PIXEL diff --git a/hw/display/trace-events b/hw/display/trace-events index 957b8ba994..9fccca18a1 100644 --- a/hw/display/trace-events +++ b/hw/display/trace-events @@ -13,16 +13,6 @@ xenfb_input_connected(void *xendev, int abs_pointer_wanted) "%p abs %d" g364fb_read(uint64_t addr, uint32_t val) "read addr=0x%"PRIx64": 0x%x" g364fb_write(uint64_t addr, uint32_t new) "write addr=0x%"PRIx64": 0x%x" -# milkymist-tmu2.c -milkymist_tmu2_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_tmu2_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_tmu2_start(void) "Start TMU" -milkymist_tmu2_pulse_irq(void) "Pulse IRQ" - -# milkymist-vgafb.c -milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" - # vmware_vga.c vmware_value_read(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_value_write(uint32_t index, uint32_t value) "index %d, value 0x%x" diff --git a/hw/dma/meson.build b/hw/dma/meson.build index 5c78a4e05f..f3f0661bc3 100644 --- a/hw/dma/meson.build +++ b/hw/dma/meson.build @@ -1,4 +1,3 @@ -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')) diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c deleted file mode 100644 index cca1e9ec21..0000000000 --- a/hw/dma/puv3_dma.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * DMA device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#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" -OBJECT_DECLARE_SIMPLE_TYPE(PUV3DMAState, PUV3_DMA) - -struct PUV3DMAState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint32_t reg_CFG[PUV3_DMA_CH_NR]; -}; - -static uint64_t puv3_dma_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3DMAState *s = opaque; - uint32_t ret = 0; - - assert(PUV3_DMA_CH(offset) < PUV3_DMA_CH_NR); - - switch (offset & PUV3_DMA_CH_MASK) { - case 0x10: - ret = s->reg_CFG[PUV3_DMA_CH(offset)]; - break; - default: - 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; -} - -static void puv3_dma_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3DMAState *s = opaque; - - assert(PUV3_DMA_CH(offset) < PUV3_DMA_CH_NR); - - switch (offset & PUV3_DMA_CH_MASK) { - case 0x10: - s->reg_CFG[PUV3_DMA_CH(offset)] = value; - break; - default: - 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); -} - -static const MemoryRegionOps puv3_dma_ops = { - .read = puv3_dma_read, - .write = puv3_dma_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void puv3_dma_realize(DeviceState *dev, Error **errp) -{ - PUV3DMAState *s = PUV3_DMA(dev); - int i; - - for (i = 0; i < PUV3_DMA_CH_NR; i++) { - s->reg_CFG[i] = 0x0; - } - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_dma_ops, s, "puv3_dma", - PUV3_REGS_OFFSET); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); -} - -static void puv3_dma_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = puv3_dma_realize; -} - -static const TypeInfo puv3_dma_info = { - .name = TYPE_PUV3_DMA, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3DMAState), - .class_init = puv3_dma_class_init, -}; - -static void puv3_dma_register_type(void) -{ - type_register_static(&puv3_dma_info); -} - -type_init(puv3_dma_register_type) diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build index 79568f00ce..7bd6a57264 100644 --- a/hw/gpio/meson.build +++ b/hw/gpio/meson.build @@ -3,7 +3,6 @@ softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c')) softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.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')) diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c deleted file mode 100644 index e003ae505c..0000000000 --- a/hw/gpio/puv3_gpio.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * GPIO device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#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" -OBJECT_DECLARE_SIMPLE_TYPE(PUV3GPIOState, PUV3_GPIO) - -struct PUV3GPIOState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq irq[9]; - - uint32_t reg_GPLR; - uint32_t reg_GPDR; - uint32_t reg_GPIR; -}; - -static uint64_t puv3_gpio_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3GPIOState *s = opaque; - uint32_t ret = 0; - - switch (offset) { - case 0x00: - ret = s->reg_GPLR; - break; - case 0x04: - ret = s->reg_GPDR; - break; - case 0x20: - ret = s->reg_GPIR; - break; - default: - 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; -} - -static void puv3_gpio_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3GPIOState *s = opaque; - - DPRINTF("offset 0x%x, value 0x%x\n", offset, value); - switch (offset) { - case 0x04: - s->reg_GPDR = value; - break; - case 0x08: - if (s->reg_GPDR & value) { - s->reg_GPLR |= value; - } else { - 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 { - qemu_log_mask(LOG_GUEST_ERROR, "%s: Write gpio input port\n", - __func__); - } - break; - case 0x10: /* GRER */ - case 0x14: /* GFER */ - case 0x18: /* GEDR */ - break; - case 0x20: /* GPIR */ - s->reg_GPIR = value; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Bad write offset 0x%"HWADDR_PRIx"\n", - __func__, offset); - } -} - -static const MemoryRegionOps puv3_gpio_ops = { - .read = puv3_gpio_read, - .write = puv3_gpio_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void puv3_gpio_realize(DeviceState *dev, Error **errp) -{ - PUV3GPIOState *s = PUV3_GPIO(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - s->reg_GPLR = 0; - s->reg_GPDR = 0; - - /* FIXME: these irqs not handled yet */ - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW0]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW1]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW2]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW3]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW4]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW5]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW6]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOLOW7]); - sysbus_init_irq(sbd, &s->irq[PUV3_IRQS_GPIOHIGH]); - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio", - PUV3_REGS_OFFSET); - sysbus_init_mmio(sbd, &s->iomem); -} - -static void puv3_gpio_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = puv3_gpio_realize; -} - -static const TypeInfo puv3_gpio_info = { - .name = TYPE_PUV3_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3GPIOState), - .class_init = puv3_gpio_class_init, -}; - -static void puv3_gpio_register_type(void) -{ - type_register_static(&puv3_gpio_info); -} - -type_init(puv3_gpio_register_type) diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig index 09642a6dcb..8d120a25d5 100644 --- a/hw/i2c/Kconfig +++ b/hw/i2c/Kconfig @@ -28,3 +28,7 @@ config IMX_I2C config MPC_I2C bool select I2C + +config PCA954X + bool + select I2C diff --git a/hw/i2c/core.c b/hw/i2c/core.c index 21ec52ac5a..3a7bae311d 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -77,6 +77,30 @@ int i2c_bus_busy(I2CBus *bus) return !QLIST_EMPTY(&bus->current_devs); } +bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast, + I2CNodeList *current_devs) +{ + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; + I2CSlave *candidate = I2C_SLAVE(qdev); + I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(candidate); + + if (sc->match_and_add(candidate, address, broadcast, current_devs)) { + if (!broadcast) { + return true; + } + } + } + + /* + * If broadcast was true, and the list was full or empty, return true. If + * broadcast was false, return false. + */ + return broadcast; +} + /* TODO: Make this handle multiple masters. */ /* * Start or continue an i2c transaction. When this is called for the @@ -93,7 +117,6 @@ int i2c_bus_busy(I2CBus *bus) */ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) { - BusChild *kid; I2CSlaveClass *sc; I2CNode *node; bool bus_scanned = false; @@ -115,18 +138,8 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) * terminating the previous transaction. */ if (QLIST_EMPTY(&bus->current_devs)) { - QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { - DeviceState *qdev = kid->child; - I2CSlave *candidate = I2C_SLAVE(qdev); - if ((candidate->address == address) || (bus->broadcast)) { - node = g_malloc(sizeof(struct I2CNode)); - node->elt = candidate; - QLIST_INSERT_HEAD(&bus->current_devs, node, next); - if (!bus->broadcast) { - break; - } - } - } + /* Disregard whether devices were found. */ + (void)i2c_scan_bus(bus, address, bus->broadcast, &bus->current_devs); bus_scanned = true; } @@ -290,12 +303,28 @@ I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr) return dev; } +static bool i2c_slave_match(I2CSlave *candidate, uint8_t address, + bool broadcast, I2CNodeList *current_devs) +{ + if ((candidate->address == address) || (broadcast)) { + I2CNode *node = g_malloc(sizeof(struct I2CNode)); + node->elt = candidate; + QLIST_INSERT_HEAD(current_devs, node, next); + return true; + } + + /* Not found and not broadcast. */ + return false; +} + static void i2c_slave_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); + I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass); set_bit(DEVICE_CATEGORY_MISC, k->categories); k->bus_type = TYPE_I2C_BUS; device_class_set_props(k, i2c_props); + sc->match_and_add = i2c_slave_match; } static const TypeInfo i2c_slave_type_info = { diff --git a/hw/i2c/i2c_mux_pca954x.c b/hw/i2c/i2c_mux_pca954x.c new file mode 100644 index 0000000000..847c59921c --- /dev/null +++ b/hw/i2c/i2c_mux_pca954x.c @@ -0,0 +1,290 @@ +/* + * I2C multiplexer for PCA954x series of I2C multiplexer/switch chips. + * + * Copyright 2021 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 "qapi/error.h" +#include "hw/i2c/i2c.h" +#include "hw/i2c/i2c_mux_pca954x.h" +#include "hw/i2c/smbus_slave.h" +#include "hw/qdev-core.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/queue.h" +#include "qom/object.h" +#include "trace.h" + +#define PCA9548_CHANNEL_COUNT 8 +#define PCA9546_CHANNEL_COUNT 4 + +/* + * struct Pca954xChannel - The i2c mux device will have N of these states + * that own the i2c channel bus. + * @bus: The owned channel bus. + * @enabled: Is this channel active? + */ +typedef struct Pca954xChannel { + SysBusDevice parent; + + I2CBus *bus; + + bool enabled; +} Pca954xChannel; + +#define TYPE_PCA954X_CHANNEL "pca954x-channel" +#define PCA954X_CHANNEL(obj) \ + OBJECT_CHECK(Pca954xChannel, (obj), TYPE_PCA954X_CHANNEL) + +/* + * struct Pca954xState - The pca954x state object. + * @control: The value written to the mux control. + * @channel: The set of i2c channel buses that act as channels which own the + * i2c children. + */ +typedef struct Pca954xState { + SMBusDevice parent; + + uint8_t control; + + /* The channel i2c buses. */ + Pca954xChannel channel[PCA9548_CHANNEL_COUNT]; +} Pca954xState; + +/* + * struct Pca954xClass - The pca954x class object. + * @nchans: The number of i2c channels this device has. + */ +typedef struct Pca954xClass { + SMBusDeviceClass parent; + + uint8_t nchans; +} Pca954xClass; + +#define TYPE_PCA954X "pca954x" +OBJECT_DECLARE_TYPE(Pca954xState, Pca954xClass, PCA954X) + +/* + * For each channel, if it's enabled, recursively call match on those children. + */ +static bool pca954x_match(I2CSlave *candidate, uint8_t address, + bool broadcast, + I2CNodeList *current_devs) +{ + Pca954xState *mux = PCA954X(candidate); + Pca954xClass *mc = PCA954X_GET_CLASS(mux); + int i; + + /* They are talking to the mux itself (or all devices enabled). */ + if ((candidate->address == address) || broadcast) { + I2CNode *node = g_malloc(sizeof(struct I2CNode)); + node->elt = candidate; + QLIST_INSERT_HEAD(current_devs, node, next); + if (!broadcast) { + return true; + } + } + + for (i = 0; i < mc->nchans; i++) { + if (!mux->channel[i].enabled) { + continue; + } + + if (i2c_scan_bus(mux->channel[i].bus, address, broadcast, + current_devs)) { + if (!broadcast) { + return true; + } + } + } + + /* If we arrived here we didn't find a match, return broadcast. */ + return broadcast; +} + +static void pca954x_enable_channel(Pca954xState *s, uint8_t enable_mask) +{ + Pca954xClass *mc = PCA954X_GET_CLASS(s); + int i; + + /* + * For each channel, check if their bit is set in enable_mask and if yes, + * enable it, otherwise disable, hide it. + */ + for (i = 0; i < mc->nchans; i++) { + if (enable_mask & (1 << i)) { + s->channel[i].enabled = true; + } else { + s->channel[i].enabled = false; + } + } +} + +static void pca954x_write(Pca954xState *s, uint8_t data) +{ + s->control = data; + pca954x_enable_channel(s, data); + + trace_pca954x_write_bytes(data); +} + +static int pca954x_write_data(SMBusDevice *d, uint8_t *buf, uint8_t len) +{ + Pca954xState *s = PCA954X(d); + + if (len == 0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: writing empty data\n", __func__); + return -1; + } + + /* + * len should be 1, because they write one byte to enable/disable channels. + */ + if (len > 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: extra data after channel selection mask\n", + __func__); + return -1; + } + + pca954x_write(s, buf[0]); + return 0; +} + +static uint8_t pca954x_read_byte(SMBusDevice *d) +{ + Pca954xState *s = PCA954X(d); + uint8_t data = s->control; + trace_pca954x_read_data(data); + return data; +} + +static void pca954x_enter_reset(Object *obj, ResetType type) +{ + Pca954xState *s = PCA954X(obj); + /* Reset will disable all channels. */ + pca954x_write(s, 0); +} + +I2CBus *pca954x_i2c_get_bus(I2CSlave *mux, uint8_t channel) +{ + Pca954xClass *pc = PCA954X_GET_CLASS(mux); + Pca954xState *pca954x = PCA954X(mux); + + g_assert(channel < pc->nchans); + return I2C_BUS(qdev_get_child_bus(DEVICE(&pca954x->channel[channel]), + "i2c-bus")); +} + +static void pca954x_channel_init(Object *obj) +{ + Pca954xChannel *s = PCA954X_CHANNEL(obj); + s->bus = i2c_init_bus(DEVICE(s), "i2c-bus"); + + /* Start all channels as disabled. */ + s->enabled = false; +} + +static void pca954x_channel_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + dc->desc = "Pca954x Channel"; +} + +static void pca9546_class_init(ObjectClass *klass, void *data) +{ + Pca954xClass *s = PCA954X_CLASS(klass); + s->nchans = PCA9546_CHANNEL_COUNT; +} + +static void pca9548_class_init(ObjectClass *klass, void *data) +{ + Pca954xClass *s = PCA954X_CLASS(klass); + s->nchans = PCA9548_CHANNEL_COUNT; +} + +static void pca954x_realize(DeviceState *dev, Error **errp) +{ + Pca954xState *s = PCA954X(dev); + Pca954xClass *c = PCA954X_GET_CLASS(s); + int i; + + /* SMBus modules. Cannot fail. */ + for (i = 0; i < c->nchans; i++) { + sysbus_realize(SYS_BUS_DEVICE(&s->channel[i]), &error_abort); + } +} + +static void pca954x_init(Object *obj) +{ + Pca954xState *s = PCA954X(obj); + Pca954xClass *c = PCA954X_GET_CLASS(obj); + int i; + + /* Only initialize the children we expect. */ + for (i = 0; i < c->nchans; i++) { + object_initialize_child(obj, "channel[*]", &s->channel[i], + TYPE_PCA954X_CHANNEL); + } +} + +static void pca954x_class_init(ObjectClass *klass, void *data) +{ + I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + SMBusDeviceClass *k = SMBUS_DEVICE_CLASS(klass); + + sc->match_and_add = pca954x_match; + + rc->phases.enter = pca954x_enter_reset; + + dc->desc = "Pca954x i2c-mux"; + dc->realize = pca954x_realize; + + k->write_data = pca954x_write_data; + k->receive_byte = pca954x_read_byte; +} + +static const TypeInfo pca954x_info[] = { + { + .name = TYPE_PCA954X, + .parent = TYPE_SMBUS_DEVICE, + .instance_size = sizeof(Pca954xState), + .instance_init = pca954x_init, + .class_size = sizeof(Pca954xClass), + .class_init = pca954x_class_init, + .abstract = true, + }, + { + .name = TYPE_PCA9546, + .parent = TYPE_PCA954X, + .class_init = pca9546_class_init, + }, + { + .name = TYPE_PCA9548, + .parent = TYPE_PCA954X, + .class_init = pca9548_class_init, + }, + { + .name = TYPE_PCA954X_CHANNEL, + .parent = TYPE_SYS_BUS_DEVICE, + .class_init = pca954x_channel_class_init, + .instance_size = sizeof(Pca954xChannel), + .instance_init = pca954x_channel_init, + } +}; + +DEFINE_TYPES(pca954x_info) diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index cdcd694a7f..dd3aef02b2 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -14,4 +14,5 @@ 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')) +i2c_ss.add(when: 'CONFIG_PCA954X', if_true: files('i2c_mux_pca954x.c')) softmmu_ss.add_all(when: 'CONFIG_I2C', if_true: i2c_ss) diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events index 82fe6f965f..82f19e6a2d 100644 --- a/hw/i2c/trace-events +++ b/hw/i2c/trace-events @@ -26,3 +26,8 @@ npcm7xx_smbus_recv_byte(const char *id, uint8_t value) "%s recv byte: 0x%02x" npcm7xx_smbus_stop(const char *id) "%s stopping" npcm7xx_smbus_nack(const char *id) "%s nacking" npcm7xx_smbus_recv_fifo(const char *id, uint8_t received, uint8_t expected) "%s recv fifo: received %u, expected %u" + +# i2c-mux-pca954x.c + +pca954x_write_bytes(uint8_t value) "PCA954X write data: 0x%02x" +pca954x_read_data(uint8_t value) "PCA954X read data: 0x%02x" diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index bfecb0038c..80bee00da6 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1815,6 +1815,7 @@ build_hpet(GArray *table_data, BIOSLinker *linker, const char *oem_id, const char *oem_table_id) { Acpi20Hpet *hpet; + int hpet_start = table_data->len; hpet = acpi_data_push(table_data, sizeof(*hpet)); /* Note timer_block_id value must be kept in sync with value advertised by @@ -1823,13 +1824,15 @@ build_hpet(GArray *table_data, BIOSLinker *linker, const char *oem_id, hpet->timer_block_id = cpu_to_le32(0x8086a201); hpet->addr.address = cpu_to_le64(HPET_BASE); build_header(linker, table_data, - (void *)hpet, "HPET", sizeof(*hpet), 1, oem_id, oem_table_id); + (void *)(table_data->data + hpet_start), + "HPET", sizeof(*hpet), 1, oem_id, oem_table_id); } static void build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, const char *oem_id, const char *oem_table_id) { + int tcpa_start = table_data->len; Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa); unsigned log_addr_size = sizeof(tcpa->log_area_start_address); unsigned log_addr_offset = @@ -1848,7 +1851,8 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog, ACPI_BUILD_TPMLOG_FILE, 0); build_header(linker, table_data, - (void *)tcpa, "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id); + (void *)(table_data->data + tcpa_start), + "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id); } #define HOLE_640K_START (640 * KiB) diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 74a93a5d93..2801dff97c 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -99,7 +99,7 @@ static uint64_t amdvi_readq(AMDVIState *s, hwaddr addr) } /* internal write */ -static void amdvi_writeq_raw(AMDVIState *s, uint64_t val, hwaddr addr) +static void amdvi_writeq_raw(AMDVIState *s, hwaddr addr, uint64_t val) { stq_le_p(&s->mmior[addr], val); } @@ -382,7 +382,7 @@ static void amdvi_completion_wait(AMDVIState *s, uint64_t *cmd) } /* set completion interrupt */ if (extract64(cmd[0], 1, 1)) { - amdvi_test_mask(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_COMP_INT); + amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_COMP_INT); /* generate interrupt */ amdvi_generate_msi_interrupt(s); } @@ -553,7 +553,7 @@ static void amdvi_cmdbuf_run(AMDVIState *s) trace_amdvi_command_exec(s->cmdbuf_head, s->cmdbuf_tail, s->cmdbuf); amdvi_cmdbuf_exec(s); s->cmdbuf_head += AMDVI_COMMAND_SIZE; - amdvi_writeq_raw(s, s->cmdbuf_head, AMDVI_MMIO_COMMAND_HEAD); + amdvi_writeq_raw(s, AMDVI_MMIO_COMMAND_HEAD, s->cmdbuf_head); /* wrap head pointer */ if (s->cmdbuf_head >= s->cmdbuf_len * AMDVI_COMMAND_SIZE) { @@ -860,8 +860,8 @@ static inline uint8_t get_pte_translation_mode(uint64_t pte) static inline uint64_t pte_override_page_mask(uint64_t pte) { - uint8_t page_mask = 12; - uint64_t addr = (pte & AMDVI_DEV_PT_ROOT_MASK) ^ AMDVI_DEV_PT_ROOT_MASK; + uint8_t page_mask = 13; + uint64_t addr = (pte & AMDVI_DEV_PT_ROOT_MASK) >> 12; /* find the first zero bit */ while (addr & 1) { page_mask++; diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index e48a54fa36..4e68d5dea4 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -22,6 +22,7 @@ #include "hw/nvram/fw_cfg.h" #include "e820_memory_layout.h" #include "kvm/kvm_i386.h" +#include "qapi/error.h" #include CONFIG_DEVICES struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; @@ -78,7 +79,8 @@ void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg) } smbios_get_tables(ms, mem_array, array_count, &smbios_tables, &smbios_tables_len, - &smbios_anchor, &smbios_anchor_len); + &smbios_anchor, &smbios_anchor_len, + &error_fatal); g_free(mem_array); if (smbios_anchor) { diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c index e82b7dcdd2..bd47c3d672 100644 --- a/hw/i386/xen/xen-mapcache.c +++ b/hw/i386/xen/xen-mapcache.c @@ -169,7 +169,8 @@ static void xen_remap_bucket(MapCacheEntry *entry, if (entry->vaddr_base != NULL) { if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) { - ram_block_notify_remove(entry->vaddr_base, entry->size); + ram_block_notify_remove(entry->vaddr_base, entry->size, + entry->size); } /* @@ -224,7 +225,7 @@ static void xen_remap_bucket(MapCacheEntry *entry, } if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) { - ram_block_notify_add(vaddr_base, size); + ram_block_notify_add(vaddr_base, size, size); } entry->vaddr_base = vaddr_base; @@ -465,7 +466,7 @@ static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer) } pentry->next = entry->next; - ram_block_notify_remove(entry->vaddr_base, entry->size); + ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size); if (munmap(entry->vaddr_base, entry->size) != 0) { perror("unmap fails"); exit(-1); diff --git a/hw/input/meson.build b/hw/input/meson.build index 0042c3f0dc..8deb011d4a 100644 --- a/hw/input/meson.build +++ b/hw/input/meson.build @@ -13,7 +13,6 @@ 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 deleted file mode 100644 index d885c708d7..0000000000 --- a/hw/input/milkymist-softusb.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * QEMU model of the Milkymist SoftUSB block. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * not available yet - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "ui/console.h" -#include "hw/input/hid.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -enum { - R_CTRL = 0, - R_MAX -}; - -enum { - CTRL_RESET = (1<<0), -}; - -#define COMLOC_DEBUG_PRODUCE 0x1000 -#define COMLOC_DEBUG_BASE 0x1001 -#define COMLOC_MEVT_PRODUCE 0x1101 -#define COMLOC_MEVT_BASE 0x1102 -#define COMLOC_KEVT_PRODUCE 0x1142 -#define COMLOC_KEVT_BASE 0x1143 - -#define TYPE_MILKYMIST_SOFTUSB "milkymist-softusb" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistSoftUsbState, MILKYMIST_SOFTUSB) - -struct MilkymistSoftUsbState { - SysBusDevice parent_obj; - - HIDState hid_kbd; - HIDState hid_mouse; - - MemoryRegion regs_region; - MemoryRegion pmem; - MemoryRegion dmem; - qemu_irq irq; - - void *pmem_ptr; - void *dmem_ptr; - - /* device properties */ - uint32_t pmem_size; - uint32_t dmem_size; - - /* device registers */ - uint32_t regs[R_MAX]; - - /* mouse state */ - uint8_t mouse_hid_buffer[4]; - - /* keyboard state */ - uint8_t kbd_hid_buffer[8]; -}; - -static uint64_t softusb_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistSoftUsbState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTRL: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_softusb: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_softusb_memory_read(addr << 2, r); - - return r; -} - -static void -softusb_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistSoftUsbState *s = opaque; - - trace_milkymist_softusb_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTRL: - s->regs[addr] = value; - break; - - default: - error_report("milkymist_softusb: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps softusb_mmio_ops = { - .read = softusb_read, - .write = softusb_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static inline void softusb_read_dmem(MilkymistSoftUsbState *s, - uint32_t offset, uint8_t *buf, uint32_t len) -{ - if (offset + len >= s->dmem_size) { - error_report("milkymist_softusb: read dmem out of bounds " - "at offset 0x%x, len %d", offset, len); - memset(buf, 0, len); - return; - } - - memcpy(buf, s->dmem_ptr + offset, len); -} - -static inline void softusb_write_dmem(MilkymistSoftUsbState *s, - uint32_t offset, uint8_t *buf, uint32_t len) -{ - if (offset + len >= s->dmem_size) { - error_report("milkymist_softusb: write dmem out of bounds " - "at offset 0x%x, len %d", offset, len); - return; - } - - memcpy(s->dmem_ptr + offset, buf, len); -} - -static void softusb_mouse_changed(MilkymistSoftUsbState *s) -{ - uint8_t m; - - softusb_read_dmem(s, COMLOC_MEVT_PRODUCE, &m, 1); - trace_milkymist_softusb_mevt(m); - softusb_write_dmem(s, COMLOC_MEVT_BASE + 4 * m, s->mouse_hid_buffer, 4); - m = (m + 1) & 0xf; - softusb_write_dmem(s, COMLOC_MEVT_PRODUCE, &m, 1); - - trace_milkymist_softusb_pulse_irq(); - qemu_irq_pulse(s->irq); -} - -static void softusb_kbd_changed(MilkymistSoftUsbState *s) -{ - uint8_t m; - - softusb_read_dmem(s, COMLOC_KEVT_PRODUCE, &m, 1); - trace_milkymist_softusb_kevt(m); - softusb_write_dmem(s, COMLOC_KEVT_BASE + 8 * m, s->kbd_hid_buffer, 8); - m = (m + 1) & 0x7; - softusb_write_dmem(s, COMLOC_KEVT_PRODUCE, &m, 1); - - trace_milkymist_softusb_pulse_irq(); - qemu_irq_pulse(s->irq); -} - -static void softusb_kbd_hid_datain(HIDState *hs) -{ - MilkymistSoftUsbState *s = container_of(hs, MilkymistSoftUsbState, hid_kbd); - int len; - - /* if device is in reset, do nothing */ - if (s->regs[R_CTRL] & CTRL_RESET) { - return; - } - - while (hid_has_events(hs)) { - len = hid_keyboard_poll(hs, s->kbd_hid_buffer, - sizeof(s->kbd_hid_buffer)); - - if (len == 8) { - softusb_kbd_changed(s); - } - } -} - -static void softusb_mouse_hid_datain(HIDState *hs) -{ - MilkymistSoftUsbState *s = - container_of(hs, MilkymistSoftUsbState, hid_mouse); - int len; - - /* if device is in reset, do nothing */ - if (s->regs[R_CTRL] & CTRL_RESET) { - return; - } - - while (hid_has_events(hs)) { - len = hid_pointer_poll(hs, s->mouse_hid_buffer, - sizeof(s->mouse_hid_buffer)); - - if (len == 4) { - softusb_mouse_changed(s); - } - } -} - -static void milkymist_softusb_reset(DeviceState *d) -{ - MilkymistSoftUsbState *s = MILKYMIST_SOFTUSB(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - memset(s->kbd_hid_buffer, 0, sizeof(s->kbd_hid_buffer)); - memset(s->mouse_hid_buffer, 0, sizeof(s->mouse_hid_buffer)); - - hid_reset(&s->hid_kbd); - hid_reset(&s->hid_mouse); - - /* defaults */ - s->regs[R_CTRL] = CTRL_RESET; -} - -static void milkymist_softusb_realize(DeviceState *dev, Error **errp) -{ - MilkymistSoftUsbState *s = MILKYMIST_SOFTUSB(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - sysbus_init_irq(sbd, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(s), &softusb_mmio_ops, s, - "milkymist-softusb", R_MAX * 4); - sysbus_init_mmio(sbd, &s->regs_region); - - /* register pmem and dmem */ - memory_region_init_ram_nomigrate(&s->pmem, OBJECT(s), "milkymist-softusb.pmem", - s->pmem_size, &error_fatal); - vmstate_register_ram_global(&s->pmem); - s->pmem_ptr = memory_region_get_ram_ptr(&s->pmem); - sysbus_init_mmio(sbd, &s->pmem); - memory_region_init_ram_nomigrate(&s->dmem, OBJECT(s), "milkymist-softusb.dmem", - s->dmem_size, &error_fatal); - vmstate_register_ram_global(&s->dmem); - s->dmem_ptr = memory_region_get_ram_ptr(&s->dmem); - sysbus_init_mmio(sbd, &s->dmem); - - hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain); - hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain); -} - -static const VMStateDescription vmstate_milkymist_softusb = { - .name = "milkymist-softusb", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistSoftUsbState, R_MAX), - VMSTATE_HID_KEYBOARD_DEVICE(hid_kbd, MilkymistSoftUsbState), - VMSTATE_HID_POINTER_DEVICE(hid_mouse, MilkymistSoftUsbState), - VMSTATE_BUFFER(kbd_hid_buffer, MilkymistSoftUsbState), - VMSTATE_BUFFER(mouse_hid_buffer, MilkymistSoftUsbState), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_softusb_properties[] = { - DEFINE_PROP_UINT32("pmem_size", MilkymistSoftUsbState, pmem_size, 0x00001000), - DEFINE_PROP_UINT32("dmem_size", MilkymistSoftUsbState, dmem_size, 0x00002000), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_softusb_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_softusb_realize; - dc->reset = milkymist_softusb_reset; - dc->vmsd = &vmstate_milkymist_softusb; - device_class_set_props(dc, milkymist_softusb_properties); -} - -static const TypeInfo milkymist_softusb_info = { - .name = TYPE_MILKYMIST_SOFTUSB, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistSoftUsbState), - .class_init = milkymist_softusb_class_init, -}; - -static void milkymist_softusb_register_types(void) -{ - type_register_static(&milkymist_softusb_info); -} - -type_init(milkymist_softusb_register_types) diff --git a/hw/input/trace-events b/hw/input/trace-events index 1dd8ad6018..33741e74f5 100644 --- a/hw/input/trace-events +++ b/hw/input/trace-events @@ -44,13 +44,6 @@ ps2_mouse_reset(void *opaque) "%p" ps2_kbd_init(void *s) "%p" ps2_mouse_init(void *s) "%p" -# milkymist-softusb.c -milkymist_softusb_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_softusb_mevt(uint8_t m) "m %d" -milkymist_softusb_kevt(uint8_t m) "m %d" -milkymist_softusb_pulse_irq(void) "Pulse IRQ" - # hid.c hid_kbd_queue_full(void) "queue full" hid_kbd_queue_empty(void) "queue empty" diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c index 85daf73f1a..137efba57b 100644 --- a/hw/input/virtio-input-host.c +++ b/hw/input/virtio-input-host.c @@ -193,13 +193,16 @@ static void virtio_input_host_handle_status(VirtIOInput *vinput, { VirtIOInputHost *vih = VIRTIO_INPUT_HOST(vinput); struct input_event evdev; + struct timeval tval; int rc; - if (gettimeofday(&evdev.time, NULL)) { + if (gettimeofday(&tval, NULL)) { perror("virtio_input_host_handle_status: gettimeofday"); return; } + evdev.input_event_sec = tval.tv_sec; + evdev.input_event_usec = tval.tv_usec; evdev.type = le16_to_cpu(event->type); evdev.code = le16_to_cpu(event->code); evdev.value = le32_to_cpu(event->value); diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c deleted file mode 100644 index 991a90bc99..0000000000 --- a/hw/intc/lm32_pic.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * LatticeMico32 CPU interrupt controller logic. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" - -#include "migration/vmstate.h" -#include "monitor/monitor.h" -#include "qemu/module.h" -#include "hw/sysbus.h" -#include "trace.h" -#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" -OBJECT_DECLARE_SIMPLE_TYPE(LM32PicState, LM32_PIC) - -struct LM32PicState { - SysBusDevice parent_obj; - - qemu_irq parent_irq; - uint32_t im; /* interrupt mask */ - uint32_t ip; /* interrupt pending */ - uint32_t irq_state; - - /* statistics */ - uint64_t stats_irq_count[32]; -}; - -static void update_irq(LM32PicState *s) -{ - s->ip |= s->irq_state; - - if (s->ip & s->im) { - trace_lm32_pic_raise_irq(); - qemu_irq_raise(s->parent_irq); - } else { - trace_lm32_pic_lower_irq(); - qemu_irq_lower(s->parent_irq); - } -} - -static void irq_handler(void *opaque, int irq, int level) -{ - LM32PicState *s = opaque; - - assert(irq < 32); - trace_lm32_pic_interrupt(irq, level); - - if (level) { - s->irq_state |= (1 << irq); - s->stats_irq_count[irq]++; - } else { - s->irq_state &= ~(1 << irq); - } - - update_irq(s); -} - -void lm32_pic_set_im(DeviceState *d, uint32_t im) -{ - LM32PicState *s = LM32_PIC(d); - - trace_lm32_pic_set_im(im); - s->im = im; - - update_irq(s); -} - -void lm32_pic_set_ip(DeviceState *d, uint32_t ip) -{ - LM32PicState *s = LM32_PIC(d); - - trace_lm32_pic_set_ip(ip); - - /* ack interrupt */ - s->ip &= ~ip; - - update_irq(s); -} - -uint32_t lm32_pic_get_im(DeviceState *d) -{ - LM32PicState *s = LM32_PIC(d); - - trace_lm32_pic_get_im(s->im); - return s->im; -} - -uint32_t lm32_pic_get_ip(DeviceState *d) -{ - LM32PicState *s = LM32_PIC(d); - - trace_lm32_pic_get_ip(s->ip); - return s->ip; -} - -static void pic_reset(DeviceState *d) -{ - LM32PicState *s = LM32_PIC(d); - int i; - - s->im = 0; - s->ip = 0; - s->irq_state = 0; - for (i = 0; i < 32; i++) { - s->stats_irq_count[i] = 0; - } -} - -static bool lm32_get_statistics(InterruptStatsProvider *obj, - uint64_t **irq_counts, unsigned int *nb_irqs) -{ - LM32PicState *s = LM32_PIC(obj); - *irq_counts = s->stats_irq_count; - *nb_irqs = ARRAY_SIZE(s->stats_irq_count); - return true; -} - -static void lm32_print_info(InterruptStatsProvider *obj, Monitor *mon) -{ - LM32PicState *s = LM32_PIC(obj); - monitor_printf(mon, "lm32-pic: im=%08x ip=%08x irq_state=%08x\n", - s->im, s->ip, s->irq_state); -} - -static void lm32_pic_init(Object *obj) -{ - DeviceState *dev = DEVICE(obj); - LM32PicState *s = LM32_PIC(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - - qdev_init_gpio_in(dev, irq_handler, 32); - sysbus_init_irq(sbd, &s->parent_irq); -} - -static const VMStateDescription vmstate_lm32_pic = { - .name = "lm32-pic", - .version_id = 2, - .minimum_version_id = 2, - .fields = (VMStateField[]) { - VMSTATE_UINT32(im, LM32PicState), - VMSTATE_UINT32(ip, LM32PicState), - VMSTATE_UINT32(irq_state, LM32PicState), - VMSTATE_UINT64_ARRAY(stats_irq_count, LM32PicState, 32), - VMSTATE_END_OF_LIST() - } -}; - -static void lm32_pic_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); - - dc->reset = pic_reset; - dc->vmsd = &vmstate_lm32_pic; - ic->get_statistics = lm32_get_statistics; - ic->print_info = lm32_print_info; -} - -static const TypeInfo lm32_pic_info = { - .name = TYPE_LM32_PIC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LM32PicState), - .instance_init = lm32_pic_init, - .class_init = lm32_pic_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_INTERRUPT_STATS_PROVIDER }, - { } - }, -}; - -static void lm32_pic_register_types(void) -{ - type_register_static(&lm32_pic_info); -} - -type_init(lm32_pic_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 1c299039f6..6e52a166e3 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -14,10 +14,8 @@ 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_DEVICES', 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')) diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c deleted file mode 100644 index 65226f5e7c..0000000000 --- a/hw/intc/puv3_intc.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * INTC device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#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" -OBJECT_DECLARE_SIMPLE_TYPE(PUV3INTCState, PUV3_INTC) - -struct PUV3INTCState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq parent_irq; - - uint32_t reg_ICMR; - uint32_t reg_ICPR; -}; - -/* Update interrupt status after enabled or pending bits have been changed. */ -static void puv3_intc_update(PUV3INTCState *s) -{ - if (s->reg_ICMR & s->reg_ICPR) { - qemu_irq_raise(s->parent_irq); - } else { - qemu_irq_lower(s->parent_irq); - } -} - -/* Process a change in an external INTC input. */ -static void puv3_intc_handler(void *opaque, int irq, int level) -{ - PUV3INTCState *s = opaque; - - DPRINTF("irq 0x%x, level 0x%x\n", irq, level); - if (level) { - s->reg_ICPR |= (1 << irq); - } else { - s->reg_ICPR &= ~(1 << irq); - } - puv3_intc_update(s); -} - -static uint64_t puv3_intc_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3INTCState *s = opaque; - uint32_t ret = 0; - - switch (offset) { - case 0x04: /* INTC_ICMR */ - ret = s->reg_ICMR; - break; - case 0x0c: /* INTC_ICIP */ - ret = s->reg_ICPR; /* the same value with ICPR */ - break; - default: - 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; -} - -static void puv3_intc_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3INTCState *s = opaque; - - DPRINTF("offset 0x%x, value 0x%x\n", offset, value); - switch (offset) { - case 0x00: /* INTC_ICLR */ - case 0x14: /* INTC_ICCR */ - break; - case 0x04: /* INTC_ICMR */ - s->reg_ICMR = value; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Bad write offset 0x%"HWADDR_PRIx"\n", - __func__, offset); - return; - } - puv3_intc_update(s); -} - -static const MemoryRegionOps puv3_intc_ops = { - .read = puv3_intc_read, - .write = puv3_intc_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void puv3_intc_realize(DeviceState *dev, Error **errp) -{ - PUV3INTCState *s = PUV3_INTC(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - qdev_init_gpio_in(dev, puv3_intc_handler, PUV3_IRQS_NR); - sysbus_init_irq(sbd, &s->parent_irq); - - s->reg_ICMR = 0; - s->reg_ICPR = 0; - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_intc_ops, s, "puv3_intc", - PUV3_REGS_OFFSET); - sysbus_init_mmio(sbd, &s->iomem); -} - -static void puv3_intc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = puv3_intc_realize; -} - -static const TypeInfo puv3_intc_info = { - .name = TYPE_PUV3_INTC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3INTCState), - .class_init = puv3_intc_class_init, -}; - -static void puv3_intc_register_type(void) -{ - type_register_static(&puv3_intc_info); -} - -type_init(puv3_intc_register_type) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index c9ab17234b..626bb554b2 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -51,15 +51,6 @@ grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64 grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" -# lm32_pic.c -lm32_pic_raise_irq(void) "Raise CPU interrupt" -lm32_pic_lower_irq(void) "Lower CPU interrupt" -lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d" -lm32_pic_set_im(uint32_t im) "im 0x%08x" -lm32_pic_set_ip(uint32_t ip) "ip 0x%08x" -lm32_pic_get_im(uint32_t im) "im 0x%08x" -lm32_pic_get_ip(uint32_t ip) "ip 0x%08x" - # xics.c xics_icp_check_ipi(int server, uint8_t mfrr) "CPU %d can take IPI mfrr=0x%x" xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR 0x%"PRIx32"->0x%"PRIx32 diff --git a/hw/lm32/Kconfig b/hw/lm32/Kconfig deleted file mode 100644 index 8ac94205d7..0000000000 --- a/hw/lm32/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -config LM32_DEVICES - bool - select PTIMER - -config MILKYMIST - bool - # FIXME: disabling it results in compile-time errors - select MILKYMIST_TMU2 if OPENGL && X11 - select PFLASH_CFI01 - select FRAMEBUFFER - select SD - select USB_OHCI - select LM32_DEVICES - -config LM32_EVR - bool - select LM32_DEVICES - select PFLASH_CFI02 diff --git a/hw/lm32/lm32.h b/hw/lm32/lm32.h deleted file mode 100644 index 7b4f6255b9..0000000000 --- a/hw/lm32/lm32.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef HW_LM32_H -#define HW_LM32_H - -#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_new("lm32-pic"); - d = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(d, &error_fatal); - sysbus_connect_irq(d, 0, cpu_irq); - - return dev; -} - -static inline DeviceState *lm32_juart_init(Chardev *chr) -{ - DeviceState *dev; - - dev = qdev_new(TYPE_LM32_JUART); - qdev_prop_set_chr(dev, "chardev", chr); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - - return dev; -} - -static inline DeviceState *lm32_uart_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new("lm32-uart"); - s = SYS_BUS_DEVICE(dev); - qdev_prop_set_chr(dev, "chardev", chr); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, addr); - sysbus_connect_irq(s, 0, irq); - return dev; -} - -#endif diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c deleted file mode 100644 index 2961e4c2b4..0000000000 --- a/hw/lm32/lm32_boards.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * QEMU models for LatticeMico32 uclinux and evr32 boards. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "qemu/units.h" -#include "qemu/cutils.h" -#include "qemu/error-report.h" -#include "cpu.h" -#include "hw/sysbus.h" -#include "hw/irq.h" -#include "hw/block/flash.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "elf.h" -#include "lm32_hwsetup.h" -#include "lm32.h" -#include "sysemu/reset.h" -#include "sysemu/sysemu.h" - -typedef struct { - LM32CPU *cpu; - hwaddr bootstrap_pc; - hwaddr flash_base; - hwaddr hwsetup_base; - hwaddr initrd_base; - size_t initrd_size; - hwaddr cmdline_base; -} ResetInfo; - -static void cpu_irq_handler(void *opaque, int irq, int level) -{ - LM32CPU *cpu = opaque; - CPUState *cs = CPU(cpu); - - if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } -} - -static void main_cpu_reset(void *opaque) -{ - ResetInfo *reset_info = opaque; - CPULM32State *env = &reset_info->cpu->env; - - cpu_reset(CPU(reset_info->cpu)); - - /* init defaults */ - env->pc = (uint32_t)reset_info->bootstrap_pc; - env->regs[R_R1] = (uint32_t)reset_info->hwsetup_base; - env->regs[R_R2] = (uint32_t)reset_info->cmdline_base; - env->regs[R_R3] = (uint32_t)reset_info->initrd_base; - env->regs[R_R4] = (uint32_t)(reset_info->initrd_base + - reset_info->initrd_size); - env->eba = reset_info->flash_base; - env->deba = reset_info->flash_base; -} - -static void lm32_evr_init(MachineState *machine) -{ - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *kernel_filename = machine->kernel_filename; - LM32CPU *cpu; - CPULM32State *env; - DriveInfo *dinfo; - MemoryRegion *address_space_mem = get_system_memory(); - qemu_irq irq[32]; - ResetInfo *reset_info; - int i; - - if (machine->ram_size != mc->default_ram_size) { - char *sz = size_to_str(mc->default_ram_size); - error_report("Invalid RAM size, should be %s", sz); - g_free(sz); - exit(EXIT_FAILURE); - } - - /* memory map */ - hwaddr flash_base = 0x04000000; - size_t flash_sector_size = 256 * KiB; - size_t flash_size = 32 * MiB; - hwaddr ram_base = 0x08000000; - hwaddr timer0_base = 0x80002000; - hwaddr uart0_base = 0x80006000; - hwaddr timer1_base = 0x8000a000; - int uart0_irq = 0; - int timer0_irq = 1; - int timer1_irq = 3; - - reset_info = g_malloc0(sizeof(ResetInfo)); - - cpu = LM32_CPU(cpu_create(machine->cpu_type)); - - env = &cpu->env; - reset_info->cpu = cpu; - - reset_info->flash_base = flash_base; - - memory_region_add_subregion(address_space_mem, ram_base, machine->ram); - - dinfo = drive_get(IF_PFLASH, 0, 0); - /* Spansion S29NS128P */ - pflash_cfi02_register(flash_base, "lm32_evr.flash", flash_size, - dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, - flash_sector_size, - 1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); - - /* create irq lines */ - env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, cpu, 0)); - for (i = 0; i < 32; i++) { - irq[i] = qdev_get_gpio_in(env->pic_state, i); - } - - lm32_uart_create(uart0_base, irq[uart0_irq], serial_hd(0)); - sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]); - sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]); - - /* make sure juart isn't the first chardev */ - env->juart_state = lm32_juart_init(serial_hd(1)); - - reset_info->bootstrap_pc = flash_base; - - if (kernel_filename) { - uint64_t entry; - int kernel_size; - - kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &entry, NULL, NULL, NULL, - 1, EM_LATTICEMICO32, 0, 0); - reset_info->bootstrap_pc = entry; - - if (kernel_size < 0) { - kernel_size = load_image_targphys(kernel_filename, ram_base, - machine->ram_size); - reset_info->bootstrap_pc = ram_base; - } - - if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - } - - qemu_register_reset(main_cpu_reset, reset_info); -} - -static void lm32_uclinux_init(MachineState *machine) -{ - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - LM32CPU *cpu; - CPULM32State *env; - DriveInfo *dinfo; - MemoryRegion *address_space_mem = get_system_memory(); - qemu_irq irq[32]; - HWSetup *hw; - ResetInfo *reset_info; - int i; - - if (machine->ram_size != mc->default_ram_size) { - char *sz = size_to_str(mc->default_ram_size); - error_report("Invalid RAM size, should be %s", sz); - g_free(sz); - exit(EXIT_FAILURE); - } - - /* memory map */ - hwaddr flash_base = 0x04000000; - size_t flash_sector_size = 256 * KiB; - size_t flash_size = 32 * MiB; - hwaddr ram_base = 0x08000000; - hwaddr uart0_base = 0x80000000; - hwaddr timer0_base = 0x80002000; - hwaddr timer1_base = 0x80010000; - hwaddr timer2_base = 0x80012000; - int uart0_irq = 0; - int timer0_irq = 1; - int timer1_irq = 20; - int timer2_irq = 21; - hwaddr hwsetup_base = 0x0bffe000; - hwaddr cmdline_base = 0x0bfff000; - hwaddr initrd_base = 0x08400000; - size_t initrd_max = 0x01000000; - - reset_info = g_malloc0(sizeof(ResetInfo)); - - cpu = LM32_CPU(cpu_create(machine->cpu_type)); - - env = &cpu->env; - reset_info->cpu = cpu; - - reset_info->flash_base = flash_base; - - memory_region_add_subregion(address_space_mem, ram_base, machine->ram); - - dinfo = drive_get(IF_PFLASH, 0, 0); - /* Spansion S29NS128P */ - pflash_cfi02_register(flash_base, "lm32_uclinux.flash", flash_size, - dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, - flash_sector_size, - 1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); - - /* create irq lines */ - env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, env, 0)); - for (i = 0; i < 32; i++) { - irq[i] = qdev_get_gpio_in(env->pic_state, i); - } - - lm32_uart_create(uart0_base, irq[uart0_irq], serial_hd(0)); - sysbus_create_simple("lm32-timer", timer0_base, irq[timer0_irq]); - sysbus_create_simple("lm32-timer", timer1_base, irq[timer1_irq]); - sysbus_create_simple("lm32-timer", timer2_base, irq[timer2_irq]); - - /* make sure juart isn't the first chardev */ - env->juart_state = lm32_juart_init(serial_hd(1)); - - reset_info->bootstrap_pc = flash_base; - - if (kernel_filename) { - uint64_t entry; - int kernel_size; - - kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &entry, NULL, NULL, NULL, - 1, EM_LATTICEMICO32, 0, 0); - reset_info->bootstrap_pc = entry; - - if (kernel_size < 0) { - kernel_size = load_image_targphys(kernel_filename, ram_base, - machine->ram_size); - reset_info->bootstrap_pc = ram_base; - } - - if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - } - - /* generate a rom with the hardware description */ - hw = hwsetup_init(); - hwsetup_add_cpu(hw, "LM32", 75000000); - hwsetup_add_flash(hw, "flash", flash_base, flash_size); - hwsetup_add_ddr_sdram(hw, "ddr_sdram", ram_base, machine->ram_size); - hwsetup_add_timer(hw, "timer0", timer0_base, timer0_irq); - hwsetup_add_timer(hw, "timer1_dev_only", timer1_base, timer1_irq); - hwsetup_add_timer(hw, "timer2_dev_only", timer2_base, timer2_irq); - hwsetup_add_uart(hw, "uart", uart0_base, uart0_irq); - hwsetup_add_trailer(hw); - hwsetup_create_rom(hw, hwsetup_base); - hwsetup_free(hw); - - reset_info->hwsetup_base = hwsetup_base; - - if (kernel_cmdline && strlen(kernel_cmdline)) { - pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, - kernel_cmdline); - reset_info->cmdline_base = cmdline_base; - } - - if (initrd_filename) { - size_t initrd_size; - initrd_size = load_image_targphys(initrd_filename, initrd_base, - initrd_max); - reset_info->initrd_base = initrd_base; - reset_info->initrd_size = initrd_size; - } - - qemu_register_reset(main_cpu_reset, reset_info); -} - -static void lm32_evr_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - - mc->desc = "LatticeMico32 EVR32 eval system"; - mc->init = lm32_evr_init; - mc->is_default = true; - mc->default_cpu_type = LM32_CPU_TYPE_NAME("lm32-full"); - mc->default_ram_size = 64 * MiB; - mc->default_ram_id = "lm32_evr.sdram"; -} - -static const TypeInfo lm32_evr_type = { - .name = MACHINE_TYPE_NAME("lm32-evr"), - .parent = TYPE_MACHINE, - .class_init = lm32_evr_class_init, -}; - -static void lm32_uclinux_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - - mc->desc = "lm32 platform for uClinux and u-boot by Theobroma Systems"; - mc->init = lm32_uclinux_init; - mc->default_cpu_type = LM32_CPU_TYPE_NAME("lm32-full"); - mc->default_ram_size = 64 * MiB; - mc->default_ram_id = "lm32_uclinux.sdram"; -} - -static const TypeInfo lm32_uclinux_type = { - .name = MACHINE_TYPE_NAME("lm32-uclinux"), - .parent = TYPE_MACHINE, - .class_init = lm32_uclinux_class_init, -}; - -static void lm32_machine_init(void) -{ - type_register_static(&lm32_evr_type); - type_register_static(&lm32_uclinux_type); -} - -type_init(lm32_machine_init) diff --git a/hw/lm32/lm32_hwsetup.h b/hw/lm32/lm32_hwsetup.h deleted file mode 100644 index e6cd30ad68..0000000000 --- a/hw/lm32/lm32_hwsetup.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * LatticeMico32 hwsetup helper functions. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -/* - * These are helper functions for creating the hardware description blob used - * in the Theobroma's uClinux port. - */ - -#ifndef QEMU_HW_LM32_HWSETUP_H -#define QEMU_HW_LM32_HWSETUP_H - -#include "qemu/cutils.h" -#include "hw/loader.h" - -typedef struct { - void *data; - void *ptr; -} HWSetup; - -enum hwsetup_tag { - HWSETUP_TAG_EOL = 0, - HWSETUP_TAG_CPU = 1, - HWSETUP_TAG_ASRAM = 2, - HWSETUP_TAG_FLASH = 3, - HWSETUP_TAG_SDRAM = 4, - HWSETUP_TAG_OCM = 5, - HWSETUP_TAG_DDR_SDRAM = 6, - HWSETUP_TAG_DDR2_SDRAM = 7, - HWSETUP_TAG_TIMER = 8, - HWSETUP_TAG_UART = 9, - HWSETUP_TAG_GPIO = 10, - HWSETUP_TAG_TRISPEEDMAC = 11, - HWSETUP_TAG_I2CM = 12, - HWSETUP_TAG_LEDS = 13, - HWSETUP_TAG_7SEG = 14, - HWSETUP_TAG_SPI_S = 15, - HWSETUP_TAG_SPI_M = 16, -}; - -static inline HWSetup *hwsetup_init(void) -{ - HWSetup *hw; - - hw = g_malloc(sizeof(HWSetup)); - hw->data = g_malloc0(TARGET_PAGE_SIZE); - hw->ptr = hw->data; - - return hw; -} - -static inline void hwsetup_free(HWSetup *hw) -{ - g_free(hw->data); - g_free(hw); -} - -static inline void hwsetup_create_rom(HWSetup *hw, - hwaddr base) -{ - rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, - TARGET_PAGE_SIZE, base, NULL, NULL, NULL, NULL, true); -} - -static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u) -{ - stb_p(hw->ptr, u); - hw->ptr += 1; -} - -static inline void hwsetup_add_u32(HWSetup *hw, uint32_t u) -{ - stl_p(hw->ptr, u); - hw->ptr += 4; -} - -static inline void hwsetup_add_tag(HWSetup *hw, enum hwsetup_tag t) -{ - stl_p(hw->ptr, t); - hw->ptr += 4; -} - -static inline void hwsetup_add_str(HWSetup *hw, const char *str) -{ - pstrcpy(hw->ptr, 32, str); - hw->ptr += 32; -} - -static inline void hwsetup_add_trailer(HWSetup *hw) -{ - hwsetup_add_u32(hw, 8); /* size */ - hwsetup_add_tag(hw, HWSETUP_TAG_EOL); -} - -static inline void hwsetup_add_cpu(HWSetup *hw, - const char *name, uint32_t frequency) -{ - hwsetup_add_u32(hw, 44); /* size */ - hwsetup_add_tag(hw, HWSETUP_TAG_CPU); - hwsetup_add_str(hw, name); - hwsetup_add_u32(hw, frequency); -} - -static inline void hwsetup_add_flash(HWSetup *hw, - const char *name, uint32_t base, uint32_t size) -{ - hwsetup_add_u32(hw, 52); /* size */ - hwsetup_add_tag(hw, HWSETUP_TAG_FLASH); - hwsetup_add_str(hw, name); - hwsetup_add_u32(hw, base); - hwsetup_add_u32(hw, size); - hwsetup_add_u8(hw, 8); /* read latency */ - hwsetup_add_u8(hw, 8); /* write latency */ - hwsetup_add_u8(hw, 25); /* address width */ - hwsetup_add_u8(hw, 32); /* data width */ -} - -static inline void hwsetup_add_ddr_sdram(HWSetup *hw, - const char *name, uint32_t base, uint32_t size) -{ - hwsetup_add_u32(hw, 48); /* size */ - hwsetup_add_tag(hw, HWSETUP_TAG_DDR_SDRAM); - hwsetup_add_str(hw, name); - hwsetup_add_u32(hw, base); - hwsetup_add_u32(hw, size); -} - -static inline void hwsetup_add_timer(HWSetup *hw, - const char *name, uint32_t base, uint32_t irq) -{ - hwsetup_add_u32(hw, 56); /* size */ - hwsetup_add_tag(hw, HWSETUP_TAG_TIMER); - hwsetup_add_str(hw, name); - hwsetup_add_u32(hw, base); - hwsetup_add_u8(hw, 1); /* wr_tickcount */ - hwsetup_add_u8(hw, 1); /* rd_tickcount */ - hwsetup_add_u8(hw, 1); /* start_stop_control */ - hwsetup_add_u8(hw, 32); /* counter_width */ - hwsetup_add_u32(hw, 20); /* reload_ticks */ - hwsetup_add_u8(hw, irq); - hwsetup_add_u8(hw, 0); /* padding */ - hwsetup_add_u8(hw, 0); /* padding */ - hwsetup_add_u8(hw, 0); /* padding */ -} - -static inline void hwsetup_add_uart(HWSetup *hw, - const char *name, uint32_t base, uint32_t irq) -{ - hwsetup_add_u32(hw, 56); /* size */ - hwsetup_add_tag(hw, HWSETUP_TAG_UART); - hwsetup_add_str(hw, name); - hwsetup_add_u32(hw, base); - hwsetup_add_u32(hw, 115200); /* baudrate */ - hwsetup_add_u8(hw, 8); /* databits */ - hwsetup_add_u8(hw, 1); /* stopbits */ - hwsetup_add_u8(hw, 1); /* use_interrupt */ - hwsetup_add_u8(hw, 1); /* block_on_transmit */ - hwsetup_add_u8(hw, 1); /* block_on_receive */ - hwsetup_add_u8(hw, 4); /* rx_buffer_size */ - hwsetup_add_u8(hw, 4); /* tx_buffer_size */ - hwsetup_add_u8(hw, irq); -} - -#endif /* QEMU_HW_LM32_HWSETUP_H */ diff --git a/hw/lm32/meson.build b/hw/lm32/meson.build deleted file mode 100644 index 42d6f8db3d..0000000000 --- a/hw/lm32/meson.build +++ /dev/null @@ -1,6 +0,0 @@ -lm32_ss = ss.source_set() -# LM32 boards -lm32_ss.add(when: 'CONFIG_LM32_EVR', 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 deleted file mode 100644 index 5dca5d52f5..0000000000 --- a/hw/lm32/milkymist-hw.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef QEMU_HW_MILKYMIST_HW_H -#define QEMU_HW_MILKYMIST_HW_H - -#include "hw/qdev-core.h" -#include "net/net.h" -#include "qapi/error.h" - -static inline DeviceState *milkymist_uart_create(hwaddr base, - qemu_irq irq, - Chardev *chr) -{ - DeviceState *dev; - - dev = qdev_new("milkymist-uart"); - qdev_prop_set_chr(dev, "chardev", chr); - 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; -} - -static inline DeviceState *milkymist_hpdmc_create(hwaddr base) -{ - DeviceState *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; -} - -static inline DeviceState *milkymist_vgafb_create(hwaddr base, - uint32_t fb_offset, uint32_t fb_mask) -{ - DeviceState *dev; - - dev = qdev_new("milkymist-vgafb"); - qdev_prop_set_uint32(dev, "fb_offset", fb_offset); - qdev_prop_set_uint32(dev, "fb_mask", fb_mask); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); - - return dev; -} - -static inline DeviceState *milkymist_sysctl_create(hwaddr base, - qemu_irq gpio_irq, qemu_irq timer0_irq, qemu_irq timer1_irq, - uint32_t freq_hz, uint32_t system_id, uint32_t capabilities, - uint32_t gpio_strappings) -{ - DeviceState *dev; - - 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); - 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); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, timer1_irq); - - return dev; -} - -static inline DeviceState *milkymist_pfpu_create(hwaddr base, - qemu_irq irq) -{ - DeviceState *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; -} - -static inline DeviceState *milkymist_ac97_create(hwaddr base, - qemu_irq crrequest_irq, qemu_irq crreply_irq, qemu_irq dmar_irq, - qemu_irq dmaw_irq) -{ - DeviceState *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); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, dmar_irq); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 3, dmaw_irq); - - return dev; -} - -static inline DeviceState *milkymist_minimac2_create(hwaddr base, - hwaddr buffers_base, qemu_irq rx_irq, qemu_irq tx_irq) -{ - DeviceState *dev; - - qemu_check_nic_model(&nd_table[0], "minimac2"); - dev = qdev_new("milkymist-minimac2"); - qdev_set_nic_properties(dev, &nd_table[0]); - 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); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq); - - return dev; -} - -static inline DeviceState *milkymist_softusb_create(hwaddr base, - qemu_irq irq, uint32_t pmem_base, uint32_t pmem_size, - uint32_t dmem_base, uint32_t dmem_size) -{ - DeviceState *dev; - - dev = qdev_new("milkymist-softusb"); - qdev_prop_set_uint32(dev, "pmem_size", pmem_size); - qdev_prop_set_uint32(dev, "dmem_size", dmem_size); - 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); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); - - return dev; -} - -#endif /* QEMU_HW_MILKYMIST_HW_H */ diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c deleted file mode 100644 index bef7855328..0000000000 --- a/hw/lm32/milkymist.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * QEMU model for the Milkymist board. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "qemu/units.h" -#include "qemu/error-report.h" -#include "qemu-common.h" -#include "qemu/datadir.h" -#include "cpu.h" -#include "hw/sysbus.h" -#include "hw/irq.h" -#include "hw/block/flash.h" -#include "sysemu/sysemu.h" -#include "sysemu/qtest.h" -#include "sysemu/reset.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "hw/qdev-properties.h" -#include "elf.h" -#include "milkymist-hw.h" -#include "hw/display/milkymist_tmu2.h" -#include "hw/sd/sd.h" -#include "lm32.h" -#include "qemu/cutils.h" - -#define BIOS_FILENAME "mmone-bios.bin" -#define BIOS_OFFSET 0x00860000 -#define BIOS_SIZE (512 * KiB) -#define KERNEL_LOAD_ADDR 0x40000000 - -typedef struct { - LM32CPU *cpu; - hwaddr bootstrap_pc; - hwaddr flash_base; - hwaddr initrd_base; - size_t initrd_size; - hwaddr cmdline_base; -} ResetInfo; - -static void cpu_irq_handler(void *opaque, int irq, int level) -{ - LM32CPU *cpu = opaque; - CPUState *cs = CPU(cpu); - - if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } -} - -static void main_cpu_reset(void *opaque) -{ - ResetInfo *reset_info = opaque; - CPULM32State *env = &reset_info->cpu->env; - - cpu_reset(CPU(reset_info->cpu)); - - /* init defaults */ - env->pc = reset_info->bootstrap_pc; - env->regs[R_R1] = reset_info->cmdline_base; - env->regs[R_R2] = reset_info->initrd_base; - env->regs[R_R3] = reset_info->initrd_base + reset_info->initrd_size; - env->eba = reset_info->flash_base; - 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) -{ - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *bios_name = machine->firmware ?: BIOS_FILENAME; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - LM32CPU *cpu; - CPULM32State *env; - int kernel_size; - DriveInfo *dinfo; - MemoryRegion *address_space_mem = get_system_memory(); - qemu_irq irq[32]; - int i; - char *bios_filename; - ResetInfo *reset_info; - - if (machine->ram_size != mc->default_ram_size) { - char *sz = size_to_str(mc->default_ram_size); - error_report("Invalid RAM size, should be %s", sz); - g_free(sz); - exit(EXIT_FAILURE); - } - - /* memory map */ - hwaddr flash_base = 0x00000000; - size_t flash_sector_size = 128 * KiB; - size_t flash_size = 32 * MiB; - hwaddr sdram_base = 0x40000000; - - hwaddr initrd_base = sdram_base + 0x1002000; - hwaddr cmdline_base = sdram_base + 0x1000000; - size_t initrd_max = machine->ram_size - 0x1002000; - - reset_info = g_malloc0(sizeof(ResetInfo)); - - cpu = LM32_CPU(cpu_create(machine->cpu_type)); - - env = &cpu->env; - reset_info->cpu = cpu; - - cpu_lm32_set_phys_msb_ignore(env, 1); - - memory_region_add_subregion(address_space_mem, sdram_base, machine->ram); - - dinfo = drive_get(IF_PFLASH, 0, 0); - /* Numonyx JS28F256J3F105 */ - pflash_cfi01_register(flash_base, "milkymist.flash", flash_size, - dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, - flash_sector_size, 2, 0x00, 0x89, 0x00, 0x1d, 1); - - /* create irq lines */ - env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, cpu, 0)); - for (i = 0; i < 32; i++) { - irq[i] = qdev_get_gpio_in(env->pic_state, i); - } - - /* load bios rom */ - bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - - if (bios_filename) { - if (load_image_targphys(bios_filename, BIOS_OFFSET, BIOS_SIZE) < 0) { - error_report("could not load bios '%s'", bios_filename); - exit(1); - } - } - - reset_info->bootstrap_pc = BIOS_OFFSET; - - /* if no kernel is given no valid bios rom is a fatal error */ - if (!kernel_filename && !dinfo && !bios_filename && !qtest_enabled()) { - error_report("could not load Milkymist One bios '%s'", bios_name); - exit(1); - } - g_free(bios_filename); - - milkymist_uart_create(0x60000000, irq[0], serial_hd(0)); - milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3], - 80000000, 0x10014d31, 0x0000041f, 0x00000001); - milkymist_hpdmc_create(0x60002000); - milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff); - milkymist_memcard_create(0x60004000); - milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]); - milkymist_pfpu_create(0x60006000, irq[8]); - if (machine->enable_graphics) { - milkymist_tmu2_create(0x60007000, irq[9]); - } - milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]); - milkymist_softusb_create(0x6000f000, irq[15], - 0x20000000, 0x1000, 0x20020000, 0x2000); - - /* make sure juart isn't the first chardev */ - env->juart_state = lm32_juart_init(serial_hd(1)); - - if (kernel_filename) { - uint64_t entry; - - /* Boots a kernel elf binary. */ - kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &entry, NULL, NULL, NULL, - 1, EM_LATTICEMICO32, 0, 0); - reset_info->bootstrap_pc = entry; - - if (kernel_size < 0) { - kernel_size = load_image_targphys(kernel_filename, sdram_base, - machine->ram_size); - reset_info->bootstrap_pc = sdram_base; - } - - if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - } - - if (kernel_cmdline && strlen(kernel_cmdline)) { - pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, - kernel_cmdline); - reset_info->cmdline_base = (uint32_t)cmdline_base; - } - - if (initrd_filename) { - size_t initrd_size; - initrd_size = load_image_targphys(initrd_filename, initrd_base, - initrd_max); - reset_info->initrd_base = (uint32_t)initrd_base; - reset_info->initrd_size = (uint32_t)initrd_size; - } - - qemu_register_reset(main_cpu_reset, reset_info); -} - -static void milkymist_machine_init(MachineClass *mc) -{ - mc->desc = "Milkymist One"; - mc->init = milkymist_init; - mc->default_cpu_type = LM32_CPU_TYPE_NAME("lm32-full"); - mc->default_ram_size = 128 * MiB; - mc->default_ram_id = "milkymist.sdram"; -} - -DEFINE_MACHINE("milkymist", milkymist_machine_init) diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index 12b655eda8..a3a2560301 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -34,6 +34,16 @@ static int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); +static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm, Error **errp) +{ + if (!dimm->hostmem) { + error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property must be set"); + return NULL; + } + + return host_memory_backend_get_memory(dimm->hostmem); +} + void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, const uint64_t *legacy_align, Error **errp) { @@ -66,9 +76,8 @@ void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine) { - PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); - MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm, - &error_abort); + MemoryRegion *vmstate_mr = pc_dimm_get_memory_region(dimm, + &error_abort); memory_device_plug(MEMORY_DEVICE(dimm), machine); vmstate_register_ram(vmstate_mr, DEVICE(dimm)); @@ -76,9 +85,8 @@ void pc_dimm_plug(PCDIMMDevice *dimm, MachineState *machine) void pc_dimm_unplug(PCDIMMDevice *dimm, MachineState *machine) { - PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); - MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm, - &error_abort); + MemoryRegion *vmstate_mr = pc_dimm_get_memory_region(dimm, + &error_abort); memory_device_unplug(MEMORY_DEVICE(dimm), machine); vmstate_unregister_ram(vmstate_mr, DEVICE(dimm)); @@ -205,16 +213,6 @@ static void pc_dimm_unrealize(DeviceState *dev) host_memory_backend_set_mapped(dimm->hostmem, false); } -static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm, Error **errp) -{ - if (!dimm->hostmem) { - error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property must be set"); - return NULL; - } - - return host_memory_backend_get_memory(dimm->hostmem); -} - static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md) { return object_property_get_uint(OBJECT(md), PC_DIMM_ADDR_PROP, @@ -266,7 +264,6 @@ static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md, static void pc_dimm_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc); MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc); dc->realize = pc_dimm_realize; @@ -274,8 +271,6 @@ static void pc_dimm_class_init(ObjectClass *oc, void *data) device_class_set_props(dc, pc_dimm_properties); dc->desc = "DIMM memory module"; - ddc->get_vmstate_memory_region = pc_dimm_get_memory_region; - mdc->get_addr = pc_dimm_md_get_addr; mdc->set_addr = pc_dimm_md_set_addr; /* for a dimm plugged_size == region_size */ diff --git a/hw/meson.build b/hw/meson.build index 8ba79b1a52..6bdbae0e81 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -47,11 +47,9 @@ subdir('avr') subdir('cris') subdir('hppa') subdir('i386') -subdir('lm32') subdir('m68k') subdir('microblaze') subdir('mips') -subdir('moxie') subdir('nios2') subdir('openrisc') subdir('ppc') @@ -63,5 +61,4 @@ subdir('sh4') subdir('sparc') subdir('sparc64') subdir('tricore') -subdir('unicore32') subdir('xtensa') diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 1e7b8b064b..66e1648533 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -36,9 +36,6 @@ 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')) @@ -63,7 +60,6 @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files( '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', diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c deleted file mode 100644 index 09a3875f02..0000000000 --- a/hw/misc/milkymist-hpdmc.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * QEMU model of the Milkymist High Performance Dynamic Memory Controller. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/hpdmc.pdf - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -enum { - R_SYSTEM = 0, - R_BYPASS, - R_TIMING, - R_IODELAY, - R_MAX -}; - -enum { - IODELAY_DQSDELAY_RDY = (1<<5), - IODELAY_PLL1_LOCKED = (1<<6), - IODELAY_PLL2_LOCKED = (1<<7), -}; - -#define TYPE_MILKYMIST_HPDMC "milkymist-hpdmc" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistHpdmcState, MILKYMIST_HPDMC) - -struct MilkymistHpdmcState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - - uint32_t regs[R_MAX]; -}; - -static uint64_t hpdmc_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistHpdmcState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_SYSTEM: - case R_BYPASS: - case R_TIMING: - case R_IODELAY: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_hpdmc: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_hpdmc_memory_read(addr << 2, r); - - return r; -} - -static void hpdmc_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistHpdmcState *s = opaque; - - trace_milkymist_hpdmc_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_SYSTEM: - case R_BYPASS: - case R_TIMING: - s->regs[addr] = value; - break; - case R_IODELAY: - /* ignore writes */ - break; - - default: - error_report("milkymist_hpdmc: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps hpdmc_mmio_ops = { - .read = hpdmc_read, - .write = hpdmc_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_hpdmc_reset(DeviceState *d) -{ - MilkymistHpdmcState *s = MILKYMIST_HPDMC(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - /* defaults */ - s->regs[R_IODELAY] = IODELAY_DQSDELAY_RDY | IODELAY_PLL1_LOCKED - | IODELAY_PLL2_LOCKED; -} - -static void milkymist_hpdmc_realize(DeviceState *dev, Error **errp) -{ - MilkymistHpdmcState *s = MILKYMIST_HPDMC(dev); - - memory_region_init_io(&s->regs_region, OBJECT(dev), &hpdmc_mmio_ops, s, - "milkymist-hpdmc", R_MAX * 4); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->regs_region); -} - -static const VMStateDescription vmstate_milkymist_hpdmc = { - .name = "milkymist-hpdmc", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistHpdmcState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_hpdmc_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_hpdmc_realize; - dc->reset = milkymist_hpdmc_reset; - dc->vmsd = &vmstate_milkymist_hpdmc; -} - -static const TypeInfo milkymist_hpdmc_info = { - .name = TYPE_MILKYMIST_HPDMC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistHpdmcState), - .class_init = milkymist_hpdmc_class_init, -}; - -static void milkymist_hpdmc_register_types(void) -{ - type_register_static(&milkymist_hpdmc_info); -} - -type_init(milkymist_hpdmc_register_types) diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c deleted file mode 100644 index e4ee209c10..0000000000 --- a/hw/misc/milkymist-pfpu.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * QEMU model of the Milkymist programmable FPU. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/pfpu.pdf - * - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "qemu/log.h" -#include "qemu/module.h" -#include "qemu/error-report.h" -#include <math.h> -#include "qom/object.h" - -/* #define TRACE_EXEC */ - -#ifdef TRACE_EXEC -# define D_EXEC(x) x -#else -# define D_EXEC(x) -#endif - -enum { - R_CTL = 0, - R_MESHBASE, - R_HMESHLAST, - R_VMESHLAST, - R_CODEPAGE, - R_VERTICES, - R_COLLISIONS, - R_STRAYWRITES, - R_LASTDMA, - R_PC, - R_DREGBASE, - R_CODEBASE, - R_MAX -}; - -enum { - CTL_START_BUSY = (1<<0), -}; - -enum { - OP_NOP = 0, - OP_FADD, - OP_FSUB, - OP_FMUL, - OP_FABS, - OP_F2I, - OP_I2F, - OP_VECTOUT, - OP_SIN, - OP_COS, - OP_ABOVE, - OP_EQUAL, - OP_COPY, - OP_IF, - OP_TSIGN, - OP_QUAKE, -}; - -enum { - GPR_X = 0, - GPR_Y = 1, - GPR_FLAGS = 2, -}; - -enum { - LATENCY_FADD = 5, - LATENCY_FSUB = 5, - LATENCY_FMUL = 7, - LATENCY_FABS = 2, - LATENCY_F2I = 2, - LATENCY_I2F = 3, - LATENCY_VECTOUT = 0, - LATENCY_SIN = 4, - LATENCY_COS = 4, - LATENCY_ABOVE = 2, - LATENCY_EQUAL = 2, - LATENCY_COPY = 2, - LATENCY_IF = 2, - LATENCY_TSIGN = 2, - LATENCY_QUAKE = 2, - MAX_LATENCY = 7 -}; - -#define GPR_BEGIN 0x100 -#define GPR_END 0x17f -#define MICROCODE_BEGIN 0x200 -#define MICROCODE_END 0x3ff -#define MICROCODE_WORDS 2048 - -#define REINTERPRET_CAST(type, val) (*((type *)&(val))) - -#ifdef TRACE_EXEC -static const char *opcode_to_str[] = { - "NOP", "FADD", "FSUB", "FMUL", "FABS", "F2I", "I2F", "VECTOUT", - "SIN", "COS", "ABOVE", "EQUAL", "COPY", "IF", "TSIGN", "QUAKE", -}; -#endif - -#define TYPE_MILKYMIST_PFPU "milkymist-pfpu" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistPFPUState, MILKYMIST_PFPU) - -struct MilkymistPFPUState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - Chardev *chr; - qemu_irq irq; - - uint32_t regs[R_MAX]; - uint32_t gp_regs[128]; - uint32_t microcode[MICROCODE_WORDS]; - - int output_queue_pos; - uint32_t output_queue[MAX_LATENCY]; -}; - -static inline uint32_t -get_dma_address(uint32_t base, uint32_t x, uint32_t y) -{ - return base + 8 * (128 * y + x); -} - -static inline void -output_queue_insert(MilkymistPFPUState *s, uint32_t val, int pos) -{ - s->output_queue[(s->output_queue_pos + pos) % MAX_LATENCY] = val; -} - -static inline uint32_t -output_queue_remove(MilkymistPFPUState *s) -{ - return s->output_queue[s->output_queue_pos]; -} - -static inline void -output_queue_advance(MilkymistPFPUState *s) -{ - s->output_queue[s->output_queue_pos] = 0; - s->output_queue_pos = (s->output_queue_pos + 1) % MAX_LATENCY; -} - -static int pfpu_decode_insn(MilkymistPFPUState *s) -{ - uint32_t pc = s->regs[R_PC]; - uint32_t insn = s->microcode[pc]; - uint32_t reg_a = (insn >> 18) & 0x7f; - uint32_t reg_b = (insn >> 11) & 0x7f; - uint32_t op = (insn >> 7) & 0xf; - uint32_t reg_d = insn & 0x7f; - uint32_t r = 0; - int latency = 0; - - switch (op) { - case OP_NOP: - break; - case OP_FADD: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = a + b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FADD; - D_EXEC(qemu_log("ADD a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_FSUB: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = a - b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FSUB; - D_EXEC(qemu_log("SUB a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_FMUL: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = a * b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FMUL; - D_EXEC(qemu_log("MUL a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_FABS: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float t = fabsf(a); - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_FABS; - D_EXEC(qemu_log("ABS a=%f t=%f, r=%08x\n", a, t, r)); - } break; - case OP_F2I: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - int32_t t = a; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_F2I; - D_EXEC(qemu_log("F2I a=%f t=%d, r=%08x\n", a, t, r)); - } break; - case OP_I2F: - { - int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]); - float t = a; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_I2F; - D_EXEC(qemu_log("I2F a=%08x t=%f, r=%08x\n", a, t, r)); - } break; - case OP_VECTOUT: - { - uint32_t a = cpu_to_be32(s->gp_regs[reg_a]); - uint32_t b = cpu_to_be32(s->gp_regs[reg_b]); - hwaddr dma_ptr = - get_dma_address(s->regs[R_MESHBASE], - s->gp_regs[GPR_X], s->gp_regs[GPR_Y]); - cpu_physical_memory_write(dma_ptr, &a, 4); - cpu_physical_memory_write(dma_ptr + 4, &b, 4); - s->regs[R_LASTDMA] = dma_ptr + 4; - D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr)); - trace_milkymist_pfpu_vectout(a, b, dma_ptr); - } break; - case OP_SIN: - { - int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]); - float t = sinf(a * (1.0f / (M_PI * 4096.0f))); - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_SIN; - D_EXEC(qemu_log("SIN a=%d t=%f, r=%08x\n", a, t, r)); - } break; - case OP_COS: - { - int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]); - float t = cosf(a * (1.0f / (M_PI * 4096.0f))); - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_COS; - D_EXEC(qemu_log("COS a=%d t=%f, r=%08x\n", a, t, r)); - } break; - case OP_ABOVE: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = (a > b) ? 1.0f : 0.0f; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_ABOVE; - D_EXEC(qemu_log("ABOVE a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_EQUAL: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = (a == b) ? 1.0f : 0.0f; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_EQUAL; - D_EXEC(qemu_log("EQUAL a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_COPY: - { - r = s->gp_regs[reg_a]; - latency = LATENCY_COPY; - D_EXEC(qemu_log("COPY")); - } break; - case OP_IF: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - uint32_t f = s->gp_regs[GPR_FLAGS]; - float t = (f != 0) ? a : b; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_IF; - D_EXEC(qemu_log("IF f=%u a=%f b=%f t=%f, r=%08x\n", f, a, b, t, r)); - } break; - case OP_TSIGN: - { - float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]); - float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]); - float t = (b < 0) ? -a : a; - r = REINTERPRET_CAST(uint32_t, t); - latency = LATENCY_TSIGN; - D_EXEC(qemu_log("TSIGN a=%f b=%f t=%f, r=%08x\n", a, b, t, r)); - } break; - case OP_QUAKE: - { - uint32_t a = s->gp_regs[reg_a]; - r = 0x5f3759df - (a >> 1); - latency = LATENCY_QUAKE; - D_EXEC(qemu_log("QUAKE a=%d r=%08x\n", a, r)); - } break; - - default: - error_report("milkymist_pfpu: unknown opcode %d", op); - break; - } - - if (!reg_d) { - D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n", - s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency, - s->regs[R_PC] + latency)); - } else { - D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n", - s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency, - s->regs[R_PC] + latency, reg_d)); - } - - if (op == OP_VECTOUT) { - return 0; - } - - /* store output for this cycle */ - if (reg_d) { - uint32_t val = output_queue_remove(s); - D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val)); - s->gp_regs[reg_d] = val; - } - - output_queue_advance(s); - - /* store op output */ - if (op != OP_NOP) { - output_queue_insert(s, r, latency-1); - } - - /* advance PC */ - s->regs[R_PC]++; - - return 1; -}; - -static void pfpu_start(MilkymistPFPUState *s) -{ - int x, y; - int i; - - for (y = 0; y <= s->regs[R_VMESHLAST]; y++) { - for (x = 0; x <= s->regs[R_HMESHLAST]; x++) { - D_EXEC(qemu_log("\nprocessing x=%d y=%d\n", x, y)); - - /* set current position */ - s->gp_regs[GPR_X] = x; - s->gp_regs[GPR_Y] = y; - - /* run microcode on this position */ - i = 0; - while (pfpu_decode_insn(s)) { - /* decode at most MICROCODE_WORDS instructions */ - if (++i >= MICROCODE_WORDS) { - error_report("milkymist_pfpu: too many instructions " - "executed in microcode. No VECTOUT?"); - break; - } - } - - /* reset pc for next run */ - s->regs[R_PC] = 0; - } - } - - s->regs[R_VERTICES] = x * y; - - trace_milkymist_pfpu_pulse_irq(); - qemu_irq_pulse(s->irq); -} - -static inline int get_microcode_address(MilkymistPFPUState *s, uint32_t addr) -{ - return (512 * s->regs[R_CODEPAGE]) + addr - MICROCODE_BEGIN; -} - -static uint64_t pfpu_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistPFPUState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CTL: - case R_MESHBASE: - case R_HMESHLAST: - case R_VMESHLAST: - case R_CODEPAGE: - case R_VERTICES: - case R_COLLISIONS: - case R_STRAYWRITES: - case R_LASTDMA: - case R_PC: - case R_DREGBASE: - case R_CODEBASE: - r = s->regs[addr]; - break; - case GPR_BEGIN ... GPR_END: - r = s->gp_regs[addr - GPR_BEGIN]; - break; - case MICROCODE_BEGIN ... MICROCODE_END: - r = s->microcode[get_microcode_address(s, addr)]; - break; - - default: - error_report("milkymist_pfpu: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_pfpu_memory_read(addr << 2, r); - - return r; -} - -static void pfpu_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistPFPUState *s = opaque; - - trace_milkymist_pfpu_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTL: - if (value & CTL_START_BUSY) { - pfpu_start(s); - } - break; - case R_MESHBASE: - case R_HMESHLAST: - case R_VMESHLAST: - case R_CODEPAGE: - case R_VERTICES: - case R_COLLISIONS: - case R_STRAYWRITES: - case R_LASTDMA: - case R_PC: - case R_DREGBASE: - case R_CODEBASE: - s->regs[addr] = value; - break; - case GPR_BEGIN ... GPR_END: - s->gp_regs[addr - GPR_BEGIN] = value; - break; - case MICROCODE_BEGIN ... MICROCODE_END: - s->microcode[get_microcode_address(s, addr)] = value; - break; - - default: - error_report("milkymist_pfpu: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps pfpu_mmio_ops = { - .read = pfpu_read, - .write = pfpu_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_pfpu_reset(DeviceState *d) -{ - MilkymistPFPUState *s = MILKYMIST_PFPU(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - for (i = 0; i < 128; i++) { - s->gp_regs[i] = 0; - } - for (i = 0; i < MICROCODE_WORDS; i++) { - s->microcode[i] = 0; - } - s->output_queue_pos = 0; - for (i = 0; i < MAX_LATENCY; i++) { - s->output_queue[i] = 0; - } -} - -static void milkymist_pfpu_realize(DeviceState *dev, Error **errp) -{ - MilkymistPFPUState *s = MILKYMIST_PFPU(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - sysbus_init_irq(sbd, &s->irq); - - memory_region_init_io(&s->regs_region, OBJECT(dev), &pfpu_mmio_ops, s, - "milkymist-pfpu", MICROCODE_END * 4); - sysbus_init_mmio(sbd, &s->regs_region); -} - -static const VMStateDescription vmstate_milkymist_pfpu = { - .name = "milkymist-pfpu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistPFPUState, R_MAX), - VMSTATE_UINT32_ARRAY(gp_regs, MilkymistPFPUState, 128), - VMSTATE_UINT32_ARRAY(microcode, MilkymistPFPUState, MICROCODE_WORDS), - VMSTATE_INT32(output_queue_pos, MilkymistPFPUState), - VMSTATE_UINT32_ARRAY(output_queue, MilkymistPFPUState, MAX_LATENCY), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_pfpu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_pfpu_realize; - dc->reset = milkymist_pfpu_reset; - dc->vmsd = &vmstate_milkymist_pfpu; -} - -static const TypeInfo milkymist_pfpu_info = { - .name = TYPE_MILKYMIST_PFPU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistPFPUState), - .class_init = milkymist_pfpu_class_init, -}; - -static void milkymist_pfpu_register_types(void) -{ - type_register_static(&milkymist_pfpu_info); -} - -type_init(milkymist_pfpu_register_types) diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c deleted file mode 100644 index 676c23f7db..0000000000 --- a/hw/misc/puv3_pm.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Power Management device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#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" -OBJECT_DECLARE_SIMPLE_TYPE(PUV3PMState, PUV3_PM) - -struct PUV3PMState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - - uint32_t reg_PMCR; - uint32_t reg_PCGR; - uint32_t reg_PLL_SYS_CFG; - uint32_t reg_PLL_DDR_CFG; - uint32_t reg_PLL_VGA_CFG; - uint32_t reg_DIVCFG; -}; - -static uint64_t puv3_pm_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3PMState *s = opaque; - uint32_t ret = 0; - - switch (offset) { - case 0x14: - ret = s->reg_PCGR; - break; - case 0x18: - ret = s->reg_PLL_SYS_CFG; - break; - case 0x1c: - ret = s->reg_PLL_DDR_CFG; - break; - case 0x20: - ret = s->reg_PLL_VGA_CFG; - break; - case 0x24: - ret = s->reg_DIVCFG; - break; - case 0x28: /* PLL SYS STATUS */ - ret = 0x00002401; - break; - case 0x2c: /* PLL DDR STATUS */ - ret = 0x00100c00; - break; - case 0x30: /* PLL VGA STATUS */ - ret = 0x00003801; - break; - case 0x34: /* DIV STATUS */ - ret = 0x22f52015; - break; - case 0x38: /* SW RESET */ - ret = 0x0; - break; - case 0x44: /* PLL DFC DONE */ - ret = 0x7; - break; - default: - 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; -} - -static void puv3_pm_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3PMState *s = opaque; - - switch (offset) { - case 0x0: - s->reg_PMCR = value; - break; - case 0x14: - s->reg_PCGR = value; - break; - case 0x18: - s->reg_PLL_SYS_CFG = value; - break; - case 0x1c: - s->reg_PLL_DDR_CFG = value; - break; - case 0x20: - s->reg_PLL_VGA_CFG = value; - break; - case 0x24: - case 0x38: - break; - default: - 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); -} - -static const MemoryRegionOps puv3_pm_ops = { - .read = puv3_pm_read, - .write = puv3_pm_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void puv3_pm_realize(DeviceState *dev, Error **errp) -{ - PUV3PMState *s = PUV3_PM(dev); - - s->reg_PCGR = 0x0; - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_pm_ops, s, "puv3_pm", - PUV3_REGS_OFFSET); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); -} - -static void puv3_pm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = puv3_pm_realize; -} - -static const TypeInfo puv3_pm_info = { - .name = TYPE_PUV3_PM, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3PMState), - .class_init = puv3_pm_class_init, -}; - -static void puv3_pm_register_type(void) -{ - type_register_static(&puv3_pm_info); -} - -type_init(puv3_pm_register_type) diff --git a/hw/misc/trace-events b/hw/misc/trace-events index d0a89eb059..0752217636 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -67,16 +67,6 @@ slavio_sysctrl_mem_readl(uint32_t ret) "Read system control 0x%08x" slavio_led_mem_writew(uint32_t val) "Write diagnostic LED 0x%04x" slavio_led_mem_readw(uint32_t ret) "Read diagnostic LED 0x%04x" -# milkymist-hpdmc.c -milkymist_hpdmc_memory_read(uint32_t addr, uint32_t value) "addr=0x%08x value=0x%08x" -milkymist_hpdmc_memory_write(uint32_t addr, uint32_t value) "addr=0x%08x value=0x%08x" - -# milkymist-pfpu.c -milkymist_pfpu_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_pfpu_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_pfpu_vectout(uint32_t a, uint32_t b, uint32_t dma_ptr) "a 0x%08x b 0x%08x dma_ptr 0x%08x" -milkymist_pfpu_pulse_irq(void) "Pulse IRQ" - # aspeed_scu.c aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32 diff --git a/hw/moxie/Kconfig b/hw/moxie/Kconfig deleted file mode 100644 index 3793ef0372..0000000000 --- a/hw/moxie/Kconfig +++ /dev/null @@ -1,3 +0,0 @@ -config MOXIESIM - bool - select SERIAL diff --git a/hw/moxie/meson.build b/hw/moxie/meson.build deleted file mode 100644 index 05a7c2e00f..0000000000 --- a/hw/moxie/meson.build +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index 3d255d4879..0000000000 --- a/hw/moxie/moxiesim.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * QEMU/moxiesim emulation - * - * Emulates a very simple machine model similar to the one used by the - * GDB moxie simulator. - * - * Copyright (c) 2008, 2009, 2010, 2013 Anthony Green - * - * 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/error-report.h" -#include "qapi/error.h" -#include "cpu.h" -#include "net/net.h" -#include "sysemu/reset.h" -#include "sysemu/sysemu.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "hw/char/serial.h" -#include "elf.h" - -#define PHYS_MEM_BASE 0x80000000 -#define FIRMWARE_BASE 0x1000 -#define FIRMWARE_SIZE (128 * 0x1000) - -typedef struct { - uint64_t ram_size; - const char *kernel_filename; - const char *kernel_cmdline; - const char *initrd_filename; -} LoaderParams; - -static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params) -{ - 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, NULL, &kernel_high, NULL, 1, EM_MOXIE, - 0, 0); - - if (kernel_size <= 0) { - error_report("could not load kernel '%s'", - loader_params->kernel_filename); - exit(1); - } - - /* load initrd */ - initrd_size = 0; - initrd_offset = 0; - if (loader_params->initrd_filename) { - initrd_size = get_image_size(loader_params->initrd_filename); - if (initrd_size > 0) { - initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) - & TARGET_PAGE_MASK; - if (initrd_offset + initrd_size > loader_params->ram_size) { - error_report("memory too small for initial ram disk '%s'", - loader_params->initrd_filename); - exit(1); - } - initrd_size = load_image_targphys(loader_params->initrd_filename, - initrd_offset, - loader_params->ram_size); - } - if (initrd_size == (target_ulong)-1) { - error_report("could not load initial ram disk '%s'", - loader_params->initrd_filename); - exit(1); - } - } -} - -static void main_cpu_reset(void *opaque) -{ - MoxieCPU *cpu = opaque; - - cpu_reset(CPU(cpu)); -} - -static void moxiesim_init(MachineState *machine) -{ - MoxieCPU *cpu = NULL; - 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; - CPUMoxieState *env; - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - MemoryRegion *rom = g_new(MemoryRegion, 1); - hwaddr ram_base = 0x200000; - LoaderParams loader_params; - - /* Init CPUs. */ - cpu = MOXIE_CPU(cpu_create(machine->cpu_type)); - env = &cpu->env; - - qemu_register_reset(main_cpu_reset, cpu); - - /* Allocate RAM. */ - memory_region_init_ram(ram, NULL, "moxiesim.ram", ram_size, &error_fatal); - memory_region_add_subregion(address_space_mem, ram_base, ram); - - memory_region_init_ram(rom, NULL, "moxie.rom", FIRMWARE_SIZE, &error_fatal); - memory_region_add_subregion(get_system_memory(), FIRMWARE_BASE, rom); - - if (kernel_filename) { - loader_params.ram_size = ram_size; - loader_params.kernel_filename = kernel_filename; - loader_params.kernel_cmdline = kernel_cmdline; - loader_params.initrd_filename = initrd_filename; - load_kernel(cpu, &loader_params); - } - if (machine->firmware) { - if (load_image_targphys(machine->firmware, FIRMWARE_BASE, FIRMWARE_SIZE) < 0) { - error_report("Failed to load firmware '%s'", machine->firmware); - } - } - - /* A single 16450 sits at offset 0x3f8. */ - if (serial_hd(0)) { - serial_mm_init(address_space_mem, 0x3f8, 0, env->irq[4], - 8000000/16, serial_hd(0), DEVICE_LITTLE_ENDIAN); - } -} - -static void moxiesim_machine_init(MachineClass *mc) -{ - mc->desc = "Moxie simulator platform"; - mc->init = moxiesim_init; - mc->is_default = true; - mc->default_cpu_type = MOXIE_CPU_TYPE_NAME("MoxieLite"); -} - -DEFINE_MACHINE("moxiesim", moxiesim_machine_init) diff --git a/hw/net/meson.build b/hw/net/meson.build index af0749c42b..bdf71f1f40 100644 --- a/hw/net/meson.build +++ b/hw/net/meson.build @@ -39,7 +39,6 @@ softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.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')) diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c deleted file mode 100644 index 5826944fd5..0000000000 --- a/hw/net/milkymist-minimac2.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * QEMU model of the Milkymist minimac2 block. - * - * Copyright (c) 2011 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * not available yet - * - */ - -#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" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "net/net.h" -#include "qemu/log.h" -#include "qemu/module.h" -#include "qemu/error-report.h" - -#include <zlib.h> - -enum { - R_SETUP = 0, - R_MDIO, - R_STATE0, - R_COUNT0, - R_STATE1, - R_COUNT1, - R_TXCOUNT, - R_MAX -}; - -enum { - SETUP_PHY_RST = (1<<0), -}; - -enum { - MDIO_DO = (1<<0), - MDIO_DI = (1<<1), - MDIO_OE = (1<<2), - MDIO_CLK = (1<<3), -}; - -enum { - STATE_EMPTY = 0, - STATE_LOADED = 1, - STATE_PENDING = 2, -}; - -enum { - MDIO_OP_WRITE = 1, - MDIO_OP_READ = 2, -}; - -enum mdio_state { - MDIO_STATE_IDLE, - MDIO_STATE_READING, - MDIO_STATE_WRITING, -}; - -enum { - R_PHY_ID1 = 2, - R_PHY_ID2 = 3, - R_PHY_MAX = 32 -}; - -#define MINIMAC2_MTU 1530 -#define MINIMAC2_BUFFER_SIZE 2048 - -struct MilkymistMinimac2MdioState { - int last_clk; - int count; - uint32_t data; - uint16_t data_out; - int state; - - uint8_t phy_addr; - uint8_t reg_addr; -}; -typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState; - -#define TYPE_MILKYMIST_MINIMAC2 "milkymist-minimac2" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistMinimac2State, MILKYMIST_MINIMAC2) - -struct MilkymistMinimac2State { - SysBusDevice parent_obj; - - NICState *nic; - NICConf conf; - char *phy_model; - MemoryRegion buffers; - MemoryRegion regs_region; - - qemu_irq rx_irq; - qemu_irq tx_irq; - - uint32_t regs[R_MAX]; - - MilkymistMinimac2MdioState mdio; - - uint16_t phy_regs[R_PHY_MAX]; - - uint8_t *rx0_buf; - uint8_t *rx1_buf; - uint8_t *tx_buf; -}; - -static const uint8_t preamble_sfd[] = { - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5 -}; - -static void minimac2_mdio_write_reg(MilkymistMinimac2State *s, - uint8_t phy_addr, uint8_t reg_addr, uint16_t value) -{ - trace_milkymist_minimac2_mdio_write(phy_addr, reg_addr, value); - - /* nop */ -} - -static uint16_t minimac2_mdio_read_reg(MilkymistMinimac2State *s, - uint8_t phy_addr, uint8_t reg_addr) -{ - uint16_t r = s->phy_regs[reg_addr]; - - trace_milkymist_minimac2_mdio_read(phy_addr, reg_addr, r); - - return r; -} - -static void minimac2_update_mdio(MilkymistMinimac2State *s) -{ - MilkymistMinimac2MdioState *m = &s->mdio; - - /* detect rising clk edge */ - if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) { - /* shift data in */ - int bit = ((s->regs[R_MDIO] & MDIO_DO) - && (s->regs[R_MDIO] & MDIO_OE)) ? 1 : 0; - m->data = (m->data << 1) | bit; - - /* check for sync */ - if (m->data == 0xffffffff) { - m->count = 32; - } - - if (m->count == 16) { - uint8_t start = (m->data >> 14) & 0x3; - uint8_t op = (m->data >> 12) & 0x3; - uint8_t ta = (m->data) & 0x3; - - if (start == 1 && op == MDIO_OP_WRITE && ta == 2) { - m->state = MDIO_STATE_WRITING; - } else if (start == 1 && op == MDIO_OP_READ && (ta & 1) == 0) { - m->state = MDIO_STATE_READING; - } else { - m->state = MDIO_STATE_IDLE; - } - - if (m->state != MDIO_STATE_IDLE) { - m->phy_addr = (m->data >> 7) & 0x1f; - m->reg_addr = (m->data >> 2) & 0x1f; - } - - if (m->state == MDIO_STATE_READING) { - m->data_out = minimac2_mdio_read_reg(s, m->phy_addr, - m->reg_addr); - } - } - - if (m->count < 16 && m->state == MDIO_STATE_READING) { - int bit = (m->data_out & 0x8000) ? 1 : 0; - m->data_out <<= 1; - - if (bit) { - s->regs[R_MDIO] |= MDIO_DI; - } else { - s->regs[R_MDIO] &= ~MDIO_DI; - } - } - - if (m->count == 0 && m->state) { - if (m->state == MDIO_STATE_WRITING) { - uint16_t data = m->data & 0xffff; - minimac2_mdio_write_reg(s, m->phy_addr, m->reg_addr, data); - } - m->state = MDIO_STATE_IDLE; - } - m->count--; - } - - m->last_clk = (s->regs[R_MDIO] & MDIO_CLK) ? 1 : 0; -} - -static size_t assemble_frame(uint8_t *buf, size_t size, - const uint8_t *payload, size_t payload_size) -{ - uint32_t crc; - - if (size < payload_size + 12) { - qemu_log_mask(LOG_GUEST_ERROR, "milkymist_minimac2: frame too big " - "(%zd bytes)\n", payload_size); - return 0; - } - - /* prepend preamble and sfd */ - memcpy(buf, preamble_sfd, 8); - - /* now copy the payload */ - memcpy(buf + 8, payload, payload_size); - - /* pad frame if needed */ - if (payload_size < 60) { - memset(buf + payload_size + 8, 0, 60 - payload_size); - payload_size = 60; - } - - /* append fcs */ - crc = cpu_to_le32(crc32(0, buf + 8, payload_size)); - memcpy(buf + payload_size + 8, &crc, 4); - - return payload_size + 12; -} - -static void minimac2_tx(MilkymistMinimac2State *s) -{ - uint32_t txcount = s->regs[R_TXCOUNT]; - uint8_t *buf = s->tx_buf; - - if (txcount < 64) { - error_report("milkymist_minimac2: ethernet frame too small (%u < %u)", - txcount, 64); - goto err; - } - - if (txcount > MINIMAC2_MTU) { - error_report("milkymist_minimac2: MTU exceeded (%u > %u)", - txcount, MINIMAC2_MTU); - goto err; - } - - if (memcmp(buf, preamble_sfd, 8) != 0) { - error_report("milkymist_minimac2: frame doesn't contain the preamble " - "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - goto err; - } - - trace_milkymist_minimac2_tx_frame(txcount - 12); - - /* send packet, skipping preamble and sfd */ - qemu_send_packet_raw(qemu_get_queue(s->nic), buf + 8, txcount - 12); - - s->regs[R_TXCOUNT] = 0; - -err: - trace_milkymist_minimac2_pulse_irq_tx(); - qemu_irq_pulse(s->tx_irq); -} - -static void update_rx_interrupt(MilkymistMinimac2State *s) -{ - if (s->regs[R_STATE0] == STATE_PENDING - || s->regs[R_STATE1] == STATE_PENDING) { - trace_milkymist_minimac2_raise_irq_rx(); - qemu_irq_raise(s->rx_irq); - } else { - trace_milkymist_minimac2_lower_irq_rx(); - qemu_irq_lower(s->rx_irq); - } -} - -static ssize_t minimac2_rx(NetClientState *nc, const uint8_t *buf, size_t size) -{ - MilkymistMinimac2State *s = qemu_get_nic_opaque(nc); - - uint32_t r_count; - uint32_t r_state; - uint8_t *rx_buf; - - size_t frame_size; - - trace_milkymist_minimac2_rx_frame(buf, size); - - /* choose appropriate slot */ - if (s->regs[R_STATE0] == STATE_LOADED) { - r_count = R_COUNT0; - r_state = R_STATE0; - rx_buf = s->rx0_buf; - } else if (s->regs[R_STATE1] == STATE_LOADED) { - r_count = R_COUNT1; - r_state = R_STATE1; - rx_buf = s->rx1_buf; - } else { - return 0; - } - - /* assemble frame */ - frame_size = assemble_frame(rx_buf, MINIMAC2_BUFFER_SIZE, buf, size); - - if (frame_size == 0) { - return size; - } - - trace_milkymist_minimac2_rx_transfer(rx_buf, frame_size); - - /* update slot */ - s->regs[r_count] = frame_size; - s->regs[r_state] = STATE_PENDING; - - update_rx_interrupt(s); - - return size; -} - -static uint64_t -minimac2_read(void *opaque, hwaddr addr, unsigned size) -{ - MilkymistMinimac2State *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_SETUP: - case R_MDIO: - case R_STATE0: - case R_COUNT0: - case R_STATE1: - case R_COUNT1: - case R_TXCOUNT: - r = s->regs[addr]; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, - "milkymist_minimac2_rd%d: 0x%" HWADDR_PRIx "\n", - size, addr << 2); - break; - } - - trace_milkymist_minimac2_memory_read(addr << 2, r); - - return r; -} - -static int minimac2_can_rx(MilkymistMinimac2State *s) -{ - if (s->regs[R_STATE0] == STATE_LOADED) { - return 1; - } - if (s->regs[R_STATE1] == STATE_LOADED) { - return 1; - } - - return 0; -} - -static void -minimac2_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistMinimac2State *s = opaque; - - trace_milkymist_minimac2_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_MDIO: - { - /* MDIO_DI is read only */ - int mdio_di = (s->regs[R_MDIO] & MDIO_DI); - s->regs[R_MDIO] = value; - if (mdio_di) { - s->regs[R_MDIO] |= mdio_di; - } else { - s->regs[R_MDIO] &= ~mdio_di; - } - - minimac2_update_mdio(s); - } break; - case R_TXCOUNT: - s->regs[addr] = value; - if (value > 0) { - minimac2_tx(s); - } - break; - case R_STATE0: - case R_STATE1: - s->regs[addr] = value; - update_rx_interrupt(s); - if (minimac2_can_rx(s)) { - qemu_flush_queued_packets(qemu_get_queue(s->nic)); - } - break; - case R_SETUP: - case R_COUNT0: - case R_COUNT1: - s->regs[addr] = value; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, - "milkymist_minimac2_wr%d: 0x%" HWADDR_PRIx - " = 0x%" PRIx64 "\n", - size, addr << 2, value); - break; - } -} - -static const MemoryRegionOps minimac2_ops = { - .read = minimac2_read, - .write = minimac2_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_minimac2_reset(DeviceState *d) -{ - MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - for (i = 0; i < R_PHY_MAX; i++) { - s->phy_regs[i] = 0; - } - - /* defaults */ - s->phy_regs[R_PHY_ID1] = 0x0022; /* Micrel KSZ8001L */ - s->phy_regs[R_PHY_ID2] = 0x161a; -} - -static NetClientInfo net_milkymist_minimac2_info = { - .type = NET_CLIENT_DRIVER_NIC, - .size = sizeof(NICState), - .receive = minimac2_rx, -}; - -static void milkymist_minimac2_realize(DeviceState *dev, Error **errp) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(dev); - size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE); - - sysbus_init_irq(sbd, &s->rx_irq); - sysbus_init_irq(sbd, &s->tx_irq); - - memory_region_init_io(&s->regs_region, OBJECT(dev), &minimac2_ops, s, - "milkymist-minimac2", R_MAX * 4); - sysbus_init_mmio(sbd, &s->regs_region); - - /* register buffers memory */ - memory_region_init_ram_nomigrate(&s->buffers, OBJECT(dev), "milkymist-minimac2.buffers", - buffers_size, &error_fatal); - vmstate_register_ram_global(&s->buffers); - s->rx0_buf = memory_region_get_ram_ptr(&s->buffers); - s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE; - s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE; - - sysbus_init_mmio(sbd, &s->buffers); - - qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); - qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); -} - -static const VMStateDescription vmstate_milkymist_minimac2_mdio = { - .name = "milkymist-minimac2-mdio", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_INT32(last_clk, MilkymistMinimac2MdioState), - VMSTATE_INT32(count, MilkymistMinimac2MdioState), - VMSTATE_UINT32(data, MilkymistMinimac2MdioState), - VMSTATE_UINT16(data_out, MilkymistMinimac2MdioState), - VMSTATE_INT32(state, MilkymistMinimac2MdioState), - VMSTATE_UINT8(phy_addr, MilkymistMinimac2MdioState), - VMSTATE_UINT8(reg_addr, MilkymistMinimac2MdioState), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_milkymist_minimac2 = { - .name = "milkymist-minimac2", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistMinimac2State, R_MAX), - VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimac2State, R_PHY_MAX), - VMSTATE_STRUCT(mdio, MilkymistMinimac2State, 0, - vmstate_milkymist_minimac2_mdio, MilkymistMinimac2MdioState), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_minimac2_properties[] = { - DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf), - DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_minimac2_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_minimac2_realize; - dc->reset = milkymist_minimac2_reset; - dc->vmsd = &vmstate_milkymist_minimac2; - device_class_set_props(dc, milkymist_minimac2_properties); -} - -static const TypeInfo milkymist_minimac2_info = { - .name = TYPE_MILKYMIST_MINIMAC2, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistMinimac2State), - .class_init = milkymist_minimac2_class_init, -}; - -static void milkymist_minimac2_register_types(void) -{ - type_register_static(&milkymist_minimac2_info); -} - -type_init(milkymist_minimac2_register_types) diff --git a/hw/net/trace-events b/hw/net/trace-events index baf25ffa7e..314e21fa99 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -19,18 +19,6 @@ mdio_bitbang(bool mdc, bool mdio, int state, uint16_t cnt, unsigned int drive) " lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x" lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x" -# milkymist-minimac2.c -milkymist_minimac2_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_minimac2_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_minimac2_mdio_write(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr 0x%02x addr 0x%02x value 0x%04x" -milkymist_minimac2_mdio_read(uint8_t phy_addr, uint8_t addr, uint16_t value) "phy_addr 0x%02x addr 0x%02x value 0x%04x" -milkymist_minimac2_tx_frame(uint32_t length) "length %u" -milkymist_minimac2_rx_frame(const void *buf, uint32_t length) "buf %p length %u" -milkymist_minimac2_rx_transfer(const void *buf, uint32_t length) "buf %p length %d" -milkymist_minimac2_raise_irq_rx(void) "Raise IRQ RX" -milkymist_minimac2_lower_irq_rx(void) "Lower IRQ RX" -milkymist_minimac2_pulse_irq_tx(void) "Pulse IRQ TX" - # mipsnet.c mipsnet_send(uint32_t size) "sending len=%u" mipsnet_receive(uint32_t size) "receiving len=%u" diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 4ad8793406..28e003250a 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -94,8 +94,7 @@ static bool virtio_scsi_data_plane_handle_event(VirtIODevice *vdev, return progress; } -static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n, - VirtIOHandleAIOOutput fn) +static int virtio_scsi_set_host_notifier(VirtIOSCSI *s, VirtQueue *vq, int n) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); int rc; @@ -109,7 +108,6 @@ static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n, return rc; } - virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, fn); return 0; } @@ -154,40 +152,55 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev) goto fail_guest_notifiers; } - aio_context_acquire(s->ctx); - rc = virtio_scsi_vring_init(s, vs->ctrl_vq, 0, - virtio_scsi_data_plane_handle_ctrl); - if (rc) { - goto fail_vrings; + memory_region_transaction_begin(); + + rc = virtio_scsi_set_host_notifier(s, vs->ctrl_vq, 0); + if (rc != 0) { + goto fail_host_notifiers; } vq_init_count++; - rc = virtio_scsi_vring_init(s, vs->event_vq, 1, - virtio_scsi_data_plane_handle_event); - if (rc) { - goto fail_vrings; + rc = virtio_scsi_set_host_notifier(s, vs->event_vq, 1); + if (rc != 0) { + goto fail_host_notifiers; } vq_init_count++; + for (i = 0; i < vs->conf.num_queues; i++) { - rc = virtio_scsi_vring_init(s, vs->cmd_vqs[i], i + 2, - virtio_scsi_data_plane_handle_cmd); + rc = virtio_scsi_set_host_notifier(s, vs->cmd_vqs[i], i + 2); if (rc) { - goto fail_vrings; + goto fail_host_notifiers; } vq_init_count++; } + memory_region_transaction_commit(); + + aio_context_acquire(s->ctx); + virtio_queue_aio_set_host_notifier_handler(vs->ctrl_vq, s->ctx, + virtio_scsi_data_plane_handle_ctrl); + virtio_queue_aio_set_host_notifier_handler(vs->event_vq, s->ctx, + virtio_scsi_data_plane_handle_event); + + for (i = 0; i < vs->conf.num_queues; i++) { + virtio_queue_aio_set_host_notifier_handler(vs->cmd_vqs[i], s->ctx, + virtio_scsi_data_plane_handle_cmd); + } + s->dataplane_starting = false; s->dataplane_started = true; aio_context_release(s->ctx); return 0; -fail_vrings: - aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s); - aio_context_release(s->ctx); +fail_host_notifiers: for (i = 0; i < vq_init_count; i++) { virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false); + } + + memory_region_transaction_commit(); + + for (i = 0; i < vq_init_count; i++) { virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); } k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false); @@ -225,8 +238,15 @@ void virtio_scsi_dataplane_stop(VirtIODevice *vdev) blk_drain_all(); /* ensure there are no in-flight requests */ + memory_region_transaction_begin(); + for (i = 0; i < vs->conf.num_queues + 2; i++) { virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false); + } + + memory_region_transaction_commit(); + + for (i = 0; i < vs->conf.num_queues + 2; i++) { virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); } diff --git a/hw/sd/meson.build b/hw/sd/meson.build index 9c29691e13..f1ce357a3b 100644 --- a/hw/sd/meson.build +++ b/hw/sd/meson.build @@ -4,7 +4,6 @@ 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')) diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c deleted file mode 100644 index a1235aa46c..0000000000 --- a/hw/sd/milkymist-memcard.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * QEMU model of the Milkymist SD Card Controller. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/memcard.pdf - */ - -#include "qemu/osdep.h" -#include "qemu/log.h" -#include "qemu/module.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "qapi/error.h" -#include "sysemu/block-backend.h" -#include "sysemu/blockdev.h" -#include "hw/qdev-properties.h" -#include "hw/sd/sd.h" -#include "qom/object.h" - -enum { - ENABLE_CMD_TX = (1<<0), - ENABLE_CMD_RX = (1<<1), - ENABLE_DAT_TX = (1<<2), - ENABLE_DAT_RX = (1<<3), -}; - -enum { - PENDING_CMD_TX = (1<<0), - PENDING_CMD_RX = (1<<1), - PENDING_DAT_TX = (1<<2), - PENDING_DAT_RX = (1<<3), -}; - -enum { - START_CMD_TX = (1<<0), - START_DAT_RX = (1<<1), -}; - -enum { - R_CLK2XDIV = 0, - R_ENABLE, - R_PENDING, - R_START, - R_CMD, - R_DAT, - R_MAX -}; - -#define TYPE_MILKYMIST_MEMCARD "milkymist-memcard" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistMemcardState, MILKYMIST_MEMCARD) - -#define TYPE_MILKYMIST_SDBUS "milkymist-sdbus" - -struct MilkymistMemcardState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - SDBus sdbus; - - int command_write_ptr; - int response_read_ptr; - int response_len; - int ignore_next_cmd; - int enabled; - uint8_t command[6]; - uint8_t response[17]; - uint32_t regs[R_MAX]; -}; - -static void update_pending_bits(MilkymistMemcardState *s) -{ - /* transmits are instantaneous, thus tx pending bits are never set */ - s->regs[R_PENDING] = 0; - /* if rx is enabled the corresponding pending bits are always set */ - if (s->regs[R_ENABLE] & ENABLE_CMD_RX) { - s->regs[R_PENDING] |= PENDING_CMD_RX; - } - if (s->regs[R_ENABLE] & ENABLE_DAT_RX) { - s->regs[R_PENDING] |= PENDING_DAT_RX; - } -} - -static void memcard_sd_command(MilkymistMemcardState *s) -{ - SDRequest req; - - req.cmd = s->command[0] & 0x3f; - req.arg = ldl_be_p(s->command + 1); - req.crc = s->command[5]; - - s->response[0] = req.cmd; - s->response_len = sdbus_do_command(&s->sdbus, &req, s->response + 1); - s->response_read_ptr = 0; - - if (s->response_len == 16) { - /* R2 response */ - s->response[0] = 0x3f; - s->response_len += 1; - } else if (s->response_len == 4) { - /* no crc calculation, insert dummy byte */ - s->response[5] = 0; - s->response_len += 2; - } - - if (req.cmd == 0) { - /* next write is a dummy byte to clock the initialization of the sd - * card */ - s->ignore_next_cmd = 1; - } -} - -static uint64_t memcard_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistMemcardState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_CMD: - if (!s->enabled) { - r = 0xff; - } else { - r = s->response[s->response_read_ptr++]; - if (s->response_read_ptr > s->response_len) { - qemu_log_mask(LOG_GUEST_ERROR, "milkymist_memcard: " - "read more cmd bytes than available: clipping\n"); - s->response_read_ptr = 0; - } - } - break; - case R_DAT: - if (!s->enabled) { - r = 0xffffffff; - } else { - sdbus_read_data(&s->sdbus, &r, sizeof(r)); - be32_to_cpus(&r); - } - break; - case R_CLK2XDIV: - case R_ENABLE: - case R_PENDING: - case R_START: - r = s->regs[addr]; - break; - - default: - qemu_log_mask(LOG_UNIMP, "milkymist_memcard: " - "read access to unknown register 0x%" HWADDR_PRIx "\n", - addr << 2); - break; - } - - trace_milkymist_memcard_memory_read(addr << 2, r); - - return r; -} - -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); - - addr >>= 2; - switch (addr) { - case R_PENDING: - /* clear rx pending bits */ - s->regs[R_PENDING] &= ~(value & (PENDING_CMD_RX | PENDING_DAT_RX)); - update_pending_bits(s); - break; - case R_CMD: - if (!s->enabled) { - break; - } - if (s->ignore_next_cmd) { - s->ignore_next_cmd = 0; - break; - } - s->command[s->command_write_ptr] = value & 0xff; - s->command_write_ptr = (s->command_write_ptr + 1) % 6; - if (s->command_write_ptr == 0) { - memcard_sd_command(s); - } - break; - case R_DAT: - if (!s->enabled) { - break; - } - val32 = cpu_to_be32(value); - sdbus_write_data(&s->sdbus, &val32, sizeof(val32)); - break; - case R_ENABLE: - s->regs[addr] = value; - update_pending_bits(s); - break; - case R_CLK2XDIV: - case R_START: - s->regs[addr] = value; - break; - - default: - qemu_log_mask(LOG_UNIMP, "milkymist_memcard: " - "write access to unknown register 0x%" HWADDR_PRIx " " - "(value 0x%" PRIx64 ")\n", addr << 2, value); - break; - } -} - -static const MemoryRegionOps memcard_mmio_ops = { - .read = memcard_read, - .write = memcard_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void milkymist_memcard_reset(DeviceState *d) -{ - MilkymistMemcardState *s = MILKYMIST_MEMCARD(d); - int i; - - s->command_write_ptr = 0; - s->response_read_ptr = 0; - s->response_len = 0; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } -} - -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); - SysBusDevice *dev = SYS_BUS_DEVICE(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); - - qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, - DEVICE(obj), "sd-bus"); -} - -static const VMStateDescription vmstate_milkymist_memcard = { - .name = "milkymist-memcard", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_INT32(command_write_ptr, MilkymistMemcardState), - VMSTATE_INT32(response_read_ptr, MilkymistMemcardState), - VMSTATE_INT32(response_len, MilkymistMemcardState), - VMSTATE_INT32(ignore_next_cmd, MilkymistMemcardState), - VMSTATE_INT32(enabled, MilkymistMemcardState), - VMSTATE_UINT8_ARRAY(command, MilkymistMemcardState, 6), - VMSTATE_UINT8_ARRAY(response, MilkymistMemcardState, 17), - VMSTATE_UINT32_ARRAY(regs, MilkymistMemcardState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static void milkymist_memcard_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = milkymist_memcard_reset; - dc->vmsd = &vmstate_milkymist_memcard; - /* Reason: output IRQs should be wired up */ - dc->user_creatable = false; -} - -static const TypeInfo milkymist_memcard_info = { - .name = TYPE_MILKYMIST_MEMCARD, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistMemcardState), - .instance_init = milkymist_memcard_init, - .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/trace-events b/hw/sd/trace-events index 4140e48540..e185d07a1d 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -55,10 +55,6 @@ sdcard_write_data(const char *proto, const char *cmd_desc, uint8_t cmd, uint8_t 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 -milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" - # 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" diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index f22c4f5b73..7397e56737 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -27,6 +27,7 @@ #include "hw/firmware/smbios.h" #include "hw/loader.h" #include "hw/boards.h" +#include "hw/pci/pci_bus.h" #include "smbios_build.h" /* legacy structures and constants for <= 2.0 machines */ @@ -118,6 +119,28 @@ static struct { uint16_t speed; } type17; +static QEnumLookup type41_kind_lookup = { + .array = (const char *const[]) { + "other", + "unknown", + "video", + "scsi", + "ethernet", + "tokenring", + "sound", + "pata", + "sata", + "sas", + }, + .size = 10 +}; +struct type41_instance { + const char *designation, *pcidev; + uint8_t instance, kind; + QTAILQ_ENTRY(type41_instance) next; +}; +static QTAILQ_HEAD(, type41_instance) type41 = QTAILQ_HEAD_INITIALIZER(type41); + static QemuOptsList qemu_smbios_opts = { .name = "smbios", .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head), @@ -358,6 +381,32 @@ static const QemuOptDesc qemu_smbios_type17_opts[] = { { /* end of list */ } }; +static const QemuOptDesc qemu_smbios_type41_opts[] = { + { + .name = "type", + .type = QEMU_OPT_NUMBER, + .help = "SMBIOS element type", + },{ + .name = "designation", + .type = QEMU_OPT_STRING, + .help = "reference designation string", + },{ + .name = "kind", + .type = QEMU_OPT_STRING, + .help = "device type", + .def_value_str = "other", + },{ + .name = "instance", + .type = QEMU_OPT_NUMBER, + .help = "device type instance", + },{ + .name = "pcidev", + .type = QEMU_OPT_STRING, + .help = "PCI device", + }, + { /* end of list */ } +}; + static void smbios_register_config(void) { qemu_add_opts(&qemu_smbios_opts); @@ -773,6 +822,53 @@ static void smbios_build_type_32_table(void) SMBIOS_BUILD_TABLE_POST; } +static void smbios_build_type_41_table(Error **errp) +{ + unsigned instance = 0; + struct type41_instance *t41; + + QTAILQ_FOREACH(t41, &type41, next) { + SMBIOS_BUILD_TABLE_PRE(41, 0x2900 + instance, true); + + SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation); + t->device_type = t41->kind; + t->device_type_instance = t41->instance; + t->segment_group_number = cpu_to_le16(0); + t->bus_number = 0; + t->device_number = 0; + + if (t41->pcidev) { + PCIDevice *pdev = NULL; + int rc = pci_qdev_find_device(t41->pcidev, &pdev); + if (rc != 0) { + error_setg(errp, + "No PCI device %s for SMBIOS type 41 entry %s", + t41->pcidev, t41->designation); + return; + } + /* + * We only handle the case were the device is attached to + * the PCI root bus. The general case is more complex as + * bridges are enumerated later and the table would need + * to be updated at this moment. + */ + if (!pci_bus_is_root(pci_get_bus(pdev))) { + error_setg(errp, + "Cannot create type 41 entry for PCI device %s: " + "not attached to the root bus", + t41->pcidev); + return; + } + t->segment_group_number = cpu_to_le16(0); + t->bus_number = pci_dev_bus_num(pdev); + t->device_number = pdev->devfn; + } + + SMBIOS_BUILD_TABLE_POST; + instance++; + } +} + static void smbios_build_type_127_table(void) { SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */ @@ -883,7 +979,8 @@ void smbios_get_tables(MachineState *ms, const struct smbios_phys_mem_area *mem_array, const unsigned int mem_array_size, uint8_t **tables, size_t *tables_len, - uint8_t **anchor, size_t *anchor_len) + uint8_t **anchor, size_t *anchor_len, + Error **errp) { unsigned i, dimm_cnt; @@ -928,6 +1025,7 @@ void smbios_get_tables(MachineState *ms, smbios_build_type_32_table(); smbios_build_type_38_table(); + smbios_build_type_41_table(errp); smbios_build_type_127_table(); smbios_validate_table(ms); @@ -1224,6 +1322,30 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) save_opt(&type17.part, opts, "part"); type17.speed = qemu_opt_get_number(opts, "speed", 0); return; + case 41: { + struct type41_instance *t; + Error *local_err = NULL; + + if (!qemu_opts_validate(opts, qemu_smbios_type41_opts, errp)) { + return; + } + t = g_new0(struct type41_instance, 1); + save_opt(&t->designation, opts, "designation"); + t->kind = qapi_enum_parse(&type41_kind_lookup, + qemu_opt_get(opts, "kind"), + 0, &local_err) + 1; + t->kind |= 0x80; /* enabled */ + if (local_err != NULL) { + error_propagate(errp, local_err); + g_free(t); + return; + } + t->instance = qemu_opt_get_number(opts, "instance", 1); + save_opt(&t->pcidev, opts, "pcidev"); + + QTAILQ_INSERT_TAIL(&type41, t, next); + return; + } default: error_setg(errp, "Don't know how to build fields for SMBIOS type %ld", diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c deleted file mode 100644 index eeaf0ada5f..0000000000 --- a/hw/timer/lm32_timer.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * QEMU model of the LatticeMico32 timer block. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://www.latticesemi.com/documents/mico32timer.pdf - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "qemu/timer.h" -#include "hw/ptimer.h" -#include "hw/qdev-properties.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -#define DEFAULT_FREQUENCY (50*1000000) - -enum { - R_SR = 0, - R_CR, - R_PERIOD, - R_SNAPSHOT, - R_MAX -}; - -enum { - SR_TO = (1 << 0), - SR_RUN = (1 << 1), -}; - -enum { - CR_ITO = (1 << 0), - CR_CONT = (1 << 1), - CR_START = (1 << 2), - CR_STOP = (1 << 3), -}; - -#define TYPE_LM32_TIMER "lm32-timer" -OBJECT_DECLARE_SIMPLE_TYPE(LM32TimerState, LM32_TIMER) - -struct LM32TimerState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - - ptimer_state *ptimer; - - qemu_irq irq; - uint32_t freq_hz; - - uint32_t regs[R_MAX]; -}; - -static void timer_update_irq(LM32TimerState *s) -{ - int state = (s->regs[R_SR] & SR_TO) && (s->regs[R_CR] & CR_ITO); - - trace_lm32_timer_irq_state(state); - qemu_set_irq(s->irq, state); -} - -static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) -{ - LM32TimerState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_SR: - case R_CR: - case R_PERIOD: - r = s->regs[addr]; - break; - case R_SNAPSHOT: - r = (uint32_t)ptimer_get_count(s->ptimer); - break; - default: - error_report("lm32_timer: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_lm32_timer_memory_read(addr << 2, r); - return r; -} - -static void timer_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - LM32TimerState *s = opaque; - - trace_lm32_timer_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_SR: - s->regs[R_SR] &= ~SR_TO; - break; - case R_CR: - ptimer_transaction_begin(s->ptimer); - s->regs[R_CR] = value; - if (s->regs[R_CR] & CR_START) { - ptimer_run(s->ptimer, 1); - } - if (s->regs[R_CR] & CR_STOP) { - ptimer_stop(s->ptimer); - } - ptimer_transaction_commit(s->ptimer); - break; - case R_PERIOD: - s->regs[R_PERIOD] = value; - ptimer_transaction_begin(s->ptimer); - ptimer_set_count(s->ptimer, value); - ptimer_transaction_commit(s->ptimer); - break; - case R_SNAPSHOT: - error_report("lm32_timer: write access to read only register 0x" - TARGET_FMT_plx, addr << 2); - break; - default: - error_report("lm32_timer: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - timer_update_irq(s); -} - -static const MemoryRegionOps timer_ops = { - .read = timer_read, - .write = timer_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void timer_hit(void *opaque) -{ - LM32TimerState *s = opaque; - - trace_lm32_timer_hit(); - - s->regs[R_SR] |= SR_TO; - - if (s->regs[R_CR] & CR_CONT) { - ptimer_set_count(s->ptimer, s->regs[R_PERIOD]); - ptimer_run(s->ptimer, 1); - } - timer_update_irq(s); -} - -static void timer_reset(DeviceState *d) -{ - LM32TimerState *s = LM32_TIMER(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - ptimer_transaction_begin(s->ptimer); - ptimer_stop(s->ptimer); - ptimer_transaction_commit(s->ptimer); -} - -static void lm32_timer_init(Object *obj) -{ - LM32TimerState *s = LM32_TIMER(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - - sysbus_init_irq(dev, &s->irq); - - memory_region_init_io(&s->iomem, obj, &timer_ops, s, - "timer", R_MAX * 4); - sysbus_init_mmio(dev, &s->iomem); -} - -static void lm32_timer_realize(DeviceState *dev, Error **errp) -{ - LM32TimerState *s = LM32_TIMER(dev); - - s->ptimer = ptimer_init(timer_hit, s, PTIMER_POLICY_DEFAULT); - - ptimer_transaction_begin(s->ptimer); - ptimer_set_freq(s->ptimer, s->freq_hz); - ptimer_transaction_commit(s->ptimer); -} - -static const VMStateDescription vmstate_lm32_timer = { - .name = "lm32-timer", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_PTIMER(ptimer, LM32TimerState), - VMSTATE_UINT32(freq_hz, LM32TimerState), - VMSTATE_UINT32_ARRAY(regs, LM32TimerState, R_MAX), - VMSTATE_END_OF_LIST() - } -}; - -static Property lm32_timer_properties[] = { - DEFINE_PROP_UINT32("frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY), - DEFINE_PROP_END_OF_LIST(), -}; - -static void lm32_timer_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = lm32_timer_realize; - dc->reset = timer_reset; - dc->vmsd = &vmstate_lm32_timer; - device_class_set_props(dc, lm32_timer_properties); -} - -static const TypeInfo lm32_timer_info = { - .name = TYPE_LM32_TIMER, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LM32TimerState), - .instance_init = lm32_timer_init, - .class_init = lm32_timer_class_init, -}; - -static void lm32_timer_register_types(void) -{ - type_register_static(&lm32_timer_info); -} - -type_init(lm32_timer_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 598d058506..157f540ecd 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -19,15 +19,12 @@ 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_DEVICES', 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_SH_TIMER', if_true: files('sh_timer.c')) diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c deleted file mode 100644 index 9ecea63861..0000000000 --- a/hw/timer/milkymist-sysctl.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * QEMU model of the Milkymist System Controller. - * - * Copyright (c) 2010-2012 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/sysctl.pdf - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/sysbus.h" -#include "migration/vmstate.h" -#include "trace.h" -#include "qemu/timer.h" -#include "sysemu/runstate.h" -#include "hw/ptimer.h" -#include "hw/qdev-properties.h" -#include "qemu/error-report.h" -#include "qemu/module.h" -#include "qom/object.h" - -enum { - CTRL_ENABLE = (1<<0), - CTRL_AUTORESTART = (1<<1), -}; - -enum { - ICAP_READY = (1<<0), -}; - -enum { - R_GPIO_IN = 0, - R_GPIO_OUT, - R_GPIO_INTEN, - R_TIMER0_CONTROL = 4, - R_TIMER0_COMPARE, - R_TIMER0_COUNTER, - R_TIMER1_CONTROL = 8, - R_TIMER1_COMPARE, - R_TIMER1_COUNTER, - R_ICAP = 16, - R_DBG_SCRATCHPAD = 20, - R_DBG_WRITE_LOCK, - R_CLK_FREQUENCY = 29, - R_CAPABILITIES, - R_SYSTEM_ID, - R_MAX -}; - -#define TYPE_MILKYMIST_SYSCTL "milkymist-sysctl" -OBJECT_DECLARE_SIMPLE_TYPE(MilkymistSysctlState, MILKYMIST_SYSCTL) - -struct MilkymistSysctlState { - SysBusDevice parent_obj; - - MemoryRegion regs_region; - - ptimer_state *ptimer0; - ptimer_state *ptimer1; - - uint32_t freq_hz; - uint32_t capabilities; - uint32_t systemid; - uint32_t strappings; - - uint32_t regs[R_MAX]; - - qemu_irq gpio_irq; - qemu_irq timer0_irq; - qemu_irq timer1_irq; -}; - -static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value) -{ - trace_milkymist_sysctl_icap_write(value); - switch (value & 0xffff) { - case 0x000e: - qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); - break; - } -} - -static uint64_t sysctl_read(void *opaque, hwaddr addr, - unsigned size) -{ - MilkymistSysctlState *s = opaque; - uint32_t r = 0; - - addr >>= 2; - switch (addr) { - case R_TIMER0_COUNTER: - r = (uint32_t)ptimer_get_count(s->ptimer0); - /* milkymist timer counts up */ - r = s->regs[R_TIMER0_COMPARE] - r; - break; - case R_TIMER1_COUNTER: - r = (uint32_t)ptimer_get_count(s->ptimer1); - /* milkymist timer counts up */ - r = s->regs[R_TIMER1_COMPARE] - r; - break; - case R_GPIO_IN: - case R_GPIO_OUT: - case R_GPIO_INTEN: - case R_TIMER0_CONTROL: - case R_TIMER0_COMPARE: - case R_TIMER1_CONTROL: - case R_TIMER1_COMPARE: - case R_ICAP: - case R_DBG_SCRATCHPAD: - case R_DBG_WRITE_LOCK: - case R_CLK_FREQUENCY: - case R_CAPABILITIES: - case R_SYSTEM_ID: - r = s->regs[addr]; - break; - - default: - error_report("milkymist_sysctl: read access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } - - trace_milkymist_sysctl_memory_read(addr << 2, r); - - return r; -} - -static void sysctl_write(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - MilkymistSysctlState *s = opaque; - - trace_milkymist_sysctl_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_GPIO_OUT: - case R_GPIO_INTEN: - case R_TIMER0_COUNTER: - case R_TIMER1_COUNTER: - case R_DBG_SCRATCHPAD: - s->regs[addr] = value; - break; - case R_TIMER0_COMPARE: - ptimer_transaction_begin(s->ptimer0); - ptimer_set_limit(s->ptimer0, value, 0); - s->regs[addr] = value; - ptimer_transaction_commit(s->ptimer0); - break; - case R_TIMER1_COMPARE: - ptimer_transaction_begin(s->ptimer1); - ptimer_set_limit(s->ptimer1, value, 0); - s->regs[addr] = value; - ptimer_transaction_commit(s->ptimer1); - break; - case R_TIMER0_CONTROL: - ptimer_transaction_begin(s->ptimer0); - s->regs[addr] = value; - if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) { - trace_milkymist_sysctl_start_timer0(); - ptimer_set_count(s->ptimer0, - s->regs[R_TIMER0_COMPARE] - s->regs[R_TIMER0_COUNTER]); - ptimer_run(s->ptimer0, 0); - } else { - trace_milkymist_sysctl_stop_timer0(); - ptimer_stop(s->ptimer0); - } - ptimer_transaction_commit(s->ptimer0); - break; - case R_TIMER1_CONTROL: - ptimer_transaction_begin(s->ptimer1); - s->regs[addr] = value; - if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) { - trace_milkymist_sysctl_start_timer1(); - ptimer_set_count(s->ptimer1, - s->regs[R_TIMER1_COMPARE] - s->regs[R_TIMER1_COUNTER]); - ptimer_run(s->ptimer1, 0); - } else { - trace_milkymist_sysctl_stop_timer1(); - ptimer_stop(s->ptimer1); - } - ptimer_transaction_commit(s->ptimer1); - break; - case R_ICAP: - sysctl_icap_write(s, value); - break; - case R_DBG_WRITE_LOCK: - s->regs[addr] = 1; - break; - case R_SYSTEM_ID: - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - break; - - case R_GPIO_IN: - case R_CLK_FREQUENCY: - case R_CAPABILITIES: - error_report("milkymist_sysctl: write to read-only register 0x" - TARGET_FMT_plx, addr << 2); - break; - - default: - error_report("milkymist_sysctl: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static const MemoryRegionOps sysctl_mmio_ops = { - .read = sysctl_read, - .write = sysctl_write, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void timer0_hit(void *opaque) -{ - MilkymistSysctlState *s = opaque; - - if (!(s->regs[R_TIMER0_CONTROL] & CTRL_AUTORESTART)) { - s->regs[R_TIMER0_CONTROL] &= ~CTRL_ENABLE; - trace_milkymist_sysctl_stop_timer0(); - ptimer_stop(s->ptimer0); - } - - trace_milkymist_sysctl_pulse_irq_timer0(); - qemu_irq_pulse(s->timer0_irq); -} - -static void timer1_hit(void *opaque) -{ - MilkymistSysctlState *s = opaque; - - if (!(s->regs[R_TIMER1_CONTROL] & CTRL_AUTORESTART)) { - s->regs[R_TIMER1_CONTROL] &= ~CTRL_ENABLE; - trace_milkymist_sysctl_stop_timer1(); - ptimer_stop(s->ptimer1); - } - - trace_milkymist_sysctl_pulse_irq_timer1(); - qemu_irq_pulse(s->timer1_irq); -} - -static void milkymist_sysctl_reset(DeviceState *d) -{ - MilkymistSysctlState *s = MILKYMIST_SYSCTL(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - - ptimer_transaction_begin(s->ptimer0); - ptimer_stop(s->ptimer0); - ptimer_transaction_commit(s->ptimer0); - ptimer_transaction_begin(s->ptimer1); - ptimer_stop(s->ptimer1); - ptimer_transaction_commit(s->ptimer1); - - /* defaults */ - s->regs[R_ICAP] = ICAP_READY; - s->regs[R_SYSTEM_ID] = s->systemid; - s->regs[R_CLK_FREQUENCY] = s->freq_hz; - s->regs[R_CAPABILITIES] = s->capabilities; - s->regs[R_GPIO_IN] = s->strappings; -} - -static void milkymist_sysctl_init(Object *obj) -{ - MilkymistSysctlState *s = MILKYMIST_SYSCTL(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - - sysbus_init_irq(dev, &s->gpio_irq); - sysbus_init_irq(dev, &s->timer0_irq); - sysbus_init_irq(dev, &s->timer1_irq); - - memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s, - "milkymist-sysctl", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); -} - -static void milkymist_sysctl_realize(DeviceState *dev, Error **errp) -{ - MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev); - - s->ptimer0 = ptimer_init(timer0_hit, s, PTIMER_POLICY_DEFAULT); - s->ptimer1 = ptimer_init(timer1_hit, s, PTIMER_POLICY_DEFAULT); - - ptimer_transaction_begin(s->ptimer0); - ptimer_set_freq(s->ptimer0, s->freq_hz); - ptimer_transaction_commit(s->ptimer0); - ptimer_transaction_begin(s->ptimer1); - ptimer_set_freq(s->ptimer1, s->freq_hz); - ptimer_transaction_commit(s->ptimer1); -} - -static const VMStateDescription vmstate_milkymist_sysctl = { - .name = "milkymist-sysctl", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, MilkymistSysctlState, R_MAX), - VMSTATE_PTIMER(ptimer0, MilkymistSysctlState), - VMSTATE_PTIMER(ptimer1, MilkymistSysctlState), - VMSTATE_END_OF_LIST() - } -}; - -static Property milkymist_sysctl_properties[] = { - DEFINE_PROP_UINT32("frequency", MilkymistSysctlState, - freq_hz, 80000000), - DEFINE_PROP_UINT32("capabilities", MilkymistSysctlState, - capabilities, 0x00000000), - DEFINE_PROP_UINT32("systemid", MilkymistSysctlState, - systemid, 0x10014d31), - DEFINE_PROP_UINT32("gpio_strappings", MilkymistSysctlState, - strappings, 0x00000001), - DEFINE_PROP_END_OF_LIST(), -}; - -static void milkymist_sysctl_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = milkymist_sysctl_realize; - dc->reset = milkymist_sysctl_reset; - dc->vmsd = &vmstate_milkymist_sysctl; - device_class_set_props(dc, milkymist_sysctl_properties); -} - -static const TypeInfo milkymist_sysctl_info = { - .name = TYPE_MILKYMIST_SYSCTL, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MilkymistSysctlState), - .instance_init = milkymist_sysctl_init, - .class_init = milkymist_sysctl_class_init, -}; - -static void milkymist_sysctl_register_types(void) -{ - type_register_static(&milkymist_sysctl_info); -} - -type_init(milkymist_sysctl_register_types) diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c deleted file mode 100644 index d5bf26b56b..0000000000 --- a/hw/timer/puv3_ost.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * OSTimer device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#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" -OBJECT_DECLARE_SIMPLE_TYPE(PUV3OSTState, PUV3_OST) - -/* puv3 ostimer implementation. */ -struct PUV3OSTState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq irq; - ptimer_state *ptimer; - - uint32_t reg_OSMR0; - uint32_t reg_OSCR; - uint32_t reg_OSSR; - uint32_t reg_OIER; -}; - -static uint64_t puv3_ost_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3OSTState *s = opaque; - uint32_t ret = 0; - - switch (offset) { - case 0x10: /* Counter Register */ - ret = s->reg_OSMR0 - (uint32_t)ptimer_get_count(s->ptimer); - break; - case 0x14: /* Status Register */ - ret = s->reg_OSSR; - break; - case 0x1c: /* Interrupt Enable Register */ - ret = s->reg_OIER; - break; - default: - 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; -} - -static void puv3_ost_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3OSTState *s = opaque; - - DPRINTF("offset 0x%x, value 0x%x\n", offset, value); - switch (offset) { - case 0x00: /* Match Register 0 */ - ptimer_transaction_begin(s->ptimer); - s->reg_OSMR0 = value; - if (s->reg_OSMR0 > s->reg_OSCR) { - ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR); - } else { - ptimer_set_count(s->ptimer, s->reg_OSMR0 + - (0xffffffff - s->reg_OSCR)); - } - ptimer_run(s->ptimer, 2); - ptimer_transaction_commit(s->ptimer); - break; - case 0x14: /* Status Register */ - assert(value == 0); - if (s->reg_OSSR) { - s->reg_OSSR = value; - qemu_irq_lower(s->irq); - } - break; - case 0x1c: /* Interrupt Enable Register */ - s->reg_OIER = value; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Bad write offset 0x%"HWADDR_PRIx"\n", - __func__, offset); - } -} - -static const MemoryRegionOps puv3_ost_ops = { - .read = puv3_ost_read, - .write = puv3_ost_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void puv3_ost_tick(void *opaque) -{ - PUV3OSTState *s = opaque; - - DPRINTF("ost hit when ptimer counter from 0x%x to 0x%x!\n", - s->reg_OSCR, s->reg_OSMR0); - - s->reg_OSCR = s->reg_OSMR0; - if (s->reg_OIER) { - s->reg_OSSR = 1; - qemu_irq_raise(s->irq); - } -} - -static void puv3_ost_realize(DeviceState *dev, Error **errp) -{ - PUV3OSTState *s = PUV3_OST(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - s->reg_OIER = 0; - s->reg_OSSR = 0; - s->reg_OSMR0 = 0; - s->reg_OSCR = 0; - - sysbus_init_irq(sbd, &s->irq); - - s->ptimer = ptimer_init(puv3_ost_tick, s, PTIMER_POLICY_DEFAULT); - ptimer_transaction_begin(s->ptimer); - ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); - ptimer_transaction_commit(s->ptimer); - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost", - PUV3_REGS_OFFSET); - sysbus_init_mmio(sbd, &s->iomem); -} - -static void puv3_ost_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = puv3_ost_realize; -} - -static const TypeInfo puv3_ost_info = { - .name = TYPE_PUV3_OST, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3OSTState), - .class_init = puv3_ost_class_init, -}; - -static void puv3_ost_register_type(void) -{ - type_register_static(&puv3_ost_info); -} - -type_init(puv3_ost_register_type) diff --git a/hw/timer/trace-events b/hw/timer/trace-events index f8b9db25c2..029fb56280 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -24,23 +24,6 @@ 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" -# lm32_timer.c -lm32_timer_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -lm32_timer_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -lm32_timer_hit(void) "timer hit" -lm32_timer_irq_state(int level) "irq state %d" - -# milkymist-sysctl.c -milkymist_sysctl_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_sysctl_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -milkymist_sysctl_icap_write(uint32_t value) "value 0x%08x" -milkymist_sysctl_start_timer0(void) "Start timer0" -milkymist_sysctl_stop_timer0(void) "Stop timer0" -milkymist_sysctl_start_timer1(void) "Start timer1" -milkymist_sysctl_stop_timer1(void) "Stop timer1" -milkymist_sysctl_pulse_irq_timer0(void) "Pulse IRQ Timer0" -milkymist_sysctl_pulse_irq_timer1(void) "Pulse IRQ Timer1" - # aspeed_timer.c aspeed_timer_ctrl_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d" aspeed_timer_ctrl_external_clock(uint8_t i, bool enable) "Timer %" PRIu8 ": %d" diff --git a/hw/unicore32/Kconfig b/hw/unicore32/Kconfig deleted file mode 100644 index 4443a29dd2..0000000000 --- a/hw/unicore32/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -config PUV3 - bool - select ISA_BUS - select PCKBD - select PTIMER diff --git a/hw/unicore32/meson.build b/hw/unicore32/meson.build deleted file mode 100644 index fc26d6bcab..0000000000 --- a/hw/unicore32/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index eacacb4249..0000000000 --- a/hw/unicore32/puv3.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Generic PKUnity SoC machine and board descriptor - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "cpu.h" -#include "ui/console.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "sysemu/qtest.h" -#include "hw/unicore32/puv3.h" -#include "hw/input/i8042.h" -#include "hw/irq.h" - -#define KERNEL_LOAD_ADDR 0x03000000 -#define KERNEL_MAX_SIZE 0x00800000 /* Just a guess */ - -/* PKUnity System bus (AHB): 0xc0000000 - 0xedffffff (640MB) */ -#define PUV3_DMA_BASE (0xc0200000) /* AHB-4 */ - -/* PKUnity Peripheral bus (APB): 0xee000000 - 0xefffffff (128MB) */ -#define PUV3_GPIO_BASE (0xee500000) /* APB-5 */ -#define PUV3_INTC_BASE (0xee600000) /* APB-6 */ -#define PUV3_OST_BASE (0xee800000) /* APB-8 */ -#define PUV3_PM_BASE (0xeea00000) /* APB-10 */ -#define PUV3_PS2_BASE (0xeeb00000) /* APB-11 */ - -static void puv3_intc_cpu_handler(void *opaque, int irq, int level) -{ - UniCore32CPU *cpu = opaque; - CPUState *cs = CPU(cpu); - - assert(irq == 0); - if (level) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } -} - -static void puv3_soc_init(CPUUniCore32State *env) -{ - qemu_irq cpu_intc, irqs[PUV3_IRQS_NR]; - DeviceState *dev; - MemoryRegion *i8042 = g_new(MemoryRegion, 1); - int i; - - /* Initialize interrupt controller */ - cpu_intc = qemu_allocate_irq(puv3_intc_cpu_handler, - env_archcpu(env), 0); - dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, cpu_intc); - for (i = 0; i < PUV3_IRQS_NR; i++) { - irqs[i] = qdev_get_gpio_in(dev, i); - } - - /* Initialize minimal necessary devices for kernel booting */ - sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL); - sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL); - sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]); - sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE, - irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1], - irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3], - irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5], - irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7], - irqs[PUV3_IRQS_GPIOHIGH], NULL); - - /* Keyboard (i8042), mouse disabled for nographic */ - i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4); - memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042); -} - -static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size) -{ - MemoryRegion *ram_memory = g_new(MemoryRegion, 1); - - /* SDRAM at address zero. */ - memory_region_init_ram(ram_memory, NULL, "puv3.ram", ram_size, - &error_fatal); - memory_region_add_subregion(get_system_memory(), 0, ram_memory); -} - -static const GraphicHwOps no_ops; - -static void puv3_load_kernel(const char *kernel_filename) -{ - int size; - - if (kernel_filename == NULL && qtest_enabled()) { - return; - } - if (kernel_filename == NULL) { - error_report("kernel parameter cannot be empty"); - exit(1); - } - - /* only zImage format supported */ - size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR, - KERNEL_MAX_SIZE); - if (size < 0) { - error_report("Load kernel error: '%s'", kernel_filename); - exit(1); - } - - /* cheat curses that we have a graphic console, only under ocd console */ - graphic_console_init(NULL, 0, &no_ops, NULL); -} - -static void puv3_init(MachineState *machine) -{ - ram_addr_t ram_size = machine->ram_size; - const char *kernel_filename = machine->kernel_filename; - const char *initrd_filename = machine->initrd_filename; - CPUUniCore32State *env; - UniCore32CPU *cpu; - - if (initrd_filename) { - error_report("Please use kernel built-in initramdisk"); - exit(1); - } - - cpu = UNICORE32_CPU(cpu_create(machine->cpu_type)); - env = &cpu->env; - - puv3_soc_init(env); - puv3_board_init(env, ram_size); - puv3_load_kernel(kernel_filename); -} - -static void puv3_machine_init(MachineClass *mc) -{ - mc->desc = "PKUnity Version-3 based on UniCore32"; - mc->init = puv3_init; - mc->is_default = true; - mc->default_cpu_type = UNICORE32_CPU_TYPE_NAME("UniCore-II"); -} - -DEFINE_MACHINE("puv3", puv3_machine_init) diff --git a/hw/usb/quirks-ftdi-ids.h b/hw/usb/quirks-ftdi-ids.h index 57c12ef662..01aca55ca7 100644 --- a/hw/usb/quirks-ftdi-ids.h +++ b/hw/usb/quirks-ftdi-ids.h @@ -1222,12 +1222,6 @@ #define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D /* - * Milkymist One JTAG/Serial - */ -#define QIHARDWARE_VID 0x20B7 -#define MILKYMISTONE_JTAGSERIAL_PID 0x0713 - -/* * CTI GmbH RS485 Converter http://www.cti-lean.com/ */ /* USB-485-Mini*/ diff --git a/hw/usb/quirks.h b/hw/usb/quirks.h index 50ef2f9c2e..c3e595f40b 100644 --- a/hw/usb/quirks.h +++ b/hw/usb/quirks.h @@ -904,7 +904,6 @@ static const struct usb_device_id usbredir_ftdi_serial_ids[] = { { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) }, { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, - { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID) }, { USB_DEVICE(ST_VID, ST_STMCLT1030_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID) }, diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 01d2101d09..8f2fb9f10b 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -371,8 +371,8 @@ static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) return 0; } -int vhost_vdpa_get_device_id(struct vhost_dev *dev, - uint32_t *device_id) +static 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); diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index d120bf8f43..4b5d9e5e50 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -663,9 +663,6 @@ virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data) } switch (pnd->reason) { - case PRECOPY_NOTIFY_SETUP: - precopy_enable_free_page_optimization(); - break; case PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC: virtio_balloon_free_page_stop(dev); break; @@ -685,6 +682,7 @@ virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data) */ virtio_balloon_free_page_done(dev); break; + case PRECOPY_NOTIFY_SETUP: case PRECOPY_NOTIFY_COMPLETE: break; default: diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 655824ff81..75aa7d6f1b 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -902,9 +902,6 @@ static int virtio_mem_precopy_notify(NotifierWithReturn *n, void *data) 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; diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 342c918ea7..5952471b38 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -36,7 +36,9 @@ static bool virtio_mmio_ioeventfd_enabled(DeviceState *d) { - return kvm_eventfds_enabled(); + VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); + + return (proxy->flags & VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD) != 0; } static int virtio_mmio_ioeventfd_assign(DeviceState *d, @@ -720,6 +722,8 @@ static Property virtio_mmio_properties[] = { DEFINE_PROP_BOOL("format_transport_address", VirtIOMMIOProxy, format_transport_address, true), DEFINE_PROP_BOOL("force-legacy", VirtIOMMIOProxy, legacy, true), + DEFINE_PROP_BIT("ioeventfd", VirtIOMMIOProxy, flags, + VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_END_OF_LIST(), }; @@ -731,6 +735,11 @@ static void virtio_mmio_realizefn(DeviceState *d, Error **errp) qbus_create_inplace(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS, d, NULL); sysbus_init_irq(sbd, &proxy->irq); + + if (!kvm_eventfds_enabled()) { + proxy->flags &= ~VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD; + } + if (proxy->legacy) { memory_region_init_io(&proxy->iomem, OBJECT(d), &virtio_legacy_mem_ops, proxy, diff --git a/include/block/block_int.h b/include/block/block_int.h index c823f5b1b3..b2c8b09d0f 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -357,7 +357,7 @@ struct BlockDriver { * of in-flight requests, so don't waste the time if possible. * * One example usage is to avoid waiting for an nbd target node reconnect - * timeout during job-cancel. + * timeout during job-cancel with force=true. */ void (*bdrv_cancel_in_flight)(BlockDriverState *bs); @@ -954,12 +954,8 @@ struct BlockDriverState { */ int64_t total_sectors; - /* Callback before write request is processed */ - NotifierWithReturnList before_write_notifiers; - /* threshold limit for writes, in bytes. "High water mark". */ uint64_t write_threshold_offset; - NotifierWithReturn write_threshold_notifier; /* Writing to the list requires the BQL _and_ the dirty_bitmap_mutex. * Reading from the list can be done with either the BQL or the @@ -1085,15 +1081,6 @@ bool bdrv_backing_overridden(BlockDriverState *bs); /** - * bdrv_add_before_write_notifier: - * - * Register a callback that is invoked before write requests are processed but - * after any throttling or waiting for overlapping requests. - */ -void bdrv_add_before_write_notifier(BlockDriverState *bs, - NotifierWithReturn *notifier); - -/** * bdrv_add_aio_context_notifier: * * If a long-running job intends to be always run in the same AioContext as a diff --git a/include/block/write-threshold.h b/include/block/write-threshold.h index c646f267a4..f50f923e7e 100644 --- a/include/block/write-threshold.h +++ b/include/block/write-threshold.h @@ -13,7 +13,7 @@ #ifndef BLOCK_WRITE_THRESHOLD_H #define BLOCK_WRITE_THRESHOLD_H -#include "block/block_int.h" +#include "qemu/typedefs.h" /* * bdrv_write_threshold_set: @@ -36,27 +36,12 @@ void bdrv_write_threshold_set(BlockDriverState *bs, uint64_t threshold_bytes); uint64_t bdrv_write_threshold_get(const BlockDriverState *bs); /* - * bdrv_write_threshold_is_set + * bdrv_write_threshold_check_write * - * Tell if a write threshold is set for a given BDS. + * Check whether the specified request exceeds the write threshold. + * If so, send a corresponding event and disable write threshold checking. */ -bool bdrv_write_threshold_is_set(const BlockDriverState *bs); - -/* - * bdrv_write_threshold_exceeded - * - * Return the extent of a write request that exceeded the threshold, - * or zero if the request is below the threshold. - * Return zero also if the threshold was not set. - * - * NOTE: here we assume the following holds for each request this code - * deals with: - * - * assert((req->offset + req->bytes) <= UINT64_MAX) - * - * Please not there is *not* an actual C assert(). - */ -uint64_t bdrv_write_threshold_exceeded(const BlockDriverState *bs, - const BdrvTrackedRequest *req); +void bdrv_write_threshold_check_write(BlockDriverState *bs, int64_t offset, + int64_t bytes); #endif diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index 4701445e80..524f29196d 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -249,8 +249,6 @@ enum bfd_architecture #define bfd_mach_nios2 0 #define bfd_mach_nios2r1 1 #define bfd_mach_nios2r2 2 - bfd_arch_lm32, /* Lattice Mico32 */ -#define bfd_mach_lm32 1 bfd_arch_rx, /* Renesas RX */ #define bfd_mach_rx 0x75 #define bfd_mach_rx_v2 0x76 @@ -443,7 +441,6 @@ int print_insn_m32r (bfd_vma, disassemble_info*); int print_insn_m88k (bfd_vma, disassemble_info*); int print_insn_mn10200 (bfd_vma, disassemble_info*); int print_insn_mn10300 (bfd_vma, disassemble_info*); -int print_insn_moxie (bfd_vma, disassemble_info*); int print_insn_ns32k (bfd_vma, disassemble_info*); int print_insn_big_powerpc (bfd_vma, disassemble_info*); int print_insn_little_powerpc (bfd_vma, disassemble_info*); @@ -458,7 +455,6 @@ int print_insn_crisv32 (bfd_vma, disassemble_info*); int print_insn_crisv10 (bfd_vma, disassemble_info*); int print_insn_microblaze (bfd_vma, disassemble_info*); int print_insn_ia64 (bfd_vma, disassemble_info*); -int print_insn_lm32 (bfd_vma, disassemble_info*); int print_insn_big_nios2 (bfd_vma, disassemble_info*); int print_insn_little_nios2 (bfd_vma, disassemble_info*); int print_insn_xtensa (bfd_vma, disassemble_info*); diff --git a/include/elf.h b/include/elf.h index 78237c9a87..033bcc9576 100644 --- a/include/elf.h +++ b/include/elf.h @@ -174,9 +174,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_OPENRISC 92 /* OpenCores OpenRISC */ -#define EM_UNICORE32 110 /* UniCore32 */ - #define EM_HEXAGON 164 /* Qualcomm Hexagon */ + #define EM_RX 173 /* Renesas RX family */ #define EM_RISCV 243 /* RISC-V */ @@ -206,9 +205,6 @@ typedef struct mips_elf_abiflags_v0 { #define EM_AARCH64 183 -#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 */ diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 5a0a2d93e0..ccabed4003 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -57,6 +57,7 @@ const char *qemu_ram_get_idstr(RAMBlock *rb); void *qemu_ram_get_host_addr(RAMBlock *rb); ram_addr_t qemu_ram_get_offset(RAMBlock *rb); ram_addr_t qemu_ram_get_used_length(RAMBlock *rb); +ram_addr_t qemu_ram_get_max_length(RAMBlock *rb); bool qemu_ram_is_shared(RAMBlock *rb); bool qemu_ram_is_uf_zeroable(RAMBlock *rb); void qemu_ram_set_uf_zeroable(RAMBlock *rb); diff --git a/include/exec/memory.h b/include/exec/memory.h index 5728a681b2..c8b9088924 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -131,7 +131,7 @@ typedef struct IOMMUTLBEvent { #define RAM_SHARED (1 << 1) /* Only a portion of RAM (used_length) is actually used, and migrated. - * This used_length size can change across reboots. + * Resizing RAM while migrating can result in the migration being canceled. */ #define RAM_RESIZEABLE (1 << 2) @@ -955,7 +955,9 @@ void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr, * RAM. Accesses into the region will * modify memory directly. Only an initial * portion of this RAM is actually used. - * The used size can change across reboots. + * Changing the size while migrating + * can result in the migration being + * canceled. * * @mr: the #MemoryRegion to be initialized. * @owner: the object that tracks the region's reference count @@ -1586,8 +1588,8 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr); /* memory_region_ram_resize: Resize a RAM region. * - * Only legal before guest might have detected the memory size: e.g. on - * incoming migration, or right after reset. + * Resizing RAM while migrating can result in the migration being canceled. + * Care has to be taken if the guest might have already detected the memory. * * @mr: a memory region created with @memory_region_init_resizeable_ram. * @newsize: the new size the region diff --git a/include/exec/poison.h b/include/exec/poison.h index 4cd3f8abb4..7ad4ad18e8 100644 --- a/include/exec/poison.h +++ b/include/exec/poison.h @@ -4,6 +4,8 @@ #ifndef HW_POISON_H #define HW_POISON_H +#include "config-poison.h" + #pragma GCC poison TARGET_I386 #pragma GCC poison TARGET_X86_64 #pragma GCC poison TARGET_AARCH64 @@ -12,7 +14,6 @@ #pragma GCC poison TARGET_CRIS #pragma GCC poison TARGET_HEXAGON #pragma GCC poison TARGET_HPPA -#pragma GCC poison TARGET_LM32 #pragma GCC poison TARGET_M68K #pragma GCC poison TARGET_MICROBLAZE #pragma GCC poison TARGET_MIPS @@ -20,7 +21,6 @@ #pragma GCC poison TARGET_ABI_MIPSO32 #pragma GCC poison TARGET_MIPS64 #pragma GCC poison TARGET_ABI_MIPSN64 -#pragma GCC poison TARGET_MOXIE #pragma GCC poison TARGET_NIOS2 #pragma GCC poison TARGET_OPENRISC #pragma GCC poison TARGET_PPC @@ -32,7 +32,6 @@ #pragma GCC poison TARGET_SPARC #pragma GCC poison TARGET_SPARC64 #pragma GCC poison TARGET_TRICORE -#pragma GCC poison TARGET_UNICORE32 #pragma GCC poison TARGET_XTENSA #pragma GCC poison TARGET_ALIGNED_ONLY @@ -74,12 +73,10 @@ #pragma GCC poison CONFIG_HPPA_DIS #pragma GCC poison CONFIG_I386_DIS #pragma GCC poison CONFIG_HEXAGON_DIS -#pragma GCC poison CONFIG_LM32_DIS #pragma GCC poison CONFIG_M68K_DIS #pragma GCC poison CONFIG_MICROBLAZE_DIS #pragma GCC poison CONFIG_MIPS_DIS #pragma GCC poison CONFIG_NANOMIPS_DIS -#pragma GCC poison CONFIG_MOXIE_DIS #pragma GCC poison CONFIG_NIOS2_DIS #pragma GCC poison CONFIG_PPC_DIS #pragma GCC poison CONFIG_RISCV_DIS @@ -88,8 +85,12 @@ #pragma GCC poison CONFIG_SPARC_DIS #pragma GCC poison CONFIG_XTENSA_DIS +#pragma GCC poison CONFIG_HAX +#pragma GCC poison CONFIG_HVF #pragma GCC poison CONFIG_LINUX_USER #pragma GCC poison CONFIG_KVM #pragma GCC poison CONFIG_SOFTMMU +#pragma GCC poison CONFIG_WHPX +#pragma GCC poison CONFIG_XEN #endif diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h index 07d50864d8..664701b759 100644 --- a/include/exec/ramblock.h +++ b/include/exec/ramblock.h @@ -59,6 +59,16 @@ struct RAMBlock { */ unsigned long *clear_bmap; uint8_t clear_bmap_shift; + + /* + * RAM block length that corresponds to the used_length on the migration + * source (after RAM block sizes were synchronized). Especially, after + * starting to run the guest, used_length and postcopy_length can differ. + * Used to register/unregister uffd handlers and as the size of the received + * bitmap. Receiving any page beyond this length will bail out, as it + * could not have been valid on the source. + */ + ram_addr_t postcopy_length; }; #endif #endif diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h index 26704aa3b0..ece6497ee2 100644 --- a/include/exec/ramlist.h +++ b/include/exec/ramlist.h @@ -65,15 +65,20 @@ void qemu_mutex_lock_ramlist(void); void qemu_mutex_unlock_ramlist(void); struct RAMBlockNotifier { - void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size); - void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size); + void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size, + size_t max_size); + void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size, + size_t max_size); + void (*ram_block_resized)(RAMBlockNotifier *n, void *host, size_t old_size, + size_t new_size); QLIST_ENTRY(RAMBlockNotifier) next; }; void ram_block_notifier_add(RAMBlockNotifier *n); void ram_block_notifier_remove(RAMBlockNotifier *n); -void ram_block_notify_add(void *host, size_t size); -void ram_block_notify_remove(void *host, size_t size); +void ram_block_notify_add(void *host, size_t size, size_t max_size); +void ram_block_notify_remove(void *host, size_t size, size_t max_size); +void ram_block_notify_resize(void *host, size_t old_size, size_t new_size); void ram_block_dump(Monitor *mon); diff --git a/include/hw/char/lm32_juart.h b/include/hw/char/lm32_juart.h deleted file mode 100644 index 6fce278326..0000000000 --- a/include/hw/char/lm32_juart.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef QEMU_HW_CHAR_LM32_JUART_H -#define QEMU_HW_CHAR_LM32_JUART_H - -#include "hw/qdev-core.h" - -#define TYPE_LM32_JUART "lm32-juart" - -uint32_t lm32_juart_get_jtx(DeviceState *d); -uint32_t lm32_juart_get_jrx(DeviceState *d); -void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx); -void lm32_juart_set_jrx(DeviceState *d, uint32_t jrx); - -#endif /* QEMU_HW_CHAR_LM32_JUART_H */ diff --git a/include/hw/display/milkymist_tmu2.h b/include/hw/display/milkymist_tmu2.h deleted file mode 100644 index fdce9535a1..0000000000 --- a/include/hw/display/milkymist_tmu2.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * QEMU model of the Milkymist texture mapping unit. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * Copyright (c) 2010 Sebastien Bourdeauducq - * <sebastien.bourdeauducq@lekernel.net> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - * - * - * Specification available at: - * http://milkymist.walle.cc/socdoc/tmu2.pdf - * - */ - -#ifndef HW_DISPLAY_MILKYMIST_TMU2_H -#define HW_DISPLAY_MILKYMIST_TMU2_H - -#include "exec/hwaddr.h" -#include "hw/qdev-core.h" - -#if defined(CONFIG_X11) && defined(CONFIG_OPENGL) -DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq); -#else -static inline DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq) -{ - return NULL; -} -#endif - -#endif /* HW_DISPLAY_MILKYMIST_TMU2_H */ diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index 6ee458e7bc..1c37cec4ae 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -368,14 +368,6 @@ static int glue(load_elf, SZ)(const char *name, int fd, } } break; - case EM_MOXIE: - if (ehdr.e_machine != EM_MOXIE) { - if (ehdr.e_machine != EM_MOXIE_OLD) { - ret = ELF_LOAD_WRONG_ARCH; - goto fail; - } - } - break; case EM_MIPS: case EM_NANOMIPS: if ((ehdr.e_machine != EM_MIPS) && diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h index 02a0ced0a0..5a0dd0c8cf 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -258,6 +258,17 @@ struct smbios_type_32 { uint8_t boot_status; } QEMU_PACKED; +/* SMBIOS type 41 - Onboard Devices Extended Information */ +struct smbios_type_41 { + struct smbios_structure_header header; + uint8_t reference_designation_str; + uint8_t device_type; + uint8_t device_type_instance; + uint16_t segment_group_number; + uint8_t bus_number; + uint8_t device_number; +} QEMU_PACKED; + /* SMBIOS type 127 -- End-of-table */ struct smbios_type_127 { struct smbios_structure_header header; @@ -273,5 +284,6 @@ void smbios_get_tables(MachineState *ms, const struct smbios_phys_mem_area *mem_array, const unsigned int mem_array_size, uint8_t **tables, size_t *tables_len, - uint8_t **anchor, size_t *anchor_len); + uint8_t **anchor, size_t *anchor_len, + Error **errp); #endif /* QEMU_SMBIOS_H */ diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h index 277dd9f2d6..ff4129ea70 100644 --- a/include/hw/i2c/i2c.h +++ b/include/hw/i2c/i2c.h @@ -16,6 +16,7 @@ enum i2c_event { I2C_NACK /* Masker NACKed a receive byte. */ }; +typedef struct I2CNodeList I2CNodeList; #define TYPE_I2C_SLAVE "i2c-slave" OBJECT_DECLARE_TYPE(I2CSlave, I2CSlaveClass, @@ -39,6 +40,16 @@ struct I2CSlaveClass { * return code is not used and should be zero. */ int (*event)(I2CSlave *s, enum i2c_event event); + + /* + * Check if this device matches the address provided. Returns bool of + * true if it matches (or broadcast), and updates the device list, false + * otherwise. + * + * If broadcast is true, match should add the device and return true. + */ + bool (*match_and_add)(I2CSlave *candidate, uint8_t address, bool broadcast, + I2CNodeList *current_devs); }; struct I2CSlave { @@ -58,9 +69,11 @@ struct I2CNode { QLIST_ENTRY(I2CNode) next; }; +typedef QLIST_HEAD(I2CNodeList, I2CNode) I2CNodeList; + struct I2CBus { BusState qbus; - QLIST_HEAD(, I2CNode) current_devs; + I2CNodeList current_devs; uint8_t saved_address; bool broadcast; }; @@ -74,6 +87,8 @@ void i2c_nack(I2CBus *bus); 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); +bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast, + I2CNodeList *current_devs); /** * Create an I2C slave device on the heap. diff --git a/include/hw/i2c/i2c_mux_pca954x.h b/include/hw/i2c/i2c_mux_pca954x.h new file mode 100644 index 0000000000..8aaf9bbc39 --- /dev/null +++ b/include/hw/i2c/i2c_mux_pca954x.h @@ -0,0 +1,19 @@ +#ifndef QEMU_I2C_MUX_PCA954X +#define QEMU_I2C_MUX_PCA954X + +#include "hw/i2c/i2c.h" + +#define TYPE_PCA9546 "pca9546" +#define TYPE_PCA9548 "pca9548" + +/** + * Retrieves the i2c bus associated with the specified channel on this i2c + * mux. + * @mux: an i2c mux device. + * @channel: the i2c channel requested + * + * Returns: a pointer to the associated i2c bus. + */ +I2CBus *pca954x_i2c_get_bus(I2CSlave *mux, uint8_t channel); + +#endif diff --git a/include/hw/lm32/lm32_pic.h b/include/hw/lm32/lm32_pic.h deleted file mode 100644 index 9e5e038437..0000000000 --- a/include/hw/lm32/lm32_pic.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef QEMU_HW_LM32_PIC_H -#define QEMU_HW_LM32_PIC_H - - -uint32_t lm32_pic_get_ip(DeviceState *d); -uint32_t lm32_pic_get_im(DeviceState *d); -void lm32_pic_set_ip(DeviceState *d, uint32_t ip); -void lm32_pic_set_im(DeviceState *d, uint32_t im); - -#endif /* QEMU_HW_LM32_PIC_H */ diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index 3d3db82641..1473e6db62 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -56,9 +56,6 @@ struct PCDIMMDevice { * PCDIMMDeviceClass: * @realize: called after common dimm is realized so that the dimm based * devices get the chance to do specified operations. - * @get_vmstate_memory_region: returns #MemoryRegion which indicates the - * memory of @dimm should be kept during live migration. Will not fail - * after the device was realized. */ struct PCDIMMDeviceClass { /* private */ @@ -66,8 +63,6 @@ struct PCDIMMDeviceClass { /* public */ void (*realize)(PCDIMMDevice *dimm, Error **errp); - MemoryRegion *(*get_vmstate_memory_region)(PCDIMMDevice *dimm, - Error **errp); }; void pc_dimm_pre_plug(PCDIMMDevice *dimm, MachineState *machine, diff --git a/include/hw/unicore32/puv3.h b/include/hw/unicore32/puv3.h deleted file mode 100644 index f587a1f622..0000000000 --- a/include/hw/unicore32/puv3.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Misc PKUnity SoC declarations - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ - -#ifndef QEMU_HW_PUV3_H -#define QEMU_HW_PUV3_H - -#define PUV3_REGS_OFFSET (0x1000) /* 4K is reasonable */ - -/* Hardware interrupts */ -#define PUV3_IRQS_NR (32) - -#define PUV3_IRQS_GPIOLOW0 (0) -#define PUV3_IRQS_GPIOLOW1 (1) -#define PUV3_IRQS_GPIOLOW2 (2) -#define PUV3_IRQS_GPIOLOW3 (3) -#define PUV3_IRQS_GPIOLOW4 (4) -#define PUV3_IRQS_GPIOLOW5 (5) -#define PUV3_IRQS_GPIOLOW6 (6) -#define PUV3_IRQS_GPIOLOW7 (7) -#define PUV3_IRQS_GPIOHIGH (8) -#define PUV3_IRQS_PS2_KBD (22) -#define PUV3_IRQS_PS2_AUX (23) -#define PUV3_IRQS_OST0 (26) - -/* All puv3_*.c use DPRINTF for debug. */ -#ifdef DEBUG_PUV3 -#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif - -#endif /* QEMU_HW_PUV3_H */ diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h index 9b81a409da..28ca65018e 100644 --- a/include/hw/virtio/vhost-vdpa.h +++ b/include/hw/virtio/vhost-vdpa.h @@ -22,6 +22,4 @@ typedef struct vhost_vdpa { } 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/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h index d4c4c386ab..090f7730e7 100644 --- a/include/hw/virtio/virtio-mmio.h +++ b/include/hw/virtio/virtio-mmio.h @@ -49,12 +49,17 @@ typedef struct VirtIOMMIOQueue { uint32_t used[2]; } VirtIOMMIOQueue; +#define VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT 1 +#define VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD \ + (1 << VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT) + struct VirtIOMMIOProxy { /* Generic */ SysBusDevice parent_obj; MemoryRegion iomem; qemu_irq irq; bool legacy; + uint32_t flags; /* Guest accessible state needing migration and reset */ uint32_t host_features_sel; uint32_t guest_features_sel; diff --git a/include/migration/misc.h b/include/migration/misc.h index 738675ef52..465906710d 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -37,7 +37,6 @@ void precopy_infrastructure_init(void); void precopy_add_notifier(NotifierWithReturn *n); void precopy_remove_notifier(NotifierWithReturn *n); int precopy_notify(PrecopyNotifyReason reason, Error **errp); -void precopy_enable_free_page_optimization(void); void ram_mig_init(void); void qemu_guest_free_page_hint(void *addr, size_t len); diff --git a/include/qemu/job.h b/include/qemu/job.h index efc6fa7544..41162ed494 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -254,7 +254,7 @@ struct JobDriver { /** * If the callback is not NULL, it will be invoked in job_cancel_async */ - void (*cancel)(Job *job); + void (*cancel)(Job *job, bool force); /** Called when the job is freed */ diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 16da279696..e723c467eb 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -9,7 +9,6 @@ enum { QEMU_ARCH_CRIS = (1 << 2), QEMU_ARCH_I386 = (1 << 3), QEMU_ARCH_M68K = (1 << 4), - QEMU_ARCH_LM32 = (1 << 5), QEMU_ARCH_MICROBLAZE = (1 << 6), QEMU_ARCH_MIPS = (1 << 7), QEMU_ARCH_PPC = (1 << 8), @@ -18,8 +17,6 @@ enum { QEMU_ARCH_SPARC = (1 << 11), QEMU_ARCH_XTENSA = (1 << 12), QEMU_ARCH_OPENRISC = (1 << 13), - QEMU_ARCH_UNICORE32 = (1 << 14), - QEMU_ARCH_MOXIE = (1 << 15), QEMU_ARCH_TRICORE = (1 << 16), QEMU_ARCH_NIOS2 = (1 << 17), QEMU_ARCH_HPPA = (1 << 18), diff --git a/include/sysemu/hax.h b/include/sysemu/hax.h index 12fb54f990..247f0661d1 100644 --- a/include/sysemu/hax.h +++ b/include/sysemu/hax.h @@ -24,6 +24,8 @@ int hax_sync_vcpus(void); +#ifdef NEED_CPU_H + #ifdef CONFIG_HAX int hax_enabled(void); @@ -34,4 +36,6 @@ int hax_enabled(void); #endif /* CONFIG_HAX */ +#endif /* NEED_CPU_H */ + #endif /* QEMU_HAX_H */ diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index c98636bc81..bb70082e45 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -16,6 +16,8 @@ #include "qemu/accel.h" #include "qom/object.h" +#ifdef NEED_CPU_H + #ifdef CONFIG_HVF uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, int reg); @@ -26,6 +28,8 @@ extern bool hvf_allowed; #define hvf_get_supported_cpuid(func, idx, reg) 0 #endif /* !CONFIG_HVF */ +#endif /* NEED_CPU_H */ + #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf") typedef struct HVFState HVFState; diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h index 8ca1c1c4ac..2889fa2278 100644 --- a/include/sysemu/whpx.h +++ b/include/sysemu/whpx.h @@ -13,6 +13,8 @@ #ifndef QEMU_WHPX_H #define QEMU_WHPX_H +#ifdef NEED_CPU_H + #ifdef CONFIG_WHPX int whpx_enabled(void); @@ -25,4 +27,6 @@ bool whpx_apic_in_platform(void); #endif /* CONFIG_WHPX */ +#endif /* NEED_CPU_H */ + #endif /* QEMU_WHPX_H */ @@ -716,7 +716,7 @@ static int job_finalize_single(Job *job) static void job_cancel_async(Job *job, bool force) { if (job->driver->cancel) { - job->driver->cancel(job); + job->driver->cancel(job, force); } if (job->user_paused) { /* Do not call job_enter here, the caller will handle it. */ diff --git a/meson.build b/meson.build index 0b41ff4118..8e16e05c2a 100644 --- a/meson.build +++ b/meson.build @@ -847,7 +847,7 @@ if 'CONFIG_VTE' in config_host link_args: config_host['VTE_LIBS'].split()) endif x11 = not_found -if gtkx11.found() or 'lm32-softmmu' in target_dirs +if gtkx11.found() x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(), kwargs: static_kwargs) endif @@ -1210,11 +1210,9 @@ disassemblers = { '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'], @@ -2635,7 +2633,6 @@ if have_block 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 += {'FUSE exports': fuse.found()} endif summary(summary_info, bool_yn: true, section: 'Block layer support') diff --git a/migration/meson.build b/migration/meson.build index 3ecedce94d..f8714dcb15 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -31,4 +31,5 @@ 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: zstd, if_true: files('multifd-zstd.c')) -specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files('dirtyrate.c', 'ram.c')) +specific_ss.add(when: 'CONFIG_SOFTMMU', + if_true: files('dirtyrate.c', 'ram.c', 'target.c')) diff --git a/migration/migration.c b/migration/migration.c index 8ca034136b..1885860d7b 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -60,10 +60,6 @@ #include "qemu/yank.h" #include "sysemu/cpus.h" -#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 @@ -223,13 +219,18 @@ void migration_object_init(void) dirty_bitmap_mig_init(); } +void migration_cancel(void) +{ + migrate_fd_cancel(current_migration); +} + void migration_shutdown(void) { /* * Cancel the current migration - that will (eventually) * stop the migration using this structure */ - migrate_fd_cancel(current_migration); + migration_cancel(); object_unref(OBJECT(current_migration)); /* @@ -1059,41 +1060,27 @@ 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(); + GSList *cur_blocker = migration_blockers; - info->blocked = migration_is_blocked(NULL); - info->has_blocked_reasons = info->blocked; info->blocked_reasons = NULL; - if (info->blocked) { - GSList *cur_blocker = migration_blockers; - /* - * There are two types of reasons a migration might be blocked; - * a) devices marked in VMState as non-migratable, and - * b) Explicit migration blockers - * We need to add both of them here. - */ - qemu_savevm_non_migratable_list(&info->blocked_reasons); + /* + * There are two types of reasons a migration might be blocked; + * a) devices marked in VMState as non-migratable, and + * b) Explicit migration blockers + * We need to add both of them here. + */ + qemu_savevm_non_migratable_list(&info->blocked_reasons); - while (cur_blocker) { - QAPI_LIST_PREPEND(info->blocked_reasons, - g_strdup(error_get_pretty(cur_blocker->data))); - cur_blocker = g_slist_next(cur_blocker); - } + while (cur_blocker) { + QAPI_LIST_PREPEND(info->blocked_reasons, + g_strdup(error_get_pretty(cur_blocker->data))); + cur_blocker = g_slist_next(cur_blocker); } + info->has_blocked_reasons = info->blocked_reasons != NULL; switch (s->state) { case MIGRATION_STATUS_NONE: @@ -2310,7 +2297,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, void qmp_migrate_cancel(Error **errp) { - migrate_fd_cancel(migrate_get_current()); + migration_cancel(); } void qmp_migrate_continue(MigrationStatus state, Error **errp) diff --git a/migration/migration.h b/migration/migration.h index db6708326b..b88bd8fe07 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -375,5 +375,8 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); void migration_make_urgent_request(void); void migration_consume_urgent_request(void); bool migration_rate_limit(void); +void migration_cancel(void); + +void populate_vfio_info(MigrationInfo *info); #endif diff --git a/migration/multifd.c b/migration/multifd.c index a6677c45c8..0a4803cfcc 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -361,7 +361,7 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp) if (offset > (block->used_length - qemu_target_page_size())) { error_setg(errp, "multifd: offset too long %" PRIu64 " (max " RAM_ADDR_FMT ")", - offset, block->max_length); + offset, block->used_length); return -1; } p->pages->iov[i].iov_base = block->host + offset; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index ab482adef1..2e9697bdd2 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -17,6 +17,7 @@ */ #include "qemu/osdep.h" +#include "qemu/rcu.h" #include "exec/target_page.h" #include "migration.h" #include "qemu-file.h" @@ -30,6 +31,7 @@ #include "qemu/error-report.h" #include "trace.h" #include "hw/boards.h" +#include "exec/ramblock.h" /* Arbitrary limit on size of each discard command, * keeps them around ~200 bytes @@ -453,6 +455,13 @@ static int init_range(RAMBlock *rb, void *opaque) trace_postcopy_init_range(block_name, host_addr, offset, length); /* + * Save the used_length before running the guest. In case we have to + * resize RAM blocks when syncing RAM block sizes from the source during + * precopy, we'll update it manually via the ram block notifier. + */ + rb->postcopy_length = length; + + /* * We need the whole of RAM to be truly empty for postcopy, so things * like ROMs and any data tables built during init must be zero'd * - we're going to get the copy from the source anyway. @@ -474,7 +483,7 @@ static int cleanup_range(RAMBlock *rb, void *opaque) const char *block_name = qemu_ram_get_idstr(rb); void *host_addr = qemu_ram_get_host_addr(rb); ram_addr_t offset = qemu_ram_get_offset(rb); - ram_addr_t length = qemu_ram_get_used_length(rb); + ram_addr_t length = rb->postcopy_length; MigrationIncomingState *mis = opaque; struct uffdio_range range_struct; trace_postcopy_cleanup_range(block_name, host_addr, offset, length); @@ -580,7 +589,7 @@ static int nhp_range(RAMBlock *rb, void *opaque) const char *block_name = qemu_ram_get_idstr(rb); void *host_addr = qemu_ram_get_host_addr(rb); ram_addr_t offset = qemu_ram_get_offset(rb); - ram_addr_t length = qemu_ram_get_used_length(rb); + ram_addr_t length = rb->postcopy_length; trace_postcopy_nhp_range(block_name, host_addr, offset, length); /* @@ -624,7 +633,7 @@ static int ram_block_enable_notify(RAMBlock *rb, void *opaque) struct uffdio_register reg_struct; reg_struct.range.start = (uintptr_t)qemu_ram_get_host_addr(rb); - reg_struct.range.len = qemu_ram_get_used_length(rb); + reg_struct.range.len = rb->postcopy_length; reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING; /* Now tell our userfault_fd that it's responsible for this area */ diff --git a/migration/ram.c b/migration/ram.c index ace8ad431c..60ea913c54 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -240,7 +240,7 @@ int64_t ramblock_recv_bitmap_send(QEMUFile *file, return -1; } - nbits = block->used_length >> TARGET_PAGE_BITS; + nbits = block->postcopy_length >> TARGET_PAGE_BITS; /* * Make sure the tmp bitmap buffer is big enough, e.g., on 32bit @@ -311,10 +311,6 @@ struct RAMState { ram_addr_t last_page; /* last ram version we have seen */ uint32_t last_version; - /* We are in the first round */ - bool ram_bulk_stage; - /* The free page optimization is enabled */ - bool fpo_enabled; /* How many times we have dirty too many pages */ int dirty_rate_high_cnt; /* these variables are used for bitmap sync */ @@ -330,6 +326,8 @@ struct RAMState { uint64_t xbzrle_pages_prev; /* Amount of xbzrle encoded bytes since the beginning of the period */ uint64_t xbzrle_bytes_prev; + /* Start using XBZRLE (e.g., after the first round). */ + bool xbzrle_enabled; /* compression statistics since the beginning of the period */ /* amount of count that no free thread to compress data */ @@ -383,15 +381,6 @@ int precopy_notify(PrecopyNotifyReason reason, Error **errp) return notifier_with_return_list_notify(&precopy_notifier_list, &pnd); } -void precopy_enable_free_page_optimization(void) -{ - if (!ram_state) { - return; - } - - ram_state->fpo_enabled = true; -} - uint64_t ram_bytes_remaining(void) { return ram_state ? (ram_state->migration_dirty_pages * TARGET_PAGE_SIZE) : @@ -664,7 +653,7 @@ static void mig_throttle_guest_down(uint64_t bytes_dirty_period, */ static void xbzrle_cache_zero_page(RAMState *rs, ram_addr_t current_addr) { - if (rs->ram_bulk_stage || !migrate_use_xbzrle()) { + if (!rs->xbzrle_enabled) { return; } @@ -792,23 +781,12 @@ unsigned long migration_bitmap_find_dirty(RAMState *rs, RAMBlock *rb, { unsigned long size = rb->used_length >> TARGET_PAGE_BITS; unsigned long *bitmap = rb->bmap; - unsigned long next; if (ramblock_is_ignored(rb)) { return size; } - /* - * When the free page optimization is enabled, we need to check the bitmap - * to send the non-free pages rather than all the pages in the bulk stage. - */ - if (!rs->fpo_enabled && rs->ram_bulk_stage && start > 0) { - next = start + 1; - } else { - next = find_next_bit(bitmap, size, start); - } - - return next; + return find_next_bit(bitmap, size, start); } static inline bool migration_bitmap_clear_dirty(RAMState *rs, @@ -1185,8 +1163,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage) trace_ram_save_page(block->idstr, (uint64_t)offset, p); XBZRLE_cache_lock(); - if (!rs->ram_bulk_stage && !migration_in_postcopy() && - migrate_use_xbzrle()) { + if (rs->xbzrle_enabled && !migration_in_postcopy()) { pages = save_xbzrle_page(rs, &p, current_addr, block, offset, last_stage); if (!last_stage) { @@ -1365,8 +1342,8 @@ static bool find_dirty_block(RAMState *rs, PageSearchStatus *pss, bool *again) *again = false; return false; } - if ((((ram_addr_t)pss->page) << TARGET_PAGE_BITS) - >= pss->block->used_length) { + if (!offset_in_ramblock(pss->block, + ((ram_addr_t)pss->page) << TARGET_PAGE_BITS)) { /* Didn't find anything in this RAM Block */ pss->page = 0; pss->block = QLIST_NEXT_RCU(pss->block, next); @@ -1386,7 +1363,10 @@ static bool find_dirty_block(RAMState *rs, PageSearchStatus *pss, bool *again) pss->block = QLIST_FIRST_RCU(&ram_list.blocks); /* Flag that we've looped */ pss->complete_round = true; - rs->ram_bulk_stage = false; + /* After the first round, enable XBZRLE. */ + if (migrate_use_xbzrle()) { + rs->xbzrle_enabled = true; + } } /* Didn't find anything this time, but try again on the new block */ *again = true; @@ -1801,14 +1781,6 @@ static bool get_queued_page(RAMState *rs, PageSearchStatus *pss) if (block) { /* - * As soon as we start servicing pages out of order, then we have - * to kill the bulk stage, since the bulk stage assumes - * in (migration_bitmap_find_and_reset_dirty) that every page is - * dirty, that's no longer true. - */ - rs->ram_bulk_stage = false; - - /* * We want the background search to continue from the queued page * since the guest is likely to want other pages near to the page * it just requested. @@ -1891,7 +1863,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 (!offset_in_ramblock(ramblock, start + len - 1)) { error_report("%s request overrun start=" RAM_ADDR_FMT " len=" RAM_ADDR_FMT " blocklen=" RAM_ADDR_FMT, __func__, start, len, ramblock->used_length); @@ -1920,15 +1892,15 @@ static bool save_page_use_compression(RAMState *rs) } /* - * If xbzrle is on, stop using the data compression after first - * round of migration even if compression is enabled. In theory, - * xbzrle can do better than compression. + * If xbzrle is enabled (e.g., after first round of migration), stop + * using the data compression. In theory, xbzrle can do better than + * compression. */ - if (rs->ram_bulk_stage || !migrate_use_xbzrle()) { - return true; + if (rs->xbzrle_enabled) { + return false; } - return false; + return true; } /* @@ -2041,6 +2013,8 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss, int tmppages, pages = 0; size_t pagesize_bits = qemu_ram_pagesize(pss->block) >> TARGET_PAGE_BITS; + unsigned long hostpage_boundary = + QEMU_ALIGN_UP(pss->page + 1, pagesize_bits); unsigned long start_page = pss->page; int res; @@ -2051,25 +2025,27 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss, do { /* Check the pages is dirty and if it is send it */ - if (!migration_bitmap_clear_dirty(rs, pss->block, pss->page)) { - pss->page++; - continue; - } + if (migration_bitmap_clear_dirty(rs, pss->block, pss->page)) { + tmppages = ram_save_target_page(rs, pss, last_stage); + if (tmppages < 0) { + return tmppages; + } - tmppages = ram_save_target_page(rs, pss, last_stage); - if (tmppages < 0) { - return tmppages; + pages += tmppages; + /* + * Allow rate limiting to happen in the middle of huge pages if + * something is sent in the current iteration. + */ + if (pagesize_bits > 1 && tmppages > 0) { + migration_rate_limit(); + } } - - pages += tmppages; - pss->page++; - /* Allow rate limiting to happen in the middle of huge pages */ - migration_rate_limit(); - } while ((pss->page & (pagesize_bits - 1)) && + pss->page = migration_bitmap_find_dirty(rs, pss->block, pss->page); + } while ((pss->page < hostpage_boundary) && offset_in_ramblock(pss->block, ((ram_addr_t)pss->page) << TARGET_PAGE_BITS)); - /* The offset we leave with is the last one we looked at */ - pss->page--; + /* The offset we leave with is the min boundary of host page and block */ + pss->page = MIN(pss->page, hostpage_boundary) - 1; res = ram_save_release_protection(rs, pss, start_page); return (res < 0 ? res : pages); @@ -2235,8 +2211,7 @@ static void ram_state_reset(RAMState *rs) rs->last_sent_block = NULL; rs->last_page = 0; rs->last_version = ram_list.version; - rs->ram_bulk_stage = true; - rs->fpo_enabled = false; + rs->xbzrle_enabled = false; } #define MAX_WAIT 50 /* ms, half buffered_file limit */ @@ -2720,15 +2695,7 @@ static void ram_state_resume_prepare(RAMState *rs, QEMUFile *out) /* This may not be aligned with current bitmaps. Recalculate. */ rs->migration_dirty_pages = pages; - rs->last_seen_block = NULL; - rs->last_sent_block = NULL; - rs->last_page = 0; - rs->last_version = ram_list.version; - /* - * Disable the bulk stage, otherwise we'll resend the whole RAM no - * matter what we have sent. - */ - rs->ram_bulk_stage = false; + ram_state_reset(rs); /* Update RAMState cache of output QEMUFile */ rs->f = out; @@ -3118,6 +3085,20 @@ static inline void *host_from_ram_block_offset(RAMBlock *block, return block->host + offset; } +static void *host_page_from_ram_block_offset(RAMBlock *block, + ram_addr_t offset) +{ + /* Note: Explicitly no check against offset_in_ramblock(). */ + return (void *)QEMU_ALIGN_DOWN((uintptr_t)(block->host + offset), + block->page_size); +} + +static ram_addr_t host_page_offset_from_ram_block_offset(RAMBlock *block, + ram_addr_t offset) +{ + return ((uintptr_t)block->host + offset) & (block->page_size - 1); +} + static inline void *colo_cache_from_block_offset(RAMBlock *block, ram_addr_t offset, bool record_bitmap) { @@ -3345,16 +3326,9 @@ static void decompress_data_with_multi_threads(QEMUFile *f, } } - /* - * 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; } /* @@ -3521,13 +3495,12 @@ static int ram_load_postcopy(QEMUFile *f) MigrationIncomingState *mis = migration_incoming_get_current(); /* Temporary page that is later 'placed' */ void *postcopy_host_page = mis->postcopy_tmp_page; - void *this_host = NULL; + void *host_page = NULL; bool all_zero = true; int target_pages = 0; while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) { ram_addr_t addr; - void *host = NULL; void *page_buffer = NULL; void *place_source = NULL; RAMBlock *block = NULL; @@ -3552,9 +3525,18 @@ static int ram_load_postcopy(QEMUFile *f) if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE | RAM_SAVE_FLAG_COMPRESS_PAGE)) { block = ram_block_from_stream(f, flags); + if (!block) { + ret = -EINVAL; + break; + } - host = host_from_ram_block_offset(block, addr); - if (!host) { + /* + * Relying on used_length is racy and can result in false positives. + * We might place pages beyond used_length in case RAM was shrunk + * while in postcopy, which is fine - trying to place via + * UFFDIO_COPY/UFFDIO_ZEROPAGE will never segfault. + */ + if (!block->host || addr >= block->postcopy_length) { error_report("Illegal RAM offset " RAM_ADDR_FMT, addr); ret = -EINVAL; break; @@ -3572,19 +3554,17 @@ static int ram_load_postcopy(QEMUFile *f) * of a host page in one chunk. */ page_buffer = postcopy_host_page + - ((uintptr_t)host & (block->page_size - 1)); + host_page_offset_from_ram_block_offset(block, addr); + /* If all TP are zero then we can optimise the place */ if (target_pages == 1) { - this_host = (void *)QEMU_ALIGN_DOWN((uintptr_t)host, - block->page_size); - } else { + host_page = host_page_from_ram_block_offset(block, addr); + } else if (host_page != host_page_from_ram_block_offset(block, + addr)) { /* not the 1st TP within the HP */ - if (QEMU_ALIGN_DOWN((uintptr_t)host, block->page_size) != - (uintptr_t)this_host) { - error_report("Non-same host page %p/%p", - host, this_host); - ret = -EINVAL; - break; - } + error_report("Non-same host page %p/%p", host_page, + host_page_from_ram_block_offset(block, addr)); + ret = -EINVAL; + break; } /* @@ -3663,16 +3643,11 @@ static int ram_load_postcopy(QEMUFile *f) } if (!ret && place_needed) { - /* This gets called at the last target page in the host page */ - void *place_dest = (void *)QEMU_ALIGN_DOWN((uintptr_t)host, - block->page_size); - if (all_zero) { - ret = postcopy_place_page_zero(mis, place_dest, - block); + ret = postcopy_place_page_zero(mis, host_page, block); } else { - ret = postcopy_place_page(mis, place_dest, - place_source, block); + ret = postcopy_place_page(mis, host_page, place_source, + block); } place_needed = false; target_pages = 0; @@ -3721,8 +3696,8 @@ void colo_flush_ram_cache(void) while (block) { offset = migration_bitmap_find_dirty(ram_state, block, offset); - if (((ram_addr_t)offset) << TARGET_PAGE_BITS - >= block->used_length) { + if (!offset_in_ramblock(block, + ((ram_addr_t)offset) << TARGET_PAGE_BITS)) { offset = 0; block = QLIST_NEXT_RCU(block, next); } else { @@ -4136,8 +4111,69 @@ static SaveVMHandlers savevm_ram_handlers = { .resume_prepare = ram_resume_prepare, }; +static void ram_mig_ram_block_resized(RAMBlockNotifier *n, void *host, + size_t old_size, size_t new_size) +{ + PostcopyState ps = postcopy_state_get(); + ram_addr_t offset; + RAMBlock *rb = qemu_ram_block_from_host(host, false, &offset); + Error *err = NULL; + + if (ramblock_is_ignored(rb)) { + return; + } + + if (!migration_is_idle()) { + /* + * Precopy code on the source cannot deal with the size of RAM blocks + * changing at random points in time - especially after sending the + * RAM block sizes in the migration stream, they must no longer change. + * Abort and indicate a proper reason. + */ + error_setg(&err, "RAM block '%s' resized during precopy.", rb->idstr); + migrate_set_error(migrate_get_current(), err); + error_free(err); + migration_cancel(); + } + + switch (ps) { + case POSTCOPY_INCOMING_ADVISE: + /* + * Update what ram_postcopy_incoming_init()->init_range() does at the + * time postcopy was advised. Syncing RAM blocks with the source will + * result in RAM resizes. + */ + if (old_size < new_size) { + if (ram_discard_range(rb->idstr, old_size, new_size - old_size)) { + error_report("RAM block '%s' discard of resized RAM failed", + rb->idstr); + } + } + rb->postcopy_length = new_size; + break; + case POSTCOPY_INCOMING_NONE: + case POSTCOPY_INCOMING_RUNNING: + case POSTCOPY_INCOMING_END: + /* + * Once our guest is running, postcopy does no longer care about + * resizes. When growing, the new memory was not available on the + * source, no handler needed. + */ + break; + default: + error_report("RAM block '%s' resized during postcopy state: %d", + rb->idstr, ps); + exit(-1); + } +} + +static RAMBlockNotifier ram_mig_ram_notifier = { + .ram_block_resized = ram_mig_ram_block_resized, +}; + void ram_mig_init(void) { qemu_mutex_init(&XBZRLE.lock); register_savevm_live("ram", 0, 4, &savevm_ram_handlers, &ram_state); + ram_block_notifier_add(&ram_mig_ram_notifier); } diff --git a/migration/target.c b/migration/target.c new file mode 100644 index 0000000000..907ebf0a0a --- /dev/null +++ b/migration/target.c @@ -0,0 +1,25 @@ +/* + * QEMU live migration - functions that need to be compiled target-specific + * + * This work is licensed under the terms of the GNU GPL, version 2 + * or (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qapi/qapi-types-migration.h" +#include "migration.h" + +#ifdef CONFIG_VFIO +#include "hw/vfio/vfio-common.h" +#endif + +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 +} diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 0ad5b77477..d9bef63373 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -224,7 +224,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) migration_global_dump(mon); - if (info->blocked) { + if (info->blocked_reasons) { strList *reasons = info->blocked_reasons; monitor_printf(mon, "Outgoing migration blocked:\n"); while (reasons) { diff --git a/monitor/qmp.c b/monitor/qmp.c index 2b0308f933..092c527b6f 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -257,24 +257,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) trace_monitor_qmp_in_band_dequeue(req_obj, req_obj->mon->qmp_requests->length); - 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(); - /* * @req_obj has a request, we hold req_obj->mon->qmp_queue_lock */ @@ -298,8 +280,30 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) monitor_resume(&mon->common); } + /* + * Drop the queue mutex now, before yielding, otherwise we might + * deadlock if the main thread tries to lock it. + */ qemu_mutex_unlock(&mon->qmp_queue_lock); + 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(); + /* Process request */ if (req_obj->req) { if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) { diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h index dfcfea0ff0..3d0731c4c6 100644 --- a/pc-bios/s390-ccw/helper.h +++ b/pc-bios/s390-ccw/helper.h @@ -31,7 +31,7 @@ static inline void *u32toptr(uint32_t n) static inline void yield(void) { - asm volatile ("diag 0,0,0x44" + asm volatile ("diag %%r0,%%r0,0x44" : : : "memory", "cc"); } diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c index 73e4367e09..78f5f46533 100644 --- a/pc-bios/s390-ccw/jump2ipl.c +++ b/pc-bios/s390-ccw/jump2ipl.c @@ -64,8 +64,8 @@ void jump_to_IPL_code(uint64_t address) * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2 * can then use r15 as its stack pointer. */ - asm volatile("lghi 1,1\n\t" - "diag 1,1,0x308\n\t" + asm volatile("lghi %%r1,1\n\t" + "diag %%r1,%%r1,0x308\n\t" : : : "1", "memory"); panic("\n! IPL returns !\n"); } diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c index de8260a5d6..d601952d3e 100644 --- a/pc-bios/s390-ccw/menu.c +++ b/pc-bios/s390-ccw/menu.c @@ -36,9 +36,9 @@ static inline void enable_clock_int(void) uint64_t tmp = 0; asm volatile( - "stctg 0,0,%0\n" + "stctg %%c0,%%c0,%0\n" "oi 6+%0, 0x8\n" - "lctlg 0,0,%0" + "lctlg %%c0,%%c0,%0" : : "Q" (tmp) : "memory" ); } @@ -48,9 +48,9 @@ static inline void disable_clock_int(void) uint64_t tmp = 0; asm volatile( - "stctg 0,0,%0\n" + "stctg %%c0,%%c0,%0\n" "ni 6+%0, 0xf7\n" - "lctlg 0,0,%0" + "lctlg %%c0,%%c0,%0" : : "Q" (tmp) : "memory" ); } diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index ab49840db8..5d2c6e3381 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -54,7 +54,7 @@ static long kvm_hypercall(unsigned long nr, unsigned long param1, register ulong r_param3 asm("4") = param3; register long retval asm("2"); - asm volatile ("diag 2,4,0x500" + asm volatile ("diag %%r2,%%r4,0x500" : "=d" (retval) : "d" (r_nr), "0" (r_param1), "r"(r_param2), "d"(r_param3) : "memory", "cc"); diff --git a/qapi/block-core.json b/qapi/block-core.json index 6d227924d0..2ea294129e 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2818,7 +2818,6 @@ 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd', { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' }, - 'sheepdog', 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] } ## @@ -3652,26 +3651,6 @@ '*server': ['InetSocketAddressBase'] } } ## -# @BlockdevOptionsSheepdog: -# -# Driver specific block device options for sheepdog -# -# @vdi: Virtual disk image name -# @server: The Sheepdog server to connect to -# @snap-id: Snapshot ID -# @tag: Snapshot tag name -# -# Only one of @snap-id and @tag may be present. -# -# Since: 2.9 -## -{ 'struct': 'BlockdevOptionsSheepdog', - 'data': { 'server': 'SocketAddress', - 'vdi': 'str', - '*snap-id': 'uint32', - '*tag': 'str' } } - -## # @ReplicationMode: # # An enumeration of replication modes. @@ -4037,7 +4016,6 @@ 'rbd': 'BlockdevOptionsRbd', 'replication': { 'type': 'BlockdevOptionsReplication', 'if': 'defined(CONFIG_REPLICATION)' }, - 'sheepdog': 'BlockdevOptionsSheepdog', 'ssh': 'BlockdevOptionsSsh', 'throttle': 'BlockdevOptionsThrottle', 'vdi': 'BlockdevOptionsGenericFormat', @@ -4497,74 +4475,6 @@ ## -# @SheepdogRedundancyType: -# -# @full: Create a fully replicated vdi with x copies -# @erasure-coded: Create an erasure coded vdi with x data strips and -# y parity strips -# -# Since: 2.12 -## -{ 'enum': 'SheepdogRedundancyType', - 'data': [ 'full', 'erasure-coded' ] } - -## -# @SheepdogRedundancyFull: -# -# @copies: Number of copies to use (between 1 and 31) -# -# Since: 2.12 -## -{ 'struct': 'SheepdogRedundancyFull', - 'data': { 'copies': 'int' }} - -## -# @SheepdogRedundancyErasureCoded: -# -# @data-strips: Number of data strips to use (one of {2,4,8,16}) -# @parity-strips: Number of parity strips to use (between 1 and 15) -# -# Since: 2.12 -## -{ 'struct': 'SheepdogRedundancyErasureCoded', - 'data': { 'data-strips': 'int', - 'parity-strips': 'int' }} - -## -# @SheepdogRedundancy: -# -# Since: 2.12 -## -{ 'union': 'SheepdogRedundancy', - 'base': { 'type': 'SheepdogRedundancyType' }, - 'discriminator': 'type', - 'data': { 'full': 'SheepdogRedundancyFull', - 'erasure-coded': 'SheepdogRedundancyErasureCoded' } } - -## -# @BlockdevCreateOptionsSheepdog: -# -# Driver specific image creation options for Sheepdog. -# -# @location: Where to store the new image file -# @size: Size of the virtual disk in bytes -# @backing-file: File name of a base image -# @preallocation: Preallocation mode for the new image (default: off; -# allowed values: off, full) -# @redundancy: Redundancy of the image -# @object-size: Object size of the image -# -# Since: 2.12 -## -{ 'struct': 'BlockdevCreateOptionsSheepdog', - 'data': { 'location': 'BlockdevOptionsSheepdog', - 'size': 'size', - '*backing-file': 'str', - '*preallocation': 'PreallocMode', - '*redundancy': 'SheepdogRedundancy', - '*object-size': 'size' } } - -## # @BlockdevCreateOptionsSsh: # # Driver specific image creation options for SSH. @@ -4687,7 +4597,6 @@ 'qcow2': 'BlockdevCreateOptionsQcow2', 'qed': 'BlockdevCreateOptionsQed', 'rbd': 'BlockdevCreateOptionsRbd', - 'sheepdog': 'BlockdevCreateOptionsSheepdog', 'ssh': 'BlockdevCreateOptionsSsh', 'vdi': 'BlockdevCreateOptionsVdi', 'vhdx': 'BlockdevCreateOptionsVhdx', @@ -5322,7 +5231,7 @@ # # Notes: In transaction, if @name is empty, or any snapshot matching @name # exists, the operation will fail. Only some image formats support it, -# for example, qcow2, rbd, and sheepdog. +# for example, qcow2, and rbd. # # Since: 1.7 ## diff --git a/qapi/machine.json b/qapi/machine.json index 6e90d463fc..58a9c86b36 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -29,11 +29,11 @@ # Since: 3.0 ## { 'enum' : 'SysEmuTarget', - 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', 'lm32', + 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', - 'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc', + 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', - 'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32', + 'sh4eb', 'sparc', 'sparc64', 'tricore', 'x86_64', 'xtensa', 'xtensaeb' ] } ## diff --git a/qapi/migration.json b/qapi/migration.json index 0b17cce46b..7a5bdf9a0d 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -228,11 +228,6 @@ # Present and non-empty when migration is blocked. # (since 6.0) # -# @blocked: True if outgoing migration is blocked (since 6.0) -# -# Features: -# @deprecated: Member @blocked is deprecated. Use @blocked-reasons instead. -# # Since: 0.14 ## { 'struct': 'MigrationInfo', @@ -246,7 +241,6 @@ '*setup-time': 'int', '*cpu-throttle-percentage': 'int', '*error-desc': 'str', - 'blocked': { 'type': 'bool', 'features': [ 'deprecated' ] }, '*blocked-reasons': ['str'], '*postcopy-blocktime' : 'uint32', '*postcopy-vcpu-blocktime': ['uint32'], diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 0c7491cd82..6200c671be 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -23,7 +23,7 @@ ## { 'event': 'RTC_CHANGE', 'data': { 'offset': 'int' }, - 'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_MOXIE) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' } + 'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' } ## # @rtc-reset-reinjection: diff --git a/qapi/transaction.json b/qapi/transaction.json index 15ddebdbc3..894258d9e2 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -112,10 +112,10 @@ # # On failure, the original disks pre-snapshot attempt will be used. # -# For internal snapshots, the dictionary contains the device and the snapshot's -# name. If an internal snapshot matching name already exists, the request will -# be rejected. Only some image formats support it, for example, qcow2, rbd, -# and sheepdog. +# For internal snapshots, the dictionary contains the device and the +# snapshot's name. If an internal snapshot matching name already exists, +# the request will be rejected. Only some image formats support it, for +# example, qcow2, and rbd, # # On failure, qemu will try delete the newly created internal snapshot in the # transaction. When an I/O error occurs during deletion, the user needs to fix diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 97611969cb..998b67186d 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -2457,9 +2457,12 @@ static const cmdinfo_t help_cmd = { .oneline = "help for one or all commands", }; +/* + * Called with aio context of blk acquired. Or with qemu_get_aio_context() + * context acquired if blk is NULL. + */ int qemuio_command(BlockBackend *blk, const char *cmd) { - AioContext *ctx; char *input; const cmdinfo_t *ct; char **v; @@ -2471,10 +2474,7 @@ int qemuio_command(BlockBackend *blk, const char *cmd) if (c) { ct = find_command(v[0]); if (ct) { - ctx = blk ? blk_get_aio_context(blk) : qemu_get_aio_context(); - aio_context_acquire(ctx); ret = command(blk, ct, c, v); - aio_context_release(ctx); } else { fprintf(stderr, "command \"%s\" not found\n", v[0]); ret = -EINVAL; @@ -411,6 +411,19 @@ static void prep_fetchline(void *opaque) *fetchable= 1; } +static int do_qemuio_command(const char *cmd) +{ + int ret; + AioContext *ctx = + qemuio_blk ? blk_get_aio_context(qemuio_blk) : qemu_get_aio_context(); + + aio_context_acquire(ctx); + ret = qemuio_command(qemuio_blk, cmd); + aio_context_release(ctx); + + return ret; +} + static int command_loop(void) { int i, fetchable = 0, prompted = 0; @@ -418,7 +431,7 @@ static int command_loop(void) char *input; for (i = 0; !quit_qemu_io && i < ncmdline; i++) { - ret = qemuio_command(qemuio_blk, cmdline[i]); + ret = do_qemuio_command(cmdline[i]); if (ret < 0) { last_error = ret; } @@ -446,7 +459,7 @@ static int command_loop(void) if (input == NULL) { break; } - ret = qemuio_command(qemuio_blk, input); + ret = do_qemuio_command(input); g_free(input); if (ret < 0) { diff --git a/qemu-options.hx b/qemu-options.hx index 7c825f81fc..e22fb94d99 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2370,7 +2370,9 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, " 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", + " specify SMBIOS type 17 fields\n" + "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n" + " specify SMBIOS type 41 fields\n", QEMU_ARCH_I386 | QEMU_ARCH_ARM) SRST ``-smbios file=binary`` @@ -2432,6 +2434,32 @@ SRST ``-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str][,asset=str][,part=str][,speed=%d]`` Specify SMBIOS type 17 fields + +``-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]`` + Specify SMBIOS type 41 fields + + This argument can be repeated multiple times. Its main use is to allow network interfaces be created + as ``enoX`` on Linux, with X being the instance number, instead of the name depending on the interface + position on the PCI bus. + + Here is an example of use: + + .. parsed-literal:: + + -netdev user,id=internet \\ + -device virtio-net-pci,mac=50:54:00:00:00:42,netdev=internet,id=internet-dev \\ + -smbios type=41,designation='Onboard LAN',instance=1,kind=ethernet,pcidev=internet-dev + + In the guest OS, the device should then appear as ``eno1``: + + ..parsed-literal:: + + $ ip -brief l + lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP> + eno1 UP 50:54:00:00:00:42 <BROADCAST,MULTICAST,UP,LOWER_UP> + + Currently, the PCI device has to be attached to the root bus. + ERST DEFHEADING() @@ -4288,7 +4316,7 @@ SRST ERST DEF("semihosting", 0, QEMU_OPTION_semihosting, "-semihosting semihosting mode\n", - QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 | + QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV) SRST ``-semihosting`` @@ -4303,7 +4331,7 @@ ERST DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config, "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \ " semihosting configuration\n", -QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 | +QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV) SRST ``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]`` diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8f7053ec9b..3d185cceac 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1532,6 +1532,7 @@ sub process { ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && (defined($1) || defined($2)))) && !(($realfile ne '') && + defined($acpi_testexpected) && ($realfile eq $acpi_testexpected))) { $reported_maintainer_file = 1; WARN("added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); diff --git a/softmmu/arch_init.c b/softmmu/arch_init.c index f09bab830c..6ff9f30bad 100644 --- a/softmmu/arch_init.c +++ b/softmmu/arch_init.c @@ -56,16 +56,12 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_HPPA #elif defined(TARGET_I386) #define QEMU_ARCH QEMU_ARCH_I386 -#elif defined(TARGET_LM32) -#define QEMU_ARCH QEMU_ARCH_LM32 #elif defined(TARGET_M68K) #define QEMU_ARCH QEMU_ARCH_M68K #elif defined(TARGET_MICROBLAZE) #define QEMU_ARCH QEMU_ARCH_MICROBLAZE #elif defined(TARGET_MIPS) #define QEMU_ARCH QEMU_ARCH_MIPS -#elif defined(TARGET_MOXIE) -#define QEMU_ARCH QEMU_ARCH_MOXIE #elif defined(TARGET_NIOS2) #define QEMU_ARCH QEMU_ARCH_NIOS2 #elif defined(TARGET_OPENRISC) @@ -84,8 +80,6 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_SPARC #elif defined(TARGET_TRICORE) #define QEMU_ARCH QEMU_ARCH_TRICORE -#elif defined(TARGET_UNICORE32) -#define QEMU_ARCH QEMU_ARCH_UNICORE32 #elif defined(TARGET_XTENSA) #define QEMU_ARCH QEMU_ARCH_XTENSA #elif defined(TARGET_AVR) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 5232696571..e1da81ed2f 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1694,6 +1694,11 @@ ram_addr_t qemu_ram_get_used_length(RAMBlock *rb) return rb->used_length; } +ram_addr_t qemu_ram_get_max_length(RAMBlock *rb) +{ + return rb->max_length; +} + bool qemu_ram_is_shared(RAMBlock *rb) { return rb->flags & RAM_SHARED; @@ -1793,8 +1798,9 @@ static int memory_try_enable_merging(void *addr, size_t len) return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE); } -/* Only legal before guest might have detected the memory size: e.g. on - * incoming migration, or right after reset. +/* + * Resizing RAM while migrating can result in the migration being canceled. + * Care has to be taken if the guest might have already detected the memory. * * As memory core doesn't know how is memory accessed, it is up to * resize callback to update device state and/or add assertions to detect @@ -1802,6 +1808,7 @@ static int memory_try_enable_merging(void *addr, size_t len) */ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) { + const ram_addr_t oldsize = block->used_length; const ram_addr_t unaligned_size = newsize; assert(block); @@ -1838,6 +1845,11 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) return -EINVAL; } + /* Notify before modifying the ram block and touching the bitmaps. */ + if (block->host) { + ram_block_notify_resize(block->host, oldsize, newsize); + } + cpu_physical_memory_clear_dirty_range(block->offset, block->used_length); block->used_length = newsize; cpu_physical_memory_set_dirty_range(block->offset, block->used_length, @@ -2005,7 +2017,8 @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared) qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK); } - ram_block_notify_add(new_block->host, new_block->max_length); + ram_block_notify_add(new_block->host, new_block->used_length, + new_block->max_length); } } @@ -2184,7 +2197,8 @@ void qemu_ram_free(RAMBlock *block) } if (block->host) { - ram_block_notify_remove(block->host, block->max_length); + ram_block_notify_remove(block->host, block->used_length, + block->max_length); } qemu_mutex_lock_ramlist(); @@ -3486,7 +3500,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) goto err; } - if ((start + length) <= rb->used_length) { + if ((start + length) <= rb->max_length) { bool need_madvise, need_fallocate; if (!QEMU_IS_ALIGNED(length, rb->page_size)) { error_report("ram_block_discard_range: Unaligned length: %zx", @@ -3553,7 +3567,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) } else { error_report("ram_block_discard_range: Overrun block '%s' (%" PRIu64 "/%zx/" RAM_ADDR_FMT")", - rb->idstr, start, length, rb->used_length); + rb->idstr, start, length, rb->max_length); } err: diff --git a/target/i386/hax/hax-mem.c b/target/i386/hax/hax-mem.c index 35495f5e82..8d44edbffd 100644 --- a/target/i386/hax/hax-mem.c +++ b/target/i386/hax/hax-mem.c @@ -293,7 +293,8 @@ static MemoryListener hax_memory_listener = { .priority = 10, }; -static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) +static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size, + size_t max_size) { /* * We must register each RAM block with the HAXM kernel module, or @@ -304,7 +305,7 @@ static void hax_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) * host physical pages for the RAM block as part of this registration * process, hence the name hax_populate_ram(). */ - if (hax_populate_ram((uint64_t)(uintptr_t)host, size) < 0) { + if (hax_populate_ram((uint64_t)(uintptr_t)host, max_size) < 0) { fprintf(stderr, "HAX failed to populate RAM\n"); abort(); } diff --git a/target/i386/sev.c b/target/i386/sev.c index 9a43be11cb..41f7800b5f 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -180,7 +180,8 @@ sev_set_guest_state(SevGuestState *sev, SevState new_state) } static void -sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) +sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size, + size_t max_size) { int r; struct kvm_enc_region range; @@ -197,19 +198,20 @@ sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) } range.addr = (__u64)(unsigned long)host; - range.size = size; + range.size = max_size; - trace_kvm_memcrypt_register_region(host, size); + trace_kvm_memcrypt_register_region(host, max_size); r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range); if (r) { error_report("%s: failed to register region (%p+%#zx) error '%s'", - __func__, host, size, strerror(errno)); + __func__, host, max_size, strerror(errno)); exit(1); } } static void -sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size) +sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size, + size_t max_size) { int r; struct kvm_enc_region range; @@ -226,13 +228,13 @@ sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size) } range.addr = (__u64)(unsigned long)host; - range.size = size; + range.size = max_size; - trace_kvm_memcrypt_unregister_region(host, size); + trace_kvm_memcrypt_unregister_region(host, max_size); r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range); if (r) { error_report("%s: failed to unregister region (%p+%#zx)", - __func__, host, size); + __func__, host, max_size); } } diff --git a/target/lm32/README b/target/lm32/README deleted file mode 100644 index ba3508a711..0000000000 --- a/target/lm32/README +++ /dev/null @@ -1,45 +0,0 @@ -LatticeMico32 target --------------------- - -General -------- -All opcodes including the JUART CSRs are supported. - - -JTAG UART ---------- -JTAG UART is routed to a serial console device. For the current boards it -is the second one. Ie to enable it in the qemu virtual console window use -the following command line parameters: - -serial vc -serial vc -This will make serial0 (the lm32_uart) and serial1 (the JTAG UART) -available as virtual consoles. - - -Semihosting ------------ -Semihosting on this target is supported. Some system calls like read, write -and exit are executed on the host if semihosting is enabled. See -target/lm32-semi.c for all supported system calls. Emulation aware programs -can use this mechanism to shut down the virtual machine and print to the -host console. See the tcg tests for an example. - - -Special instructions --------------------- -The translation recognizes one special instruction to halt the cpu: - and r0, r0, r0 -On real hardware this instruction is a nop. It is not used by GCC and -should (hopefully) not be used within hand-crafted assembly. -Insert this instruction in your idle loop to reduce the cpu load on the -host. - - -Ignoring the MSB of the address bus ------------------------------------ -Some SoC ignores the MSB on the address bus. Thus creating a shadow memory -area. As a general rule, 0x00000000-0x7fffffff is cached, whereas -0x80000000-0xffffffff is not cached and used to access IO devices. This -behaviour can be enabled with: - cpu_lm32_set_phys_msb_ignore(env, 1); - diff --git a/target/lm32/TODO b/target/lm32/TODO deleted file mode 100644 index e163c42ebe..0000000000 --- a/target/lm32/TODO +++ /dev/null @@ -1 +0,0 @@ -* linux-user emulation diff --git a/target/lm32/cpu-param.h b/target/lm32/cpu-param.h deleted file mode 100644 index d89574ad19..0000000000 --- a/target/lm32/cpu-param.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * LatticeMico32 cpu parameters for qemu. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * SPDX-License-Identifier: LGPL-2.0+ - */ - -#ifndef LM32_CPU_PARAM_H -#define LM32_CPU_PARAM_H 1 - -#define TARGET_LONG_BITS 32 -#define TARGET_PAGE_BITS 12 -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define NB_MMU_MODES 1 - -#endif diff --git a/target/lm32/cpu-qom.h b/target/lm32/cpu-qom.h deleted file mode 100644 index 245b35cd1d..0000000000 --- a/target/lm32/cpu-qom.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * QEMU LatticeMico32 CPU - * - * Copyright (c) 2012 SUSE LINUX Products GmbH - * - * This library is free software; you can redistribute it 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 - * <http://www.gnu.org/licenses/lgpl-2.1.html> - */ -#ifndef QEMU_LM32_CPU_QOM_H -#define QEMU_LM32_CPU_QOM_H - -#include "hw/core/cpu.h" -#include "qom/object.h" - -#define TYPE_LM32_CPU "lm32-cpu" - -OBJECT_DECLARE_TYPE(LM32CPU, LM32CPUClass, - LM32_CPU) - -/** - * LM32CPUClass: - * @parent_realize: The parent class' realize handler. - * @parent_reset: The parent class' reset handler. - * - * A LatticeMico32 CPU model. - */ -struct LM32CPUClass { - /*< private >*/ - CPUClass parent_class; - /*< public >*/ - - DeviceRealize parent_realize; - DeviceReset parent_reset; -}; - - -#endif diff --git a/target/lm32/cpu.c b/target/lm32/cpu.c deleted file mode 100644 index c23d72874c..0000000000 --- a/target/lm32/cpu.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * QEMU LatticeMico32 CPU - * - * Copyright (c) 2012 SUSE LINUX Products GmbH - * - * This library is free software; you can redistribute it 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 - * <http://www.gnu.org/licenses/lgpl-2.1.html> - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu/qemu-print.h" -#include "cpu.h" - - -static void lm32_cpu_set_pc(CPUState *cs, vaddr value) -{ - LM32CPU *cpu = LM32_CPU(cs); - - cpu->env.pc = value; -} - -static void lm32_cpu_list_entry(gpointer data, gpointer user_data) -{ - ObjectClass *oc = data; - const char *typename = object_class_get_name(oc); - char *name; - - name = g_strndup(typename, strlen(typename) - strlen(LM32_CPU_TYPE_SUFFIX)); - qemu_printf(" %s\n", name); - g_free(name); -} - - -void lm32_cpu_list(void) -{ - GSList *list; - - list = object_class_get_list_sorted(TYPE_LM32_CPU, false); - qemu_printf("Available CPUs:\n"); - g_slist_foreach(list, lm32_cpu_list_entry, NULL); - g_slist_free(list); -} - -static void lm32_cpu_init_cfg_reg(LM32CPU *cpu) -{ - CPULM32State *env = &cpu->env; - uint32_t cfg = 0; - - if (cpu->features & LM32_FEATURE_MULTIPLY) { - cfg |= CFG_M; - } - - if (cpu->features & LM32_FEATURE_DIVIDE) { - cfg |= CFG_D; - } - - if (cpu->features & LM32_FEATURE_SHIFT) { - cfg |= CFG_S; - } - - if (cpu->features & LM32_FEATURE_SIGN_EXTEND) { - cfg |= CFG_X; - } - - if (cpu->features & LM32_FEATURE_I_CACHE) { - cfg |= CFG_IC; - } - - if (cpu->features & LM32_FEATURE_D_CACHE) { - cfg |= CFG_DC; - } - - if (cpu->features & LM32_FEATURE_CYCLE_COUNT) { - cfg |= CFG_CC; - } - - cfg |= (cpu->num_interrupts << CFG_INT_SHIFT); - cfg |= (cpu->num_breakpoints << CFG_BP_SHIFT); - cfg |= (cpu->num_watchpoints << CFG_WP_SHIFT); - cfg |= (cpu->revision << CFG_REV_SHIFT); - - env->cfg = cfg; -} - -static bool lm32_cpu_has_work(CPUState *cs) -{ - return cs->interrupt_request & CPU_INTERRUPT_HARD; -} - -static void lm32_cpu_reset(DeviceState *dev) -{ - CPUState *s = CPU(dev); - LM32CPU *cpu = LM32_CPU(s); - LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu); - CPULM32State *env = &cpu->env; - - lcc->parent_reset(dev); - - /* reset cpu state */ - memset(env, 0, offsetof(CPULM32State, end_reset_fields)); - - lm32_cpu_init_cfg_reg(cpu); -} - -static void lm32_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) -{ - info->mach = bfd_mach_lm32; - info->print_insn = print_insn_lm32; -} - -static void lm32_cpu_realizefn(DeviceState *dev, Error **errp) -{ - CPUState *cs = CPU(dev); - LM32CPUClass *lcc = LM32_CPU_GET_CLASS(dev); - Error *local_err = NULL; - - cpu_exec_realizefn(cs, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } - - cpu_reset(cs); - - qemu_init_vcpu(cs); - - lcc->parent_realize(dev, errp); -} - -static void lm32_cpu_initfn(Object *obj) -{ - LM32CPU *cpu = LM32_CPU(obj); - CPULM32State *env = &cpu->env; - - cpu_set_cpustate_pointers(cpu); - - env->flags = 0; -} - -static void lm32_basic_cpu_initfn(Object *obj) -{ - LM32CPU *cpu = LM32_CPU(obj); - - cpu->revision = 3; - cpu->num_interrupts = 32; - cpu->num_breakpoints = 4; - cpu->num_watchpoints = 4; - cpu->features = LM32_FEATURE_SHIFT - | LM32_FEATURE_SIGN_EXTEND - | LM32_FEATURE_CYCLE_COUNT; -} - -static void lm32_standard_cpu_initfn(Object *obj) -{ - LM32CPU *cpu = LM32_CPU(obj); - - cpu->revision = 3; - cpu->num_interrupts = 32; - cpu->num_breakpoints = 4; - cpu->num_watchpoints = 4; - cpu->features = LM32_FEATURE_MULTIPLY - | LM32_FEATURE_DIVIDE - | LM32_FEATURE_SHIFT - | LM32_FEATURE_SIGN_EXTEND - | LM32_FEATURE_I_CACHE - | LM32_FEATURE_CYCLE_COUNT; -} - -static void lm32_full_cpu_initfn(Object *obj) -{ - LM32CPU *cpu = LM32_CPU(obj); - - cpu->revision = 3; - cpu->num_interrupts = 32; - cpu->num_breakpoints = 4; - cpu->num_watchpoints = 4; - cpu->features = LM32_FEATURE_MULTIPLY - | LM32_FEATURE_DIVIDE - | LM32_FEATURE_SHIFT - | LM32_FEATURE_SIGN_EXTEND - | LM32_FEATURE_I_CACHE - | LM32_FEATURE_D_CACHE - | LM32_FEATURE_CYCLE_COUNT; -} - -static ObjectClass *lm32_cpu_class_by_name(const char *cpu_model) -{ - ObjectClass *oc; - char *typename; - - typename = g_strdup_printf(LM32_CPU_TYPE_NAME("%s"), cpu_model); - oc = object_class_by_name(typename); - g_free(typename); - if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_LM32_CPU) || - object_class_is_abstract(oc))) { - oc = NULL; - } - return oc; -} - -#include "hw/core/tcg-cpu-ops.h" - -static struct TCGCPUOps lm32_tcg_ops = { - .initialize = lm32_translate_init, - .cpu_exec_interrupt = lm32_cpu_exec_interrupt, - .tlb_fill = lm32_cpu_tlb_fill, - .debug_excp_handler = lm32_debug_excp_handler, - -#ifndef CONFIG_USER_ONLY - .do_interrupt = lm32_cpu_do_interrupt, -#endif /* !CONFIG_USER_ONLY */ -}; - -static void lm32_cpu_class_init(ObjectClass *oc, void *data) -{ - LM32CPUClass *lcc = LM32_CPU_CLASS(oc); - CPUClass *cc = CPU_CLASS(oc); - DeviceClass *dc = DEVICE_CLASS(oc); - - device_class_set_parent_realize(dc, lm32_cpu_realizefn, - &lcc->parent_realize); - device_class_set_parent_reset(dc, lm32_cpu_reset, &lcc->parent_reset); - - cc->class_by_name = lm32_cpu_class_by_name; - cc->has_work = lm32_cpu_has_work; - cc->dump_state = lm32_cpu_dump_state; - cc->set_pc = lm32_cpu_set_pc; - cc->gdb_read_register = lm32_cpu_gdb_read_register; - cc->gdb_write_register = lm32_cpu_gdb_write_register; -#ifndef CONFIG_USER_ONLY - cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug; - cc->vmsd = &vmstate_lm32_cpu; -#endif - cc->gdb_num_core_regs = 32 + 7; - cc->gdb_stop_before_watchpoint = true; - cc->disas_set_info = lm32_cpu_disas_set_info; - cc->tcg_ops = &lm32_tcg_ops; -} - -#define DEFINE_LM32_CPU_TYPE(cpu_model, initfn) \ - { \ - .parent = TYPE_LM32_CPU, \ - .name = LM32_CPU_TYPE_NAME(cpu_model), \ - .instance_init = initfn, \ - } - -static const TypeInfo lm32_cpus_type_infos[] = { - { /* base class should be registered first */ - .name = TYPE_LM32_CPU, - .parent = TYPE_CPU, - .instance_size = sizeof(LM32CPU), - .instance_init = lm32_cpu_initfn, - .abstract = true, - .class_size = sizeof(LM32CPUClass), - .class_init = lm32_cpu_class_init, - }, - DEFINE_LM32_CPU_TYPE("lm32-basic", lm32_basic_cpu_initfn), - DEFINE_LM32_CPU_TYPE("lm32-standard", lm32_standard_cpu_initfn), - DEFINE_LM32_CPU_TYPE("lm32-full", lm32_full_cpu_initfn), -}; - -DEFINE_TYPES(lm32_cpus_type_infos) diff --git a/target/lm32/cpu.h b/target/lm32/cpu.h deleted file mode 100644 index ea7c01ca8b..0000000000 --- a/target/lm32/cpu.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * LatticeMico32 virtual CPU header. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef LM32_CPU_H -#define LM32_CPU_H - -#include "cpu-qom.h" -#include "exec/cpu-defs.h" - -typedef struct CPULM32State CPULM32State; - -static inline int cpu_mmu_index(CPULM32State *env, bool ifetch) -{ - return 0; -} - -/* Exceptions indices */ -enum { - EXCP_RESET = 0, - EXCP_BREAKPOINT, - EXCP_INSN_BUS_ERROR, - EXCP_WATCHPOINT, - EXCP_DATA_BUS_ERROR, - EXCP_DIVIDE_BY_ZERO, - EXCP_IRQ, - EXCP_SYSTEMCALL -}; - -/* Registers */ -enum { - R_R0 = 0, R_R1, R_R2, R_R3, R_R4, R_R5, R_R6, R_R7, R_R8, R_R9, R_R10, - R_R11, R_R12, R_R13, R_R14, R_R15, R_R16, R_R17, R_R18, R_R19, R_R20, - R_R21, R_R22, R_R23, R_R24, R_R25, R_R26, R_R27, R_R28, R_R29, R_R30, - R_R31 -}; - -/* Register aliases */ -enum { - R_GP = R_R26, - R_FP = R_R27, - R_SP = R_R28, - R_RA = R_R29, - R_EA = R_R30, - R_BA = R_R31 -}; - -/* IE flags */ -enum { - IE_IE = (1<<0), - IE_EIE = (1<<1), - IE_BIE = (1<<2), -}; - -/* DC flags */ -enum { - DC_SS = (1<<0), - DC_RE = (1<<1), - DC_C0 = (1<<2), - DC_C1 = (1<<3), - DC_C2 = (1<<4), - DC_C3 = (1<<5), -}; - -/* CFG mask */ -enum { - CFG_M = (1<<0), - CFG_D = (1<<1), - CFG_S = (1<<2), - CFG_U = (1<<3), - CFG_X = (1<<4), - CFG_CC = (1<<5), - CFG_IC = (1<<6), - CFG_DC = (1<<7), - CFG_G = (1<<8), - CFG_H = (1<<9), - CFG_R = (1<<10), - CFG_J = (1<<11), - CFG_INT_SHIFT = 12, - CFG_BP_SHIFT = 18, - CFG_WP_SHIFT = 22, - CFG_REV_SHIFT = 26, -}; - -/* CSRs */ -enum { - CSR_IE = 0x00, - CSR_IM = 0x01, - CSR_IP = 0x02, - CSR_ICC = 0x03, - CSR_DCC = 0x04, - CSR_CC = 0x05, - CSR_CFG = 0x06, - CSR_EBA = 0x07, - CSR_DC = 0x08, - CSR_DEBA = 0x09, - CSR_JTX = 0x0e, - CSR_JRX = 0x0f, - CSR_BP0 = 0x10, - CSR_BP1 = 0x11, - CSR_BP2 = 0x12, - CSR_BP3 = 0x13, - CSR_WP0 = 0x18, - CSR_WP1 = 0x19, - CSR_WP2 = 0x1a, - CSR_WP3 = 0x1b, -}; - -enum { - LM32_FEATURE_MULTIPLY = 1, - LM32_FEATURE_DIVIDE = 2, - LM32_FEATURE_SHIFT = 4, - LM32_FEATURE_SIGN_EXTEND = 8, - LM32_FEATURE_I_CACHE = 16, - LM32_FEATURE_D_CACHE = 32, - LM32_FEATURE_CYCLE_COUNT = 64, -}; - -enum { - LM32_FLAG_IGNORE_MSB = 1, -}; - -struct CPULM32State { - /* general registers */ - uint32_t regs[32]; - - /* special registers */ - uint32_t pc; /* program counter */ - uint32_t ie; /* interrupt enable */ - uint32_t icc; /* instruction cache control */ - uint32_t dcc; /* data cache control */ - uint32_t cc; /* cycle counter */ - uint32_t cfg; /* configuration */ - - /* debug registers */ - uint32_t dc; /* debug control */ - uint32_t bp[4]; /* breakpoints */ - uint32_t wp[4]; /* watchpoints */ - - struct CPUBreakpoint *cpu_breakpoint[4]; - struct CPUWatchpoint *cpu_watchpoint[4]; - - /* Fields up to this point are cleared by a CPU reset */ - struct {} end_reset_fields; - - /* Fields from here on are preserved across CPU reset. */ - uint32_t eba; /* exception base address */ - uint32_t deba; /* debug exception base address */ - - /* interrupt controller handle for callbacks */ - DeviceState *pic_state; - /* JTAG UART handle for callbacks */ - DeviceState *juart_state; - - /* processor core features */ - uint32_t flags; - -}; - -/** - * LM32CPU: - * @env: #CPULM32State - * - * A LatticeMico32 CPU. - */ -struct LM32CPU { - /*< private >*/ - CPUState parent_obj; - /*< public >*/ - - CPUNegativeOffsetState neg; - CPULM32State env; - - uint32_t revision; - uint8_t num_interrupts; - uint8_t num_breakpoints; - uint8_t num_watchpoints; - uint32_t features; -}; - - -#ifndef CONFIG_USER_ONLY -extern const VMStateDescription vmstate_lm32_cpu; -#endif - -void lm32_cpu_do_interrupt(CPUState *cpu); -bool lm32_cpu_exec_interrupt(CPUState *cs, int int_req); -void lm32_cpu_dump_state(CPUState *cpu, FILE *f, int flags); -hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -int lm32_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); -int lm32_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); - -typedef enum { - LM32_WP_DISABLED = 0, - LM32_WP_READ, - LM32_WP_WRITE, - LM32_WP_READ_WRITE, -} lm32_wp_t; - -static inline lm32_wp_t lm32_wp_type(uint32_t dc, int idx) -{ - assert(idx < 4); - return (dc >> (idx+1)*2) & 0x3; -} - -/* you can call this signal handler from your SIGBUS and SIGSEGV - signal handlers to inform the virtual CPU of exceptions. non zero - is returned if the signal was handled by the virtual CPU. */ -int cpu_lm32_signal_handler(int host_signum, void *pinfo, - void *puc); -void lm32_cpu_list(void); -void lm32_translate_init(void); -void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value); -void QEMU_NORETURN raise_exception(CPULM32State *env, int index); -void lm32_debug_excp_handler(CPUState *cs); -void lm32_breakpoint_insert(CPULM32State *env, int index, target_ulong address); -void lm32_breakpoint_remove(CPULM32State *env, int index); -void lm32_watchpoint_insert(CPULM32State *env, int index, target_ulong address, - lm32_wp_t wp_type); -void lm32_watchpoint_remove(CPULM32State *env, int index); -bool lm32_cpu_do_semihosting(CPUState *cs); - -#define LM32_CPU_TYPE_SUFFIX "-" TYPE_LM32_CPU -#define LM32_CPU_TYPE_NAME(model) model LM32_CPU_TYPE_SUFFIX -#define CPU_RESOLVING_TYPE TYPE_LM32_CPU - -#define cpu_list lm32_cpu_list -#define cpu_signal_handler cpu_lm32_signal_handler - -bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr); - -typedef CPULM32State CPUArchState; -typedef LM32CPU ArchCPU; - -#include "exec/cpu-all.h" - -static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) -{ - *pc = env->pc; - *cs_base = 0; - *flags = 0; -} - -#endif diff --git a/target/lm32/gdbstub.c b/target/lm32/gdbstub.c deleted file mode 100644 index 56f508a5b6..0000000000 --- a/target/lm32/gdbstub.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * LM32 gdb server stub - * - * Copyright (c) 2003-2005 Fabrice Bellard - * Copyright (c) 2013 SUSE LINUX Products GmbH - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/gdbstub.h" -#include "hw/lm32/lm32_pic.h" - -int lm32_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - - if (n < 32) { - return gdb_get_reg32(mem_buf, env->regs[n]); - } else { - switch (n) { - case 32: - return gdb_get_reg32(mem_buf, env->pc); - /* FIXME: put in right exception ID */ - case 33: - return gdb_get_reg32(mem_buf, 0); - case 34: - return gdb_get_reg32(mem_buf, env->eba); - case 35: - return gdb_get_reg32(mem_buf, env->deba); - case 36: - return gdb_get_reg32(mem_buf, env->ie); - case 37: - return gdb_get_reg32(mem_buf, lm32_pic_get_im(env->pic_state)); - case 38: - return gdb_get_reg32(mem_buf, lm32_pic_get_ip(env->pic_state)); - } - } - return 0; -} - -int lm32_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPUClass *cc = CPU_GET_CLASS(cs); - CPULM32State *env = &cpu->env; - uint32_t tmp; - - if (n > cc->gdb_num_core_regs) { - return 0; - } - - tmp = ldl_p(mem_buf); - - if (n < 32) { - env->regs[n] = tmp; - } else { - switch (n) { - case 32: - env->pc = tmp; - break; - case 34: - env->eba = tmp; - break; - case 35: - env->deba = tmp; - break; - case 36: - env->ie = tmp; - break; - case 37: - lm32_pic_set_im(env->pic_state, tmp); - break; - case 38: - lm32_pic_set_ip(env->pic_state, tmp); - break; - } - } - return 4; -} diff --git a/target/lm32/helper.c b/target/lm32/helper.c deleted file mode 100644 index 01cc3c53a5..0000000000 --- a/target/lm32/helper.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * LatticeMico32 helper routines. - * - * Copyright (c) 2010-2014 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "qemu/host-utils.h" -#include "semihosting/semihost.h" -#include "exec/log.h" - -bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - int prot; - - address &= TARGET_PAGE_MASK; - prot = PAGE_BITS; - if (env->flags & LM32_FLAG_IGNORE_MSB) { - tlb_set_page(cs, address, address & 0x7fffffff, prot, mmu_idx, - TARGET_PAGE_SIZE); - } else { - tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); - } - return true; -} - -hwaddr lm32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - LM32CPU *cpu = LM32_CPU(cs); - - addr &= TARGET_PAGE_MASK; - if (cpu->env.flags & LM32_FLAG_IGNORE_MSB) { - return addr & 0x7fffffff; - } else { - return addr; - } -} - -void lm32_breakpoint_insert(CPULM32State *env, int idx, target_ulong address) -{ - cpu_breakpoint_insert(env_cpu(env), address, BP_CPU, - &env->cpu_breakpoint[idx]); -} - -void lm32_breakpoint_remove(CPULM32State *env, int idx) -{ - if (!env->cpu_breakpoint[idx]) { - return; - } - - cpu_breakpoint_remove_by_ref(env_cpu(env), env->cpu_breakpoint[idx]); - env->cpu_breakpoint[idx] = NULL; -} - -void lm32_watchpoint_insert(CPULM32State *env, int idx, target_ulong address, - lm32_wp_t wp_type) -{ - int flags = 0; - - switch (wp_type) { - case LM32_WP_DISABLED: - /* nothing to do */ - break; - case LM32_WP_READ: - flags = BP_CPU | BP_STOP_BEFORE_ACCESS | BP_MEM_READ; - break; - case LM32_WP_WRITE: - flags = BP_CPU | BP_STOP_BEFORE_ACCESS | BP_MEM_WRITE; - break; - case LM32_WP_READ_WRITE: - flags = BP_CPU | BP_STOP_BEFORE_ACCESS | BP_MEM_ACCESS; - break; - } - - if (flags != 0) { - cpu_watchpoint_insert(env_cpu(env), address, 1, flags, - &env->cpu_watchpoint[idx]); - } -} - -void lm32_watchpoint_remove(CPULM32State *env, int idx) -{ - if (!env->cpu_watchpoint[idx]) { - return; - } - - cpu_watchpoint_remove_by_ref(env_cpu(env), env->cpu_watchpoint[idx]); - env->cpu_watchpoint[idx] = NULL; -} - -static bool check_watchpoints(CPULM32State *env) -{ - LM32CPU *cpu = env_archcpu(env); - int i; - - for (i = 0; i < cpu->num_watchpoints; i++) { - if (env->cpu_watchpoint[i] && - env->cpu_watchpoint[i]->flags & BP_WATCHPOINT_HIT) { - return true; - } - } - return false; -} - -void lm32_debug_excp_handler(CPUState *cs) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - CPUBreakpoint *bp; - - if (cs->watchpoint_hit) { - if (cs->watchpoint_hit->flags & BP_CPU) { - cs->watchpoint_hit = NULL; - if (check_watchpoints(env)) { - raise_exception(env, EXCP_WATCHPOINT); - } else { - cpu_loop_exit_noexc(cs); - } - } - } else { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == env->pc) { - if (bp->flags & BP_CPU) { - raise_exception(env, EXCP_BREAKPOINT); - } - break; - } - } - } -} - -void lm32_cpu_do_interrupt(CPUState *cs) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - - qemu_log_mask(CPU_LOG_INT, - "exception at pc=%x type=%x\n", env->pc, cs->exception_index); - - switch (cs->exception_index) { - case EXCP_SYSTEMCALL: - if (unlikely(semihosting_enabled())) { - /* do_semicall() returns true if call was handled. Otherwise - * do the normal exception handling. */ - if (lm32_cpu_do_semihosting(cs)) { - env->pc += 4; - break; - } - } - /* fall through */ - case EXCP_INSN_BUS_ERROR: - case EXCP_DATA_BUS_ERROR: - case EXCP_DIVIDE_BY_ZERO: - case EXCP_IRQ: - /* non-debug exceptions */ - env->regs[R_EA] = env->pc; - env->ie |= (env->ie & IE_IE) ? IE_EIE : 0; - env->ie &= ~IE_IE; - if (env->dc & DC_RE) { - env->pc = env->deba + (cs->exception_index * 32); - } else { - env->pc = env->eba + (cs->exception_index * 32); - } - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - break; - case EXCP_BREAKPOINT: - case EXCP_WATCHPOINT: - /* debug exceptions */ - env->regs[R_BA] = env->pc; - env->ie |= (env->ie & IE_IE) ? IE_BIE : 0; - env->ie &= ~IE_IE; - env->pc = env->deba + (cs->exception_index * 32); - log_cpu_state_mask(CPU_LOG_INT, cs, 0); - break; - default: - cpu_abort(cs, "unhandled exception type=%d\n", - cs->exception_index); - break; - } -} - -bool lm32_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - - if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->ie & IE_IE)) { - cs->exception_index = EXCP_IRQ; - lm32_cpu_do_interrupt(cs); - return true; - } - return false; -} - -/* Some soc ignores the MSB on the address bus. Thus creating a shadow memory - * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas - * 0x80000000-0xffffffff is not cached and used to access IO devices. */ -void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value) -{ - if (value) { - env->flags |= LM32_FLAG_IGNORE_MSB; - } else { - env->flags &= ~LM32_FLAG_IGNORE_MSB; - } -} diff --git a/target/lm32/helper.h b/target/lm32/helper.h deleted file mode 100644 index 445578c439..0000000000 --- a/target/lm32/helper.h +++ /dev/null @@ -1,14 +0,0 @@ -DEF_HELPER_2(raise_exception, void, env, i32) -DEF_HELPER_1(hlt, void, env) -DEF_HELPER_3(wcsr_bp, void, env, i32, i32) -DEF_HELPER_3(wcsr_wp, void, env, i32, i32) -DEF_HELPER_2(wcsr_dc, void, env, i32) -DEF_HELPER_2(wcsr_im, void, env, i32) -DEF_HELPER_2(wcsr_ip, void, env, i32) -DEF_HELPER_2(wcsr_jtx, void, env, i32) -DEF_HELPER_2(wcsr_jrx, void, env, i32) -DEF_HELPER_1(rcsr_im, i32, env) -DEF_HELPER_1(rcsr_ip, i32, env) -DEF_HELPER_1(rcsr_jtx, i32, env) -DEF_HELPER_1(rcsr_jrx, i32, env) -DEF_HELPER_1(ill, void, env) diff --git a/target/lm32/lm32-semi.c b/target/lm32/lm32-semi.c deleted file mode 100644 index 661a770249..0000000000 --- a/target/lm32/lm32-semi.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Lattice Mico32 semihosting syscall interface - * - * Copyright (c) 2014 Michael Walle <michael@walle.cc> - * - * Based on target/m68k/m68k-semi.c, which is - * Copyright (c) 2005-2007 CodeSourcery. - * - * 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 "exec/helper-proto.h" -#include "exec/softmmu-semi.h" - -enum { - TARGET_SYS_exit = 1, - TARGET_SYS_open = 2, - TARGET_SYS_close = 3, - TARGET_SYS_read = 4, - TARGET_SYS_write = 5, - TARGET_SYS_lseek = 6, - TARGET_SYS_fstat = 10, - TARGET_SYS_stat = 15, -}; - -enum { - NEWLIB_O_RDONLY = 0x0, - NEWLIB_O_WRONLY = 0x1, - NEWLIB_O_RDWR = 0x2, - NEWLIB_O_APPEND = 0x8, - NEWLIB_O_CREAT = 0x200, - NEWLIB_O_TRUNC = 0x400, - NEWLIB_O_EXCL = 0x800, -}; - -static int translate_openflags(int flags) -{ - int hf; - - if (flags & NEWLIB_O_WRONLY) { - hf = O_WRONLY; - } else if (flags & NEWLIB_O_RDWR) { - hf = O_RDWR; - } else { - hf = O_RDONLY; - } - - if (flags & NEWLIB_O_APPEND) { - hf |= O_APPEND; - } - - if (flags & NEWLIB_O_CREAT) { - hf |= O_CREAT; - } - - if (flags & NEWLIB_O_TRUNC) { - hf |= O_TRUNC; - } - - if (flags & NEWLIB_O_EXCL) { - hf |= O_EXCL; - } - - return hf; -} - -struct newlib_stat { - int16_t newlib_st_dev; /* device */ - uint16_t newlib_st_ino; /* inode */ - uint16_t newlib_st_mode; /* protection */ - uint16_t newlib_st_nlink; /* number of hard links */ - uint16_t newlib_st_uid; /* user ID of owner */ - uint16_t newlib_st_gid; /* group ID of owner */ - int16_t newlib_st_rdev; /* device type (if inode device) */ - int32_t newlib_st_size; /* total size, in bytes */ - int32_t newlib_st_atime; /* time of last access */ - uint32_t newlib_st_spare1; - int32_t newlib_st_mtime; /* time of last modification */ - uint32_t newlib_st_spare2; - int32_t newlib_st_ctime; /* time of last change */ - uint32_t newlib_st_spare3; -} QEMU_PACKED; - -static int translate_stat(CPULM32State *env, target_ulong addr, - struct stat *s) -{ - struct newlib_stat *p; - - p = lock_user(VERIFY_WRITE, addr, sizeof(struct newlib_stat), 0); - if (!p) { - return 0; - } - p->newlib_st_dev = cpu_to_be16(s->st_dev); - p->newlib_st_ino = cpu_to_be16(s->st_ino); - p->newlib_st_mode = cpu_to_be16(s->st_mode); - p->newlib_st_nlink = cpu_to_be16(s->st_nlink); - p->newlib_st_uid = cpu_to_be16(s->st_uid); - p->newlib_st_gid = cpu_to_be16(s->st_gid); - p->newlib_st_rdev = cpu_to_be16(s->st_rdev); - p->newlib_st_size = cpu_to_be32(s->st_size); - p->newlib_st_atime = cpu_to_be32(s->st_atime); - p->newlib_st_mtime = cpu_to_be32(s->st_mtime); - p->newlib_st_ctime = cpu_to_be32(s->st_ctime); - unlock_user(p, addr, sizeof(struct newlib_stat)); - - return 1; -} - -bool lm32_cpu_do_semihosting(CPUState *cs) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - - int ret = -1; - target_ulong nr, arg0, arg1, arg2; - void *p; - struct stat s; - - nr = env->regs[R_R8]; - arg0 = env->regs[R_R1]; - arg1 = env->regs[R_R2]; - arg2 = env->regs[R_R3]; - - switch (nr) { - case TARGET_SYS_exit: - /* void _exit(int rc) */ - exit(arg0); - - case TARGET_SYS_open: - /* int open(const char *pathname, int flags) */ - p = lock_user_string(arg0); - if (!p) { - ret = -1; - } else { - ret = open(p, translate_openflags(arg2)); - unlock_user(p, arg0, 0); - } - break; - - case TARGET_SYS_read: - /* ssize_t read(int fd, const void *buf, size_t count) */ - p = lock_user(VERIFY_WRITE, arg1, arg2, 0); - if (!p) { - ret = -1; - } else { - ret = read(arg0, p, arg2); - unlock_user(p, arg1, arg2); - } - break; - - case TARGET_SYS_write: - /* ssize_t write(int fd, const void *buf, size_t count) */ - p = lock_user(VERIFY_READ, arg1, arg2, 1); - if (!p) { - ret = -1; - } else { - ret = write(arg0, p, arg2); - unlock_user(p, arg1, 0); - } - break; - - case TARGET_SYS_close: - /* int close(int fd) */ - /* don't close stdin/stdout/stderr */ - if (arg0 > 2) { - ret = close(arg0); - } else { - ret = 0; - } - break; - - case TARGET_SYS_lseek: - /* off_t lseek(int fd, off_t offset, int whence */ - ret = lseek(arg0, arg1, arg2); - break; - - case TARGET_SYS_stat: - /* int stat(const char *path, struct stat *buf) */ - p = lock_user_string(arg0); - if (!p) { - ret = -1; - } else { - ret = stat(p, &s); - unlock_user(p, arg0, 0); - if (translate_stat(env, arg1, &s) == 0) { - ret = -1; - } - } - break; - - case TARGET_SYS_fstat: - /* int stat(int fd, struct stat *buf) */ - ret = fstat(arg0, &s); - if (ret == 0) { - if (translate_stat(env, arg1, &s) == 0) { - ret = -1; - } - } - break; - - default: - /* unhandled */ - return false; - } - - env->regs[R_R1] = ret; - return true; -} diff --git a/target/lm32/machine.c b/target/lm32/machine.c deleted file mode 100644 index 365eaa2e47..0000000000 --- a/target/lm32/machine.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "qemu/osdep.h" -#include "cpu.h" -#include "migration/cpu.h" - -static const VMStateDescription vmstate_env = { - .name = "env", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, CPULM32State, 32), - VMSTATE_UINT32(pc, CPULM32State), - VMSTATE_UINT32(ie, CPULM32State), - VMSTATE_UINT32(icc, CPULM32State), - VMSTATE_UINT32(dcc, CPULM32State), - VMSTATE_UINT32(cc, CPULM32State), - VMSTATE_UINT32(eba, CPULM32State), - VMSTATE_UINT32(dc, CPULM32State), - VMSTATE_UINT32(deba, CPULM32State), - VMSTATE_UINT32_ARRAY(bp, CPULM32State, 4), - VMSTATE_UINT32_ARRAY(wp, CPULM32State, 4), - VMSTATE_END_OF_LIST() - } -}; - -const VMStateDescription vmstate_lm32_cpu = { - .name = "cpu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_STRUCT(env, LM32CPU, 1, vmstate_env, CPULM32State), - VMSTATE_END_OF_LIST() - } -}; diff --git a/target/lm32/meson.build b/target/lm32/meson.build deleted file mode 100644 index ef0eef07f1..0000000000 --- a/target/lm32/meson.build +++ /dev/null @@ -1,15 +0,0 @@ -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/op_helper.c b/target/lm32/op_helper.c deleted file mode 100644 index e39fcd5647..0000000000 --- a/target/lm32/op_helper.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "qemu/host-utils.h" -#include "qemu/main-loop.h" -#include "sysemu/runstate.h" - -#include "hw/lm32/lm32_pic.h" -#include "hw/char/lm32_juart.h" - -#include "exec/exec-all.h" -#include "exec/cpu_ldst.h" - -#ifndef CONFIG_USER_ONLY -#endif - -#if !defined(CONFIG_USER_ONLY) -void raise_exception(CPULM32State *env, int index) -{ - CPUState *cs = env_cpu(env); - - cs->exception_index = index; - cpu_loop_exit(cs); -} - -void HELPER(raise_exception)(CPULM32State *env, uint32_t index) -{ - raise_exception(env, index); -} - -void HELPER(hlt)(CPULM32State *env) -{ - CPUState *cs = env_cpu(env); - - cs->halted = 1; - cs->exception_index = EXCP_HLT; - cpu_loop_exit(cs); -} - -void HELPER(ill)(CPULM32State *env) -{ -#ifndef CONFIG_USER_ONLY - CPUState *cs = env_cpu(env); - fprintf(stderr, "VM paused due to illegal instruction. " - "Connect a debugger or switch to the monitor console " - "to find out more.\n"); - vm_stop(RUN_STATE_PAUSED); - cs->halted = 1; - raise_exception(env, EXCP_HALTED); -#endif -} - -void HELPER(wcsr_bp)(CPULM32State *env, uint32_t bp, uint32_t idx) -{ - uint32_t addr = bp & ~1; - - assert(idx < 4); - - env->bp[idx] = bp; - lm32_breakpoint_remove(env, idx); - if (bp & 1) { - lm32_breakpoint_insert(env, idx, addr); - } -} - -void HELPER(wcsr_wp)(CPULM32State *env, uint32_t wp, uint32_t idx) -{ - lm32_wp_t wp_type; - - assert(idx < 4); - - env->wp[idx] = wp; - - wp_type = lm32_wp_type(env->dc, idx); - lm32_watchpoint_remove(env, idx); - if (wp_type != LM32_WP_DISABLED) { - lm32_watchpoint_insert(env, idx, wp, wp_type); - } -} - -void HELPER(wcsr_dc)(CPULM32State *env, uint32_t dc) -{ - uint32_t old_dc; - int i; - lm32_wp_t old_type; - lm32_wp_t new_type; - - old_dc = env->dc; - env->dc = dc; - - for (i = 0; i < 4; i++) { - old_type = lm32_wp_type(old_dc, i); - new_type = lm32_wp_type(dc, i); - - if (old_type != new_type) { - lm32_watchpoint_remove(env, i); - if (new_type != LM32_WP_DISABLED) { - lm32_watchpoint_insert(env, i, env->wp[i], new_type); - } - } - } -} - -void HELPER(wcsr_im)(CPULM32State *env, uint32_t im) -{ - qemu_mutex_lock_iothread(); - lm32_pic_set_im(env->pic_state, im); - qemu_mutex_unlock_iothread(); -} - -void HELPER(wcsr_ip)(CPULM32State *env, uint32_t im) -{ - qemu_mutex_lock_iothread(); - lm32_pic_set_ip(env->pic_state, im); - qemu_mutex_unlock_iothread(); -} - -void HELPER(wcsr_jtx)(CPULM32State *env, uint32_t jtx) -{ - lm32_juart_set_jtx(env->juart_state, jtx); -} - -void HELPER(wcsr_jrx)(CPULM32State *env, uint32_t jrx) -{ - lm32_juart_set_jrx(env->juart_state, jrx); -} - -uint32_t HELPER(rcsr_im)(CPULM32State *env) -{ - return lm32_pic_get_im(env->pic_state); -} - -uint32_t HELPER(rcsr_ip)(CPULM32State *env) -{ - return lm32_pic_get_ip(env->pic_state); -} - -uint32_t HELPER(rcsr_jtx)(CPULM32State *env) -{ - return lm32_juart_get_jtx(env->juart_state); -} - -uint32_t HELPER(rcsr_jrx)(CPULM32State *env) -{ - return lm32_juart_get_jrx(env->juart_state); -} -#endif - diff --git a/target/lm32/translate.c b/target/lm32/translate.c deleted file mode 100644 index 20c70d03f1..0000000000 --- a/target/lm32/translate.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * LatticeMico32 main translation routines. - * - * Copyright (c) 2010 Michael Walle <michael@walle.cc> - * - * This library is free software; you can redistribute it 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 <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "disas/disas.h" -#include "exec/helper-proto.h" -#include "exec/exec-all.h" -#include "exec/translator.h" -#include "tcg/tcg-op.h" -#include "qemu/qemu-print.h" - -#include "exec/cpu_ldst.h" -#include "hw/lm32/lm32_pic.h" - -#include "exec/helper-gen.h" - -#include "trace-tcg.h" -#include "exec/log.h" - - -#define DISAS_LM32 0 - -#define LOG_DIS(...) \ - do { \ - if (DISAS_LM32) { \ - qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ - } \ - } while (0) - -#define EXTRACT_FIELD(src, start, end) \ - (((src) >> start) & ((1 << (end - start + 1)) - 1)) - -#define MEM_INDEX 0 - -/* 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 */ - -static TCGv cpu_R[32]; -static TCGv cpu_pc; -static TCGv cpu_ie; -static TCGv cpu_icc; -static TCGv cpu_dcc; -static TCGv cpu_cc; -static TCGv cpu_cfg; -static TCGv cpu_eba; -static TCGv cpu_dc; -static TCGv cpu_deba; -static TCGv cpu_bp[4]; -static TCGv cpu_wp[4]; - -#include "exec/gen-icount.h" - -enum { - OP_FMT_RI, - OP_FMT_RR, - OP_FMT_CR, - OP_FMT_I -}; - -/* This is the state at translation time. */ -typedef struct DisasContext { - target_ulong pc; - - /* Decoder. */ - int format; - uint32_t ir; - uint8_t opcode; - uint8_t r0, r1, r2, csr; - uint16_t imm5; - uint16_t imm16; - uint32_t imm26; - - unsigned int delayed_branch; - unsigned int tb_flags, synced_flags; /* tb dependent flags. */ - int is_jmp; - - TranslationBlock *tb; - int singlestep_enabled; - - uint32_t features; - uint8_t num_breakpoints; - uint8_t num_watchpoints; -} DisasContext; - -static const char *regnames[] = { - "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/gp", "r27/fp", "r28/sp", "r29/ra", - "r30/ea", "r31/ba", "bp0", "bp1", "bp2", "bp3", "wp0", - "wp1", "wp2", "wp3" -}; - -static inline int zero_extend(unsigned int val, int width) -{ - return val & ((1 << width) - 1); -} - -static inline int sign_extend(unsigned int val, int width) -{ - int sval; - - /* LSL. */ - val <<= 32 - width; - sval = val; - /* ASR. */ - sval >>= 32 - width; - - return sval; -} - -static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) -{ - TCGv_i32 tmp = tcg_const_i32(index); - - gen_helper_raise_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); -} - -static inline void t_gen_illegal_insn(DisasContext *dc) -{ - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_helper_ill(cpu_env); -} - -static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) -{ - if (unlikely(dc->singlestep_enabled)) { - return false; - } - -#ifndef CONFIG_USER_ONLY - return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); -#else - return true; -#endif -} - -static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) -{ - if (use_goto_tb(dc, dest)) { - tcg_gen_goto_tb(n); - tcg_gen_movi_tl(cpu_pc, dest); - tcg_gen_exit_tb(dc->tb, n); - } else { - tcg_gen_movi_tl(cpu_pc, dest); - if (dc->singlestep_enabled) { - t_gen_raise_exception(dc, EXCP_DEBUG); - } - tcg_gen_exit_tb(NULL, 0); - } -} - -static void dec_add(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - if (dc->r0 == R_R0) { - if (dc->r1 == R_R0 && dc->imm16 == 0) { - LOG_DIS("nop\n"); - } else { - LOG_DIS("mvi r%d, %d\n", dc->r1, sign_extend(dc->imm16, 16)); - } - } else { - LOG_DIS("addi r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16)); - } - } else { - LOG_DIS("add r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_addi_tl(cpu_R[dc->r1], cpu_R[dc->r0], - sign_extend(dc->imm16, 16)); - } else { - tcg_gen_add_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_and(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("andi r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - LOG_DIS("and r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], - zero_extend(dc->imm16, 16)); - } else { - if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) { - tcg_gen_movi_tl(cpu_pc, dc->pc + 4); - gen_helper_hlt(cpu_env); - } else { - tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } - } -} - -static void dec_andhi(DisasContext *dc) -{ - LOG_DIS("andhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16); - - tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16)); -} - -static void dec_b(DisasContext *dc) -{ - if (dc->r0 == R_RA) { - LOG_DIS("ret\n"); - } else if (dc->r0 == R_EA) { - LOG_DIS("eret\n"); - } else if (dc->r0 == R_BA) { - LOG_DIS("bret\n"); - } else { - LOG_DIS("b r%d\n", dc->r0); - } - - /* restore IE.IE in case of an eret */ - if (dc->r0 == R_EA) { - TCGv t0 = tcg_temp_new(); - TCGLabel *l1 = gen_new_label(); - tcg_gen_andi_tl(t0, cpu_ie, IE_EIE); - tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE); - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_EIE, l1); - tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE); - gen_set_label(l1); - tcg_temp_free(t0); - } else if (dc->r0 == R_BA) { - TCGv t0 = tcg_temp_new(); - TCGLabel *l1 = gen_new_label(); - tcg_gen_andi_tl(t0, cpu_ie, IE_BIE); - tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE); - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_BIE, l1); - tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE); - gen_set_label(l1); - tcg_temp_free(t0); - } - tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]); - - dc->is_jmp = DISAS_JUMP; -} - -static void dec_bi(DisasContext *dc) -{ - LOG_DIS("bi %d\n", sign_extend(dc->imm26 << 2, 26)); - - gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26))); - - dc->is_jmp = DISAS_TB_JUMP; -} - -static inline void gen_cond_branch(DisasContext *dc, int cond) -{ - TCGLabel *l1 = gen_new_label(); - tcg_gen_brcond_tl(cond, cpu_R[dc->r0], cpu_R[dc->r1], l1); - gen_goto_tb(dc, 0, dc->pc + 4); - gen_set_label(l1); - gen_goto_tb(dc, 1, dc->pc + (sign_extend(dc->imm16 << 2, 16))); - dc->is_jmp = DISAS_TB_JUMP; -} - -static void dec_be(DisasContext *dc) -{ - LOG_DIS("be r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16) * 4); - - gen_cond_branch(dc, TCG_COND_EQ); -} - -static void dec_bg(DisasContext *dc) -{ - LOG_DIS("bg r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16 * 4)); - - gen_cond_branch(dc, TCG_COND_GT); -} - -static void dec_bge(DisasContext *dc) -{ - LOG_DIS("bge r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16) * 4); - - gen_cond_branch(dc, TCG_COND_GE); -} - -static void dec_bgeu(DisasContext *dc) -{ - LOG_DIS("bgeu r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16) * 4); - - gen_cond_branch(dc, TCG_COND_GEU); -} - -static void dec_bgu(DisasContext *dc) -{ - LOG_DIS("bgu r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16) * 4); - - gen_cond_branch(dc, TCG_COND_GTU); -} - -static void dec_bne(DisasContext *dc) -{ - LOG_DIS("bne r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16) * 4); - - gen_cond_branch(dc, TCG_COND_NE); -} - -static void dec_call(DisasContext *dc) -{ - LOG_DIS("call r%d\n", dc->r0); - - tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4); - tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]); - - dc->is_jmp = DISAS_JUMP; -} - -static void dec_calli(DisasContext *dc) -{ - LOG_DIS("calli %d\n", sign_extend(dc->imm26, 26) * 4); - - tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4); - gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26))); - - dc->is_jmp = DISAS_TB_JUMP; -} - -static inline void gen_compare(DisasContext *dc, int cond) -{ - int i; - - if (dc->format == OP_FMT_RI) { - switch (cond) { - case TCG_COND_GEU: - case TCG_COND_GTU: - i = zero_extend(dc->imm16, 16); - break; - default: - i = sign_extend(dc->imm16, 16); - break; - } - - tcg_gen_setcondi_tl(cond, cpu_R[dc->r1], cpu_R[dc->r0], i); - } else { - tcg_gen_setcond_tl(cond, cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_cmpe(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("cmpei r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16)); - } else { - LOG_DIS("cmpe r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - gen_compare(dc, TCG_COND_EQ); -} - -static void dec_cmpg(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("cmpgi r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16)); - } else { - LOG_DIS("cmpg r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - gen_compare(dc, TCG_COND_GT); -} - -static void dec_cmpge(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("cmpgei r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16)); - } else { - LOG_DIS("cmpge r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - gen_compare(dc, TCG_COND_GE); -} - -static void dec_cmpgeu(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("cmpgeui r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - LOG_DIS("cmpgeu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - gen_compare(dc, TCG_COND_GEU); -} - -static void dec_cmpgu(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("cmpgui r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - LOG_DIS("cmpgu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - gen_compare(dc, TCG_COND_GTU); -} - -static void dec_cmpne(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("cmpnei r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16)); - } else { - LOG_DIS("cmpne r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - gen_compare(dc, TCG_COND_NE); -} - -static void dec_divu(DisasContext *dc) -{ - TCGLabel *l1; - - LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - - if (!(dc->features & LM32_FEATURE_DIVIDE)) { - qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n"); - t_gen_illegal_insn(dc); - return; - } - - l1 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1); - tcg_gen_movi_tl(cpu_pc, dc->pc); - t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO); - gen_set_label(l1); - tcg_gen_divu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); -} - -static void dec_lb(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("lb r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_ld8s(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_lbu(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("lbu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_ld8u(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_lh(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("lh r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_ld16s(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_lhu(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("lhu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_ld16u(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_lw(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("lw r%d, (r%d+%d)\n", dc->r1, dc->r0, sign_extend(dc->imm16, 16)); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_ld32s(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_modu(DisasContext *dc) -{ - TCGLabel *l1; - - LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1); - - if (!(dc->features & LM32_FEATURE_DIVIDE)) { - qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n"); - t_gen_illegal_insn(dc); - return; - } - - l1 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1); - tcg_gen_movi_tl(cpu_pc, dc->pc); - t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO); - gen_set_label(l1); - tcg_gen_remu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); -} - -static void dec_mul(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("muli r%d, r%d, %d\n", dc->r1, dc->r0, - sign_extend(dc->imm16, 16)); - } else { - LOG_DIS("mul r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (!(dc->features & LM32_FEATURE_MULTIPLY)) { - qemu_log_mask(LOG_GUEST_ERROR, - "hardware multiplier is not available\n"); - t_gen_illegal_insn(dc); - return; - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_muli_tl(cpu_R[dc->r1], cpu_R[dc->r0], - sign_extend(dc->imm16, 16)); - } else { - tcg_gen_mul_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_nor(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("nori r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - LOG_DIS("nor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (dc->format == OP_FMT_RI) { - TCGv t0 = tcg_temp_new(); - tcg_gen_movi_tl(t0, zero_extend(dc->imm16, 16)); - tcg_gen_nor_tl(cpu_R[dc->r1], cpu_R[dc->r0], t0); - tcg_temp_free(t0); - } else { - tcg_gen_nor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_or(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("ori r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - if (dc->r1 == R_R0) { - LOG_DIS("mv r%d, r%d\n", dc->r2, dc->r0); - } else { - LOG_DIS("or r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], - zero_extend(dc->imm16, 16)); - } else { - tcg_gen_or_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_orhi(DisasContext *dc) -{ - if (dc->r0 == R_R0) { - LOG_DIS("mvhi r%d, %d\n", dc->r1, dc->imm16); - } else { - LOG_DIS("orhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16); - } - - tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16)); -} - -static void dec_scall(DisasContext *dc) -{ - switch (dc->imm5) { - case 2: - LOG_DIS("break\n"); - tcg_gen_movi_tl(cpu_pc, dc->pc); - t_gen_raise_exception(dc, EXCP_BREAKPOINT); - break; - case 7: - LOG_DIS("scall\n"); - tcg_gen_movi_tl(cpu_pc, dc->pc); - t_gen_raise_exception(dc, EXCP_SYSTEMCALL); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "invalid opcode @0x%x", dc->pc); - t_gen_illegal_insn(dc); - break; - } -} - -static void dec_rcsr(DisasContext *dc) -{ - LOG_DIS("rcsr r%d, %d\n", dc->r2, dc->csr); - - switch (dc->csr) { - case CSR_IE: - tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie); - break; - case CSR_IM: - gen_helper_rcsr_im(cpu_R[dc->r2], cpu_env); - break; - case CSR_IP: - gen_helper_rcsr_ip(cpu_R[dc->r2], cpu_env); - break; - case CSR_CC: - tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc); - break; - case CSR_CFG: - tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cfg); - break; - case CSR_EBA: - tcg_gen_mov_tl(cpu_R[dc->r2], cpu_eba); - break; - case CSR_DC: - tcg_gen_mov_tl(cpu_R[dc->r2], cpu_dc); - break; - case CSR_DEBA: - tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba); - break; - case CSR_JTX: - gen_helper_rcsr_jtx(cpu_R[dc->r2], cpu_env); - break; - case CSR_JRX: - gen_helper_rcsr_jrx(cpu_R[dc->r2], cpu_env); - break; - case CSR_ICC: - case CSR_DCC: - case CSR_BP0: - case CSR_BP1: - case CSR_BP2: - case CSR_BP3: - case CSR_WP0: - case CSR_WP1: - case CSR_WP2: - case CSR_WP3: - qemu_log_mask(LOG_GUEST_ERROR, "invalid read access csr=%x\n", dc->csr); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "read_csr: unknown csr=%x\n", dc->csr); - break; - } -} - -static void dec_sb(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("sb (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_st8(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_sextb(DisasContext *dc) -{ - LOG_DIS("sextb r%d, r%d\n", dc->r2, dc->r0); - - if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) { - qemu_log_mask(LOG_GUEST_ERROR, - "hardware sign extender is not available\n"); - t_gen_illegal_insn(dc); - return; - } - - tcg_gen_ext8s_tl(cpu_R[dc->r2], cpu_R[dc->r0]); -} - -static void dec_sexth(DisasContext *dc) -{ - LOG_DIS("sexth r%d, r%d\n", dc->r2, dc->r0); - - if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) { - qemu_log_mask(LOG_GUEST_ERROR, - "hardware sign extender is not available\n"); - t_gen_illegal_insn(dc); - return; - } - - tcg_gen_ext16s_tl(cpu_R[dc->r2], cpu_R[dc->r0]); -} - -static void dec_sh(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("sh (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_st16(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_sl(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("sli r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5); - } else { - LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (!(dc->features & LM32_FEATURE_SHIFT)) { - qemu_log_mask(LOG_GUEST_ERROR, "hardware shifter is not available\n"); - t_gen_illegal_insn(dc); - return; - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_shli_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5); - } else { - TCGv t0 = tcg_temp_new(); - tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f); - tcg_gen_shl_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0); - tcg_temp_free(t0); - } -} - -static void dec_sr(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("sri r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5); - } else { - LOG_DIS("sr r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - /* The real CPU (w/o hardware shifter) only supports right shift by exactly - * one bit */ - if (dc->format == OP_FMT_RI) { - if (!(dc->features & LM32_FEATURE_SHIFT) && (dc->imm5 != 1)) { - qemu_log_mask(LOG_GUEST_ERROR, - "hardware shifter is not available\n"); - t_gen_illegal_insn(dc); - return; - } - tcg_gen_sari_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5); - } else { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - TCGv t0 = tcg_temp_local_new(); - tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f); - - if (!(dc->features & LM32_FEATURE_SHIFT)) { - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 1, l1); - t_gen_illegal_insn(dc); - tcg_gen_br(l2); - } - - gen_set_label(l1); - tcg_gen_sar_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0); - gen_set_label(l2); - - tcg_temp_free(t0); - } -} - -static void dec_sru(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("srui r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5); - } else { - LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (dc->format == OP_FMT_RI) { - if (!(dc->features & LM32_FEATURE_SHIFT) && (dc->imm5 != 1)) { - qemu_log_mask(LOG_GUEST_ERROR, - "hardware shifter is not available\n"); - t_gen_illegal_insn(dc); - return; - } - tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5); - } else { - TCGLabel *l1 = gen_new_label(); - TCGLabel *l2 = gen_new_label(); - TCGv t0 = tcg_temp_local_new(); - tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f); - - if (!(dc->features & LM32_FEATURE_SHIFT)) { - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 1, l1); - t_gen_illegal_insn(dc); - tcg_gen_br(l2); - } - - gen_set_label(l1); - tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0); - gen_set_label(l2); - - tcg_temp_free(t0); - } -} - -static void dec_sub(DisasContext *dc) -{ - LOG_DIS("sub r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - - tcg_gen_sub_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); -} - -static void dec_sw(DisasContext *dc) -{ - TCGv t0; - - LOG_DIS("sw (r%d+%d), r%d\n", dc->r0, sign_extend(dc->imm16, 16), dc->r1); - - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); - tcg_gen_qemu_st32(cpu_R[dc->r1], t0, MEM_INDEX); - tcg_temp_free(t0); -} - -static void dec_user(DisasContext *dc) -{ - LOG_DIS("user"); - - qemu_log_mask(LOG_GUEST_ERROR, "user instruction undefined\n"); - t_gen_illegal_insn(dc); -} - -static void dec_wcsr(DisasContext *dc) -{ - int no; - - LOG_DIS("wcsr %d, r%d\n", dc->csr, dc->r1); - - switch (dc->csr) { - case CSR_IE: - tcg_gen_mov_tl(cpu_ie, cpu_R[dc->r1]); - tcg_gen_movi_tl(cpu_pc, dc->pc + 4); - dc->is_jmp = DISAS_UPDATE; - break; - case CSR_IM: - /* mark as an io operation because it could cause an interrupt */ - if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { - gen_io_start(); - } - gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]); - tcg_gen_movi_tl(cpu_pc, dc->pc + 4); - dc->is_jmp = DISAS_UPDATE; - break; - case CSR_IP: - /* mark as an io operation because it could cause an interrupt */ - if (tb_cflags(dc->tb) & CF_USE_ICOUNT) { - gen_io_start(); - } - gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]); - tcg_gen_movi_tl(cpu_pc, dc->pc + 4); - dc->is_jmp = DISAS_UPDATE; - break; - case CSR_ICC: - /* TODO */ - break; - case CSR_DCC: - /* TODO */ - break; - case CSR_EBA: - tcg_gen_mov_tl(cpu_eba, cpu_R[dc->r1]); - break; - case CSR_DEBA: - tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]); - break; - case CSR_JTX: - gen_helper_wcsr_jtx(cpu_env, cpu_R[dc->r1]); - break; - case CSR_JRX: - gen_helper_wcsr_jrx(cpu_env, cpu_R[dc->r1]); - break; - case CSR_DC: - gen_helper_wcsr_dc(cpu_env, cpu_R[dc->r1]); - break; - case CSR_BP0: - case CSR_BP1: - case CSR_BP2: - case CSR_BP3: - no = dc->csr - CSR_BP0; - if (dc->num_breakpoints <= no) { - qemu_log_mask(LOG_GUEST_ERROR, - "breakpoint #%i is not available\n", no); - t_gen_illegal_insn(dc); - break; - } - gen_helper_wcsr_bp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no)); - break; - case CSR_WP0: - case CSR_WP1: - case CSR_WP2: - case CSR_WP3: - no = dc->csr - CSR_WP0; - if (dc->num_watchpoints <= no) { - qemu_log_mask(LOG_GUEST_ERROR, - "watchpoint #%i is not available\n", no); - t_gen_illegal_insn(dc); - break; - } - gen_helper_wcsr_wp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no)); - break; - case CSR_CC: - case CSR_CFG: - qemu_log_mask(LOG_GUEST_ERROR, "invalid write access csr=%x\n", - dc->csr); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "write_csr: unknown csr=%x\n", - dc->csr); - break; - } -} - -static void dec_xnor(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("xnori r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - if (dc->r1 == R_R0) { - LOG_DIS("not r%d, r%d\n", dc->r2, dc->r0); - } else { - LOG_DIS("xnor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0], - zero_extend(dc->imm16, 16)); - tcg_gen_not_tl(cpu_R[dc->r1], cpu_R[dc->r1]); - } else { - tcg_gen_eqv_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_xor(DisasContext *dc) -{ - if (dc->format == OP_FMT_RI) { - LOG_DIS("xori r%d, r%d, %d\n", dc->r1, dc->r0, - zero_extend(dc->imm16, 16)); - } else { - LOG_DIS("xor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); - } - - if (dc->format == OP_FMT_RI) { - tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0], - zero_extend(dc->imm16, 16)); - } else { - tcg_gen_xor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); - } -} - -static void dec_ill(DisasContext *dc) -{ - qemu_log_mask(LOG_GUEST_ERROR, "invalid opcode 0x%02x\n", dc->opcode); - t_gen_illegal_insn(dc); -} - -typedef void (*DecoderInfo)(DisasContext *dc); -static const DecoderInfo decinfo[] = { - dec_sru, dec_nor, dec_mul, dec_sh, dec_lb, dec_sr, dec_xor, dec_lh, - dec_and, dec_xnor, dec_lw, dec_lhu, dec_sb, dec_add, dec_or, dec_sl, - dec_lbu, dec_be, dec_bg, dec_bge, dec_bgeu, dec_bgu, dec_sw, dec_bne, - dec_andhi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_orhi, - dec_cmpne, - dec_sru, dec_nor, dec_mul, dec_divu, dec_rcsr, dec_sr, dec_xor, dec_ill, - dec_and, dec_xnor, dec_ill, dec_scall, dec_sextb, dec_add, dec_or, dec_sl, - dec_b, dec_modu, dec_sub, dec_user, dec_wcsr, dec_ill, dec_call, dec_sexth, - dec_bi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_calli, - dec_cmpne -}; - -static inline void decode(DisasContext *dc, uint32_t ir) -{ - dc->ir = ir; - LOG_DIS("%8.8x\t", dc->ir); - - dc->opcode = EXTRACT_FIELD(ir, 26, 31); - - dc->imm5 = EXTRACT_FIELD(ir, 0, 4); - dc->imm16 = EXTRACT_FIELD(ir, 0, 15); - dc->imm26 = EXTRACT_FIELD(ir, 0, 25); - - dc->csr = EXTRACT_FIELD(ir, 21, 25); - dc->r0 = EXTRACT_FIELD(ir, 21, 25); - dc->r1 = EXTRACT_FIELD(ir, 16, 20); - dc->r2 = EXTRACT_FIELD(ir, 11, 15); - - /* bit 31 seems to indicate insn type. */ - if (ir & (1 << 31)) { - dc->format = OP_FMT_RR; - } else { - dc->format = OP_FMT_RI; - } - - assert(ARRAY_SIZE(decinfo) == 64); - assert(dc->opcode < 64); - - decinfo[dc->opcode](dc); -} - -/* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) -{ - CPULM32State *env = cs->env_ptr; - LM32CPU *cpu = env_archcpu(env); - struct DisasContext ctx, *dc = &ctx; - uint32_t pc_start; - uint32_t page_start; - int num_insns; - - pc_start = tb->pc; - dc->features = cpu->features; - dc->num_breakpoints = cpu->num_breakpoints; - dc->num_watchpoints = cpu->num_watchpoints; - dc->tb = tb; - - dc->is_jmp = DISAS_NEXT; - dc->pc = pc_start; - dc->singlestep_enabled = cs->singlestep_enabled; - - if (pc_start & 3) { - qemu_log_mask(LOG_GUEST_ERROR, - "unaligned PC=%x. Ignoring lowest bits.\n", pc_start); - pc_start &= ~3; - } - - page_start = pc_start & TARGET_PAGE_MASK; - num_insns = 0; - - gen_tb_start(tb); - do { - tcg_gen_insn_start(dc->pc); - num_insns++; - - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - 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; - } - - /* Pretty disas. */ - LOG_DIS("%8.8x:\t", dc->pc); - - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } - - decode(dc, cpu_ldl_code(env, dc->pc)); - dc->pc += 4; - } while (!dc->is_jmp - && !tcg_op_buf_full() - && !cs->singlestep_enabled - && !singlestep - && (dc->pc - page_start < TARGET_PAGE_SIZE) - && num_insns < max_insns); - - - if (unlikely(cs->singlestep_enabled)) { - if (dc->is_jmp == DISAS_NEXT) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - } - t_gen_raise_exception(dc, EXCP_DEBUG); - } else { - switch (dc->is_jmp) { - case DISAS_NEXT: - gen_goto_tb(dc, 1, dc->pc); - 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; - } - } - - gen_tb_end(tb, num_insns); - - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - -#ifdef DEBUG_DISAS - 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); - } -#endif -} - -void lm32_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ - LM32CPU *cpu = LM32_CPU(cs); - CPULM32State *env = &cpu->env; - int i; - - if (!env) { - return; - } - - qemu_fprintf(f, "IN: PC=%x %s\n", - env->pc, lookup_symbol(env->pc)); - - qemu_fprintf(f, "ie=%8.8x (IE=%x EIE=%x BIE=%x) im=%8.8x ip=%8.8x\n", - env->ie, - (env->ie & IE_IE) ? 1 : 0, - (env->ie & IE_EIE) ? 1 : 0, - (env->ie & IE_BIE) ? 1 : 0, - lm32_pic_get_im(env->pic_state), - lm32_pic_get_ip(env->pic_state)); - qemu_fprintf(f, "eba=%8.8x deba=%8.8x\n", - env->eba, - env->deba); - - 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"); -} - -void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, - target_ulong *data) -{ - env->pc = data[0]; -} - -void lm32_translate_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { - cpu_R[i] = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, regs[i]), - regnames[i]); - } - - for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) { - cpu_bp[i] = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, bp[i]), - regnames[32+i]); - } - - for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) { - cpu_wp[i] = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, wp[i]), - regnames[36+i]); - } - - cpu_pc = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, pc), - "pc"); - cpu_ie = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, ie), - "ie"); - cpu_icc = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, icc), - "icc"); - cpu_dcc = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, dcc), - "dcc"); - cpu_cc = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, cc), - "cc"); - cpu_cfg = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, cfg), - "cfg"); - cpu_eba = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, eba), - "eba"); - cpu_dc = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, dc), - "dc"); - cpu_deba = tcg_global_mem_new(cpu_env, - offsetof(CPULM32State, deba), - "deba"); -} - diff --git a/target/meson.build b/target/meson.build index 0e2c4b69cb..2f6940255e 100644 --- a/target/meson.build +++ b/target/meson.build @@ -5,11 +5,9 @@ subdir('cris') subdir('hexagon') subdir('hppa') subdir('i386') -subdir('lm32') subdir('m68k') subdir('microblaze') subdir('mips') -subdir('moxie') subdir('nios2') subdir('openrisc') subdir('ppc') @@ -19,5 +17,4 @@ subdir('s390x') subdir('sh4') subdir('sparc') subdir('tricore') -subdir('unicore32') subdir('xtensa') diff --git a/target/moxie/cpu-param.h b/target/moxie/cpu-param.h deleted file mode 100644 index 9a40ef525c..0000000000 --- a/target/moxie/cpu-param.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Moxie cpu parameters for qemu. - * - * Copyright (c) 2008, 2010, 2013 Anthony Green - * SPDX-License-Identifier: LGPL-2.1+ - */ - -#ifndef MOXIE_CPU_PARAM_H -#define MOXIE_CPU_PARAM_H 1 - -#define TARGET_LONG_BITS 32 -#define TARGET_PAGE_BITS 12 /* 4k */ -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define NB_MMU_MODES 1 - -#endif diff --git a/target/moxie/cpu.c b/target/moxie/cpu.c deleted file mode 100644 index 83bec34d36..0000000000 --- a/target/moxie/cpu.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * QEMU Moxie CPU - * - * Copyright (c) 2013 Anthony Green - * - * This library is free software; you can redistribute it 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 program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "cpu.h" -#include "migration/vmstate.h" -#include "machine.h" - -static void moxie_cpu_set_pc(CPUState *cs, vaddr value) -{ - MoxieCPU *cpu = MOXIE_CPU(cs); - - cpu->env.pc = value; -} - -static bool moxie_cpu_has_work(CPUState *cs) -{ - return cs->interrupt_request & CPU_INTERRUPT_HARD; -} - -static void moxie_cpu_reset(DeviceState *dev) -{ - CPUState *s = CPU(dev); - MoxieCPU *cpu = MOXIE_CPU(s); - MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu); - CPUMoxieState *env = &cpu->env; - - mcc->parent_reset(dev); - - memset(env, 0, offsetof(CPUMoxieState, end_reset_fields)); - env->pc = 0x1000; -} - -static void moxie_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) -{ - info->mach = bfd_arch_moxie; - info->print_insn = print_insn_moxie; -} - -static void moxie_cpu_realizefn(DeviceState *dev, Error **errp) -{ - CPUState *cs = CPU(dev); - MoxieCPUClass *mcc = MOXIE_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 moxie_cpu_initfn(Object *obj) -{ - MoxieCPU *cpu = MOXIE_CPU(obj); - - cpu_set_cpustate_pointers(cpu); -} - -static ObjectClass *moxie_cpu_class_by_name(const char *cpu_model) -{ - ObjectClass *oc; - char *typename; - - typename = g_strdup_printf(MOXIE_CPU_TYPE_NAME("%s"), cpu_model); - oc = object_class_by_name(typename); - g_free(typename); - if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_MOXIE_CPU) || - object_class_is_abstract(oc))) { - return NULL; - } - return oc; -} - -#include "hw/core/tcg-cpu-ops.h" - -static struct TCGCPUOps moxie_tcg_ops = { - .initialize = moxie_translate_init, - .tlb_fill = moxie_cpu_tlb_fill, - -#ifndef CONFIG_USER_ONLY - .do_interrupt = moxie_cpu_do_interrupt, -#endif /* !CONFIG_USER_ONLY */ -}; - -static void moxie_cpu_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - CPUClass *cc = CPU_CLASS(oc); - MoxieCPUClass *mcc = MOXIE_CPU_CLASS(oc); - - device_class_set_parent_realize(dc, moxie_cpu_realizefn, - &mcc->parent_realize); - device_class_set_parent_reset(dc, moxie_cpu_reset, &mcc->parent_reset); - - cc->class_by_name = moxie_cpu_class_by_name; - - cc->has_work = moxie_cpu_has_work; - cc->dump_state = moxie_cpu_dump_state; - cc->set_pc = moxie_cpu_set_pc; -#ifndef CONFIG_USER_ONLY - cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug; - cc->vmsd = &vmstate_moxie_cpu; -#endif - cc->disas_set_info = moxie_cpu_disas_set_info; - cc->tcg_ops = &moxie_tcg_ops; -} - -static void moxielite_initfn(Object *obj) -{ - /* Set cpu feature flags */ -} - -static void moxie_any_initfn(Object *obj) -{ - /* Set cpu feature flags */ -} - -#define DEFINE_MOXIE_CPU_TYPE(cpu_model, initfn) \ - { \ - .parent = TYPE_MOXIE_CPU, \ - .instance_init = initfn, \ - .name = MOXIE_CPU_TYPE_NAME(cpu_model), \ - } - -static const TypeInfo moxie_cpus_type_infos[] = { - { /* base class should be registered first */ - .name = TYPE_MOXIE_CPU, - .parent = TYPE_CPU, - .instance_size = sizeof(MoxieCPU), - .instance_init = moxie_cpu_initfn, - .class_size = sizeof(MoxieCPUClass), - .class_init = moxie_cpu_class_init, - }, - DEFINE_MOXIE_CPU_TYPE("MoxieLite", moxielite_initfn), - DEFINE_MOXIE_CPU_TYPE("any", moxie_any_initfn), -}; - -DEFINE_TYPES(moxie_cpus_type_infos) diff --git a/target/moxie/cpu.h b/target/moxie/cpu.h deleted file mode 100644 index bd6ab66084..0000000000 --- a/target/moxie/cpu.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Moxie emulation - * - * Copyright (c) 2008, 2010, 2013 Anthony Green - * - * This library is free software; you can redistribute it 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 program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef MOXIE_CPU_H -#define MOXIE_CPU_H - -#include "exec/cpu-defs.h" -#include "qom/object.h" - -#define MOXIE_EX_DIV0 0 -#define MOXIE_EX_BAD 1 -#define MOXIE_EX_IRQ 2 -#define MOXIE_EX_SWI 3 -#define MOXIE_EX_MMU_MISS 4 -#define MOXIE_EX_BREAK 16 - -typedef struct CPUMoxieState { - - uint32_t flags; /* general execution flags */ - uint32_t gregs[16]; /* general registers */ - uint32_t sregs[256]; /* special registers */ - uint32_t pc; /* program counter */ - /* Instead of saving the cc value, we save the cmp arguments - and compute cc on demand. */ - uint32_t cc_a; /* reg a for condition code calculation */ - uint32_t cc_b; /* reg b for condition code calculation */ - - void *irq[8]; - - /* Fields up to this point are cleared by a CPU reset */ - struct {} end_reset_fields; -} CPUMoxieState; - -#include "hw/core/cpu.h" - -#define TYPE_MOXIE_CPU "moxie-cpu" - -OBJECT_DECLARE_TYPE(MoxieCPU, MoxieCPUClass, - MOXIE_CPU) - -/** - * MoxieCPUClass: - * @parent_reset: The parent class' reset handler. - * - * A Moxie CPU model. - */ -struct MoxieCPUClass { - /*< private >*/ - CPUClass parent_class; - /*< public >*/ - - DeviceRealize parent_realize; - DeviceReset parent_reset; -}; - -/** - * MoxieCPU: - * @env: #CPUMoxieState - * - * A Moxie CPU. - */ -struct MoxieCPU { - /*< private >*/ - CPUState parent_obj; - /*< public >*/ - - CPUNegativeOffsetState neg; - CPUMoxieState env; -}; - - -void moxie_cpu_do_interrupt(CPUState *cs); -void moxie_cpu_dump_state(CPUState *cpu, FILE *f, int flags); -hwaddr moxie_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -void moxie_translate_init(void); -int cpu_moxie_signal_handler(int host_signum, void *pinfo, - void *puc); - -#define MOXIE_CPU_TYPE_SUFFIX "-" TYPE_MOXIE_CPU -#define MOXIE_CPU_TYPE_NAME(model) model MOXIE_CPU_TYPE_SUFFIX -#define CPU_RESOLVING_TYPE TYPE_MOXIE_CPU - -#define cpu_signal_handler cpu_moxie_signal_handler - -static inline int cpu_mmu_index(CPUMoxieState *env, bool ifetch) -{ - return 0; -} - -typedef CPUMoxieState CPUArchState; -typedef MoxieCPU ArchCPU; - -#include "exec/cpu-all.h" - -static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) -{ - *pc = env->pc; - *cs_base = 0; - *flags = 0; -} - -bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr); - -#endif /* MOXIE_CPU_H */ diff --git a/target/moxie/helper.c b/target/moxie/helper.c deleted file mode 100644 index b1919f62b3..0000000000 --- a/target/moxie/helper.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Moxie helper routines. - * - * Copyright (c) 2008, 2009, 2010, 2013 Anthony Green - * - * This library is free software; you can redistribute it 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 program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" - -#include "cpu.h" -#include "mmu.h" -#include "exec/exec-all.h" -#include "exec/cpu_ldst.h" -#include "qemu/host-utils.h" -#include "exec/helper-proto.h" - -void helper_raise_exception(CPUMoxieState *env, int ex) -{ - CPUState *cs = env_cpu(env); - - cs->exception_index = ex; - /* Stash the exception type. */ - env->sregs[2] = ex; - /* Stash the address where the exception occurred. */ - cpu_restore_state(cs, GETPC(), true); - env->sregs[5] = env->pc; - /* Jump to the exception handline routine. */ - env->pc = env->sregs[1]; - cpu_loop_exit(cs); -} - -uint32_t helper_div(CPUMoxieState *env, uint32_t a, uint32_t b) -{ - if (unlikely(b == 0)) { - helper_raise_exception(env, MOXIE_EX_DIV0); - return 0; - } - if (unlikely(a == INT_MIN && b == -1)) { - return INT_MIN; - } - - return (int32_t)a / (int32_t)b; -} - -uint32_t helper_udiv(CPUMoxieState *env, uint32_t a, uint32_t b) -{ - if (unlikely(b == 0)) { - helper_raise_exception(env, MOXIE_EX_DIV0); - return 0; - } - return a / b; -} - -void helper_debug(CPUMoxieState *env) -{ - CPUState *cs = env_cpu(env); - - cs->exception_index = EXCP_DEBUG; - cpu_loop_exit(cs); -} - -bool moxie_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr) -{ - MoxieCPU *cpu = MOXIE_CPU(cs); - CPUMoxieState *env = &cpu->env; - MoxieMMUResult res; - int prot, miss; - - address &= TARGET_PAGE_MASK; - prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - miss = moxie_mmu_translate(&res, env, address, access_type, mmu_idx); - if (likely(!miss)) { - tlb_set_page(cs, address, res.phy, prot, mmu_idx, TARGET_PAGE_SIZE); - return true; - } - if (probe) { - return false; - } - - cs->exception_index = MOXIE_EX_MMU_MISS; - cpu_loop_exit_restore(cs, retaddr); -} - -void moxie_cpu_do_interrupt(CPUState *cs) -{ - switch (cs->exception_index) { - case MOXIE_EX_BREAK: - break; - default: - break; - } -} - -hwaddr moxie_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - MoxieCPU *cpu = MOXIE_CPU(cs); - uint32_t phy = addr; - MoxieMMUResult res; - int miss; - - miss = moxie_mmu_translate(&res, &cpu->env, addr, 0, 0); - if (!miss) { - phy = res.phy; - } - return phy; -} diff --git a/target/moxie/helper.h b/target/moxie/helper.h deleted file mode 100644 index d94ef7a17e..0000000000 --- a/target/moxie/helper.h +++ /dev/null @@ -1,5 +0,0 @@ -DEF_HELPER_2(raise_exception, void, env, int) -DEF_HELPER_1(debug, void, env) - -DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, i32, env, i32, i32) diff --git a/target/moxie/machine.c b/target/moxie/machine.c deleted file mode 100644 index d0f177048c..0000000000 --- a/target/moxie/machine.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "qemu/osdep.h" -#include "cpu.h" -#include "machine.h" -#include "migration/cpu.h" - -const VMStateDescription vmstate_moxie_cpu = { - .name = "cpu", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(flags, CPUMoxieState), - VMSTATE_UINT32_ARRAY(gregs, CPUMoxieState, 16), - VMSTATE_UINT32_ARRAY(sregs, CPUMoxieState, 256), - VMSTATE_UINT32(pc, CPUMoxieState), - VMSTATE_UINT32(cc_a, CPUMoxieState), - VMSTATE_UINT32(cc_b, CPUMoxieState), - VMSTATE_END_OF_LIST() - } -}; diff --git a/target/moxie/machine.h b/target/moxie/machine.h deleted file mode 100644 index a1b72907ae..0000000000 --- a/target/moxie/machine.h +++ /dev/null @@ -1 +0,0 @@ -extern const VMStateDescription vmstate_moxie_cpu; diff --git a/target/moxie/meson.build b/target/moxie/meson.build deleted file mode 100644 index b4beb528cc..0000000000 --- a/target/moxie/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -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/moxie/mmu.c b/target/moxie/mmu.c deleted file mode 100644 index 87783a36f8..0000000000 --- a/target/moxie/mmu.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Moxie mmu emulation. - * - * Copyright (c) 2008, 2013 Anthony Green - * - * This library is free software; you can redistribute it 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 program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" - -#include "cpu.h" -#include "mmu.h" - -int moxie_mmu_translate(MoxieMMUResult *res, - CPUMoxieState *env, uint32_t vaddr, - int rw, int mmu_idx) -{ - /* Perform no translation yet. */ - res->phy = vaddr; - return 0; -} diff --git a/target/moxie/mmu.h b/target/moxie/mmu.h deleted file mode 100644 index d80690f4d2..0000000000 --- a/target/moxie/mmu.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TARGET_MOXIE_MMU_H -#define TARGET_MOXIE_MMU_H - -#define MOXIE_MMU_ERR_EXEC 0 -#define MOXIE_MMU_ERR_READ 1 -#define MOXIE_MMU_ERR_WRITE 2 -#define MOXIE_MMU_ERR_FLUSH 3 - -typedef struct { - uint32_t phy; - uint32_t pfn; - int cause_op; -} MoxieMMUResult; - -int moxie_mmu_translate(MoxieMMUResult *res, - CPUMoxieState *env, uint32_t vaddr, - int rw, int mmu_idx); - -#endif diff --git a/target/moxie/translate.c b/target/moxie/translate.c deleted file mode 100644 index 24a742b25e..0000000000 --- a/target/moxie/translate.c +++ /dev/null @@ -1,892 +0,0 @@ -/* - * Moxie emulation for qemu: main translation routines. - * - * Copyright (c) 2009, 2013 Anthony Green - * - * This library is free software; you can redistribute it 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 program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* For information on the Moxie architecture, see - * http://moxielogic.org/wiki - */ - -#include "qemu/osdep.h" - -#include "cpu.h" -#include "exec/exec-all.h" -#include "disas/disas.h" -#include "tcg/tcg-op.h" -#include "exec/cpu_ldst.h" -#include "qemu/qemu-print.h" - -#include "exec/helper-proto.h" -#include "exec/helper-gen.h" -#include "exec/log.h" - -/* This is the state at translation time. */ -typedef struct DisasContext { - TranslationBlock *tb; - target_ulong pc, saved_pc; - uint32_t opcode; - uint32_t fp_status; - /* Routine used to access memory */ - int memidx; - int bstate; - target_ulong btarget; - int singlestep_enabled; -} DisasContext; - -enum { - BS_NONE = 0, /* We go out of the TB without reaching a branch or an - * exception condition */ - BS_STOP = 1, /* We want to stop translation for any reason */ - BS_BRANCH = 2, /* We reached a branch condition */ - BS_EXCP = 3, /* We reached an exception condition */ -}; - -static TCGv cpu_pc; -static TCGv cpu_gregs[16]; -static TCGv cc_a, cc_b; - -#include "exec/gen-icount.h" - -#define REG(x) (cpu_gregs[x]) - -/* Extract the signed 10-bit offset from a 16-bit branch - instruction. */ -static int extract_branch_offset(int opcode) -{ - return (((signed short)((opcode & ((1 << 10) - 1)) << 6)) >> 6) << 1; -} - -void moxie_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ - MoxieCPU *cpu = MOXIE_CPU(cs); - CPUMoxieState *env = &cpu->env; - int i; - qemu_fprintf(f, "pc=0x%08x\n", env->pc); - qemu_fprintf(f, "$fp=0x%08x $sp=0x%08x $r0=0x%08x $r1=0x%08x\n", - env->gregs[0], env->gregs[1], env->gregs[2], env->gregs[3]); - for (i = 4; i < 16; i += 4) { - qemu_fprintf(f, "$r%d=0x%08x $r%d=0x%08x $r%d=0x%08x $r%d=0x%08x\n", - i - 2, env->gregs[i], i - 1, env->gregs[i + 1], - i, env->gregs[i + 2], i + 1, env->gregs[i + 3]); - } - for (i = 4; i < 16; i += 4) { - qemu_fprintf(f, "sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x\n", - i - 2, env->sregs[i], i - 1, env->sregs[i + 1], - i, env->sregs[i + 2], i + 1, env->sregs[i + 3]); - } -} - -void moxie_translate_init(void) -{ - int i; - static const char * const gregnames[16] = { - "$fp", "$sp", "$r0", "$r1", - "$r2", "$r3", "$r4", "$r5", - "$r6", "$r7", "$r8", "$r9", - "$r10", "$r11", "$r12", "$r13" - }; - - cpu_pc = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMoxieState, pc), "$pc"); - for (i = 0; i < 16; i++) - cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMoxieState, gregs[i]), - gregnames[i]); - - cc_a = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMoxieState, cc_a), "cc_a"); - cc_b = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUMoxieState, cc_b), "cc_b"); -} - -static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) -{ - if (unlikely(ctx->singlestep_enabled)) { - return false; - } - -#ifndef CONFIG_USER_ONLY - return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); -#else - return true; -#endif -} - -static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx, - int n, target_ulong dest) -{ - if (use_goto_tb(ctx, dest)) { - tcg_gen_goto_tb(n); - tcg_gen_movi_i32(cpu_pc, dest); - tcg_gen_exit_tb(ctx->tb, n); - } else { - tcg_gen_movi_i32(cpu_pc, dest); - if (ctx->singlestep_enabled) { - gen_helper_debug(cpu_env); - } - tcg_gen_exit_tb(NULL, 0); - } -} - -static int decode_opc(MoxieCPU *cpu, DisasContext *ctx) -{ - CPUMoxieState *env = &cpu->env; - - /* Local cache for the instruction opcode. */ - int opcode; - /* Set the default instruction length. */ - int length = 2; - - /* Examine the 16-bit opcode. */ - opcode = ctx->opcode; - - /* Decode instruction. */ - if (opcode & (1 << 15)) { - if (opcode & (1 << 14)) { - /* This is a Form 3 instruction. */ - int inst = (opcode >> 10 & 0xf); - -#define BRANCH(cond) \ - do { \ - TCGLabel *l1 = gen_new_label(); \ - tcg_gen_brcond_i32(cond, cc_a, cc_b, l1); \ - gen_goto_tb(env, ctx, 1, ctx->pc+2); \ - gen_set_label(l1); \ - gen_goto_tb(env, ctx, 0, extract_branch_offset(opcode) + ctx->pc+2); \ - ctx->bstate = BS_BRANCH; \ - } while (0) - - switch (inst) { - case 0x00: /* beq */ - BRANCH(TCG_COND_EQ); - break; - case 0x01: /* bne */ - BRANCH(TCG_COND_NE); - break; - case 0x02: /* blt */ - BRANCH(TCG_COND_LT); - break; - case 0x03: /* bgt */ - BRANCH(TCG_COND_GT); - break; - case 0x04: /* bltu */ - BRANCH(TCG_COND_LTU); - break; - case 0x05: /* bgtu */ - BRANCH(TCG_COND_GTU); - break; - case 0x06: /* bge */ - BRANCH(TCG_COND_GE); - break; - case 0x07: /* ble */ - BRANCH(TCG_COND_LE); - break; - case 0x08: /* bgeu */ - BRANCH(TCG_COND_GEU); - break; - case 0x09: /* bleu */ - BRANCH(TCG_COND_LEU); - break; - default: - { - TCGv temp = tcg_temp_new_i32(); - tcg_gen_movi_i32(cpu_pc, ctx->pc); - tcg_gen_movi_i32(temp, MOXIE_EX_BAD); - gen_helper_raise_exception(cpu_env, temp); - tcg_temp_free_i32(temp); - } - break; - } - } else { - /* This is a Form 2 instruction. */ - int inst = (opcode >> 12 & 0x3); - switch (inst) { - case 0x00: /* inc */ - { - int a = (opcode >> 8) & 0xf; - unsigned int v = (opcode & 0xff); - tcg_gen_addi_i32(REG(a), REG(a), v); - } - break; - case 0x01: /* dec */ - { - int a = (opcode >> 8) & 0xf; - unsigned int v = (opcode & 0xff); - tcg_gen_subi_i32(REG(a), REG(a), v); - } - break; - case 0x02: /* gsr */ - { - int a = (opcode >> 8) & 0xf; - unsigned v = (opcode & 0xff); - tcg_gen_ld_i32(REG(a), cpu_env, - offsetof(CPUMoxieState, sregs[v])); - } - break; - case 0x03: /* ssr */ - { - int a = (opcode >> 8) & 0xf; - unsigned v = (opcode & 0xff); - tcg_gen_st_i32(REG(a), cpu_env, - offsetof(CPUMoxieState, sregs[v])); - } - break; - default: - { - TCGv temp = tcg_temp_new_i32(); - tcg_gen_movi_i32(cpu_pc, ctx->pc); - tcg_gen_movi_i32(temp, MOXIE_EX_BAD); - gen_helper_raise_exception(cpu_env, temp); - tcg_temp_free_i32(temp); - } - break; - } - } - } else { - /* This is a Form 1 instruction. */ - int inst = opcode >> 8; - switch (inst) { - case 0x00: /* nop */ - break; - case 0x01: /* ldi.l (immediate) */ - { - int reg = (opcode >> 4) & 0xf; - int val = cpu_ldl_code(env, ctx->pc+2); - tcg_gen_movi_i32(REG(reg), val); - length = 6; - } - break; - case 0x02: /* mov (register-to-register) */ - { - int dest = (opcode >> 4) & 0xf; - int src = opcode & 0xf; - tcg_gen_mov_i32(REG(dest), REG(src)); - } - break; - case 0x03: /* jsra */ - { - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - - tcg_gen_movi_i32(t1, ctx->pc + 6); - - /* Make space for the static chain and return address. */ - tcg_gen_subi_i32(t2, REG(1), 8); - tcg_gen_mov_i32(REG(1), t2); - tcg_gen_qemu_st32(t1, REG(1), ctx->memidx); - - /* Push the current frame pointer. */ - tcg_gen_subi_i32(t2, REG(1), 4); - tcg_gen_mov_i32(REG(1), t2); - tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx); - - /* Set the pc and $fp. */ - tcg_gen_mov_i32(REG(0), REG(1)); - - gen_goto_tb(env, ctx, 0, cpu_ldl_code(env, ctx->pc+2)); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - ctx->bstate = BS_BRANCH; - length = 6; - } - break; - case 0x04: /* ret */ - { - TCGv t1 = tcg_temp_new_i32(); - - /* The new $sp is the old $fp. */ - tcg_gen_mov_i32(REG(1), REG(0)); - - /* Pop the frame pointer. */ - tcg_gen_qemu_ld32u(REG(0), REG(1), ctx->memidx); - tcg_gen_addi_i32(t1, REG(1), 4); - tcg_gen_mov_i32(REG(1), t1); - - - /* Pop the return address and skip over the static chain - slot. */ - tcg_gen_qemu_ld32u(cpu_pc, REG(1), ctx->memidx); - tcg_gen_addi_i32(t1, REG(1), 8); - tcg_gen_mov_i32(REG(1), t1); - - tcg_temp_free_i32(t1); - - /* Jump... */ - tcg_gen_exit_tb(NULL, 0); - - ctx->bstate = BS_BRANCH; - } - break; - case 0x05: /* add.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_add_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x06: /* push */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - tcg_gen_subi_i32(t1, REG(a), 4); - tcg_gen_mov_i32(REG(a), t1); - tcg_gen_qemu_st32(REG(b), REG(a), ctx->memidx); - tcg_temp_free_i32(t1); - } - break; - case 0x07: /* pop */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - TCGv t1 = tcg_temp_new_i32(); - - tcg_gen_qemu_ld32u(REG(b), REG(a), ctx->memidx); - tcg_gen_addi_i32(t1, REG(a), 4); - tcg_gen_mov_i32(REG(a), t1); - tcg_temp_free_i32(t1); - } - break; - case 0x08: /* lda.l */ - { - int reg = (opcode >> 4) & 0xf; - - TCGv ptr = tcg_temp_new_i32(); - tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_ld32u(REG(reg), ptr, ctx->memidx); - tcg_temp_free_i32(ptr); - - length = 6; - } - break; - case 0x09: /* sta.l */ - { - int val = (opcode >> 4) & 0xf; - - TCGv ptr = tcg_temp_new_i32(); - tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_st32(REG(val), ptr, ctx->memidx); - tcg_temp_free_i32(ptr); - - length = 6; - } - break; - case 0x0a: /* ld.l (register indirect) */ - { - int src = opcode & 0xf; - int dest = (opcode >> 4) & 0xf; - - tcg_gen_qemu_ld32u(REG(dest), REG(src), ctx->memidx); - } - break; - case 0x0b: /* st.l */ - { - int dest = (opcode >> 4) & 0xf; - int val = opcode & 0xf; - - tcg_gen_qemu_st32(REG(val), REG(dest), ctx->memidx); - } - break; - case 0x0c: /* ldo.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_ld32u(t2, t1, ctx->memidx); - tcg_gen_mov_i32(REG(a), t2); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - length = 6; - } - break; - case 0x0d: /* sto.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_st32(REG(b), t1, ctx->memidx); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - length = 6; - } - break; - case 0x0e: /* cmp */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_mov_i32(cc_a, REG(a)); - tcg_gen_mov_i32(cc_b, REG(b)); - } - break; - case 0x19: /* jsr */ - { - int fnreg = (opcode >> 4) & 0xf; - - /* Load the stack pointer into T0. */ - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - - tcg_gen_movi_i32(t1, ctx->pc+2); - - /* Make space for the static chain and return address. */ - tcg_gen_subi_i32(t2, REG(1), 8); - tcg_gen_mov_i32(REG(1), t2); - tcg_gen_qemu_st32(t1, REG(1), ctx->memidx); - - /* Push the current frame pointer. */ - tcg_gen_subi_i32(t2, REG(1), 4); - tcg_gen_mov_i32(REG(1), t2); - tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx); - - /* Set the pc and $fp. */ - tcg_gen_mov_i32(REG(0), REG(1)); - tcg_gen_mov_i32(cpu_pc, REG(fnreg)); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - tcg_gen_exit_tb(NULL, 0); - ctx->bstate = BS_BRANCH; - } - break; - case 0x1a: /* jmpa */ - { - tcg_gen_movi_i32(cpu_pc, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_exit_tb(NULL, 0); - ctx->bstate = BS_BRANCH; - length = 6; - } - break; - case 0x1b: /* ldi.b (immediate) */ - { - int reg = (opcode >> 4) & 0xf; - int val = cpu_ldl_code(env, ctx->pc+2); - tcg_gen_movi_i32(REG(reg), val); - length = 6; - } - break; - case 0x1c: /* ld.b (register indirect) */ - { - int src = opcode & 0xf; - int dest = (opcode >> 4) & 0xf; - - tcg_gen_qemu_ld8u(REG(dest), REG(src), ctx->memidx); - } - break; - case 0x1d: /* lda.b */ - { - int reg = (opcode >> 4) & 0xf; - - TCGv ptr = tcg_temp_new_i32(); - tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_ld8u(REG(reg), ptr, ctx->memidx); - tcg_temp_free_i32(ptr); - - length = 6; - } - break; - case 0x1e: /* st.b */ - { - int dest = (opcode >> 4) & 0xf; - int val = opcode & 0xf; - - tcg_gen_qemu_st8(REG(val), REG(dest), ctx->memidx); - } - break; - case 0x1f: /* sta.b */ - { - int val = (opcode >> 4) & 0xf; - - TCGv ptr = tcg_temp_new_i32(); - tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_st8(REG(val), ptr, ctx->memidx); - tcg_temp_free_i32(ptr); - - length = 6; - } - break; - case 0x20: /* ldi.s (immediate) */ - { - int reg = (opcode >> 4) & 0xf; - int val = cpu_ldl_code(env, ctx->pc+2); - tcg_gen_movi_i32(REG(reg), val); - length = 6; - } - break; - case 0x21: /* ld.s (register indirect) */ - { - int src = opcode & 0xf; - int dest = (opcode >> 4) & 0xf; - - tcg_gen_qemu_ld16u(REG(dest), REG(src), ctx->memidx); - } - break; - case 0x22: /* lda.s */ - { - int reg = (opcode >> 4) & 0xf; - - TCGv ptr = tcg_temp_new_i32(); - tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_ld16u(REG(reg), ptr, ctx->memidx); - tcg_temp_free_i32(ptr); - - length = 6; - } - break; - case 0x23: /* st.s */ - { - int dest = (opcode >> 4) & 0xf; - int val = opcode & 0xf; - - tcg_gen_qemu_st16(REG(val), REG(dest), ctx->memidx); - } - break; - case 0x24: /* sta.s */ - { - int val = (opcode >> 4) & 0xf; - - TCGv ptr = tcg_temp_new_i32(); - tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_st16(REG(val), ptr, ctx->memidx); - tcg_temp_free_i32(ptr); - - length = 6; - } - break; - case 0x25: /* jmp */ - { - int reg = (opcode >> 4) & 0xf; - tcg_gen_mov_i32(cpu_pc, REG(reg)); - tcg_gen_exit_tb(NULL, 0); - ctx->bstate = BS_BRANCH; - } - break; - case 0x26: /* and */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_and_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x27: /* lshr */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv sv = tcg_temp_new_i32(); - tcg_gen_andi_i32(sv, REG(b), 0x1f); - tcg_gen_shr_i32(REG(a), REG(a), sv); - tcg_temp_free_i32(sv); - } - break; - case 0x28: /* ashl */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv sv = tcg_temp_new_i32(); - tcg_gen_andi_i32(sv, REG(b), 0x1f); - tcg_gen_shl_i32(REG(a), REG(a), sv); - tcg_temp_free_i32(sv); - } - break; - case 0x29: /* sub.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_sub_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x2a: /* neg */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_neg_i32(REG(a), REG(b)); - } - break; - case 0x2b: /* or */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_or_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x2c: /* not */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_not_i32(REG(a), REG(b)); - } - break; - case 0x2d: /* ashr */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv sv = tcg_temp_new_i32(); - tcg_gen_andi_i32(sv, REG(b), 0x1f); - tcg_gen_sar_i32(REG(a), REG(a), sv); - tcg_temp_free_i32(sv); - } - break; - case 0x2e: /* xor */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_xor_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x2f: /* mul.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - tcg_gen_mul_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x30: /* swi */ - { - int val = cpu_ldl_code(env, ctx->pc+2); - - TCGv temp = tcg_temp_new_i32(); - tcg_gen_movi_i32(temp, val); - tcg_gen_st_i32(temp, cpu_env, - offsetof(CPUMoxieState, sregs[3])); - tcg_gen_movi_i32(cpu_pc, ctx->pc); - tcg_gen_movi_i32(temp, MOXIE_EX_SWI); - gen_helper_raise_exception(cpu_env, temp); - tcg_temp_free_i32(temp); - - length = 6; - } - break; - case 0x31: /* div.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - tcg_gen_movi_i32(cpu_pc, ctx->pc); - gen_helper_div(REG(a), cpu_env, REG(a), REG(b)); - } - break; - case 0x32: /* udiv.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - tcg_gen_movi_i32(cpu_pc, ctx->pc); - gen_helper_udiv(REG(a), cpu_env, REG(a), REG(b)); - } - break; - case 0x33: /* mod.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - tcg_gen_rem_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x34: /* umod.l */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - tcg_gen_remu_i32(REG(a), REG(a), REG(b)); - } - break; - case 0x35: /* brk */ - { - TCGv temp = tcg_temp_new_i32(); - tcg_gen_movi_i32(cpu_pc, ctx->pc); - tcg_gen_movi_i32(temp, MOXIE_EX_BREAK); - gen_helper_raise_exception(cpu_env, temp); - tcg_temp_free_i32(temp); - } - break; - case 0x36: /* ldo.b */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_ld8u(t2, t1, ctx->memidx); - tcg_gen_mov_i32(REG(a), t2); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - length = 6; - } - break; - case 0x37: /* sto.b */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_st8(REG(b), t1, ctx->memidx); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - length = 6; - } - break; - case 0x38: /* ldo.s */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_ld16u(t2, t1, ctx->memidx); - tcg_gen_mov_i32(REG(a), t2); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - length = 6; - } - break; - case 0x39: /* sto.s */ - { - int a = (opcode >> 4) & 0xf; - int b = opcode & 0xf; - - TCGv t1 = tcg_temp_new_i32(); - TCGv t2 = tcg_temp_new_i32(); - tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2)); - tcg_gen_qemu_st16(REG(b), t1, ctx->memidx); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); - - length = 6; - } - break; - default: - { - TCGv temp = tcg_temp_new_i32(); - tcg_gen_movi_i32(cpu_pc, ctx->pc); - tcg_gen_movi_i32(temp, MOXIE_EX_BAD); - gen_helper_raise_exception(cpu_env, temp); - tcg_temp_free_i32(temp); - } - break; - } - } - - return length; -} - -/* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) -{ - CPUMoxieState *env = cs->env_ptr; - MoxieCPU *cpu = env_archcpu(env); - DisasContext ctx; - target_ulong pc_start; - int num_insns; - - pc_start = tb->pc; - ctx.pc = pc_start; - ctx.saved_pc = -1; - ctx.tb = tb; - ctx.memidx = 0; - ctx.singlestep_enabled = 0; - ctx.bstate = BS_NONE; - num_insns = 0; - - gen_tb_start(tb); - do { - tcg_gen_insn_start(ctx.pc); - num_insns++; - - if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { - tcg_gen_movi_i32(cpu_pc, ctx.pc); - gen_helper_debug(cpu_env); - ctx.bstate = BS_EXCP; - /* 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. */ - ctx.pc += 2; - goto done_generating; - } - - ctx.opcode = cpu_lduw_code(env, ctx.pc); - ctx.pc += decode_opc(cpu, &ctx); - - if (num_insns >= max_insns) { - break; - } - if (cs->singlestep_enabled) { - break; - } - if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) { - break; - } - } while (ctx.bstate == BS_NONE && !tcg_op_buf_full()); - - if (cs->singlestep_enabled) { - tcg_gen_movi_tl(cpu_pc, ctx.pc); - gen_helper_debug(cpu_env); - } else { - switch (ctx.bstate) { - case BS_STOP: - case BS_NONE: - gen_goto_tb(env, &ctx, 0, ctx.pc); - break; - case BS_EXCP: - tcg_gen_exit_tb(NULL, 0); - break; - case BS_BRANCH: - default: - break; - } - } - done_generating: - gen_tb_end(tb, num_insns); - - tb->size = ctx.pc - pc_start; - tb->icount = num_insns; -} - -void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, - target_ulong *data) -{ - env->pc = data[0]; -} diff --git a/target/unicore32/cpu-param.h b/target/unicore32/cpu-param.h deleted file mode 100644 index 94d8a5daa1..0000000000 --- a/target/unicore32/cpu-param.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * UniCore32 cpu parameters for qemu. - * - * Copyright (C) 2010-2012 Guan Xuetao - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef UNICORE32_CPU_PARAM_H -#define UNICORE32_CPU_PARAM_H 1 - -#define TARGET_LONG_BITS 32 -#define TARGET_PAGE_BITS 12 -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 -#define NB_MMU_MODES 2 - -#endif diff --git a/target/unicore32/cpu-qom.h b/target/unicore32/cpu-qom.h deleted file mode 100644 index 43621e7479..0000000000 --- a/target/unicore32/cpu-qom.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * QEMU UniCore32 CPU - * - * 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 version 2 as - * published by the Free Software Foundation, or (at your option) any - * later version. See the COPYING file in the top-level directory. - */ -#ifndef QEMU_UC32_CPU_QOM_H -#define QEMU_UC32_CPU_QOM_H - -#include "hw/core/cpu.h" -#include "qom/object.h" - -#define TYPE_UNICORE32_CPU "unicore32-cpu" - -OBJECT_DECLARE_TYPE(UniCore32CPU, UniCore32CPUClass, - UNICORE32_CPU) - -/** - * UniCore32CPUClass: - * @parent_realize: The parent class' realize handler. - * - * A UniCore32 CPU model. - */ -struct UniCore32CPUClass { - /*< private >*/ - CPUClass parent_class; - /*< public >*/ - - DeviceRealize parent_realize; -}; - - -#endif diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c deleted file mode 100644 index 0258884f84..0000000000 --- a/target/unicore32/cpu.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * QEMU UniCore32 CPU - * - * Copyright (c) 2010-2012 Guan Xuetao - * 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 version 2 as - * published by the Free Software Foundation. - * - * Contributions from 2012-04-01 on are considered under GPL version 2, - * or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "cpu.h" -#include "migration/vmstate.h" -#include "exec/exec-all.h" - -static void uc32_cpu_set_pc(CPUState *cs, vaddr value) -{ - UniCore32CPU *cpu = UNICORE32_CPU(cs); - - cpu->env.regs[31] = value; -} - -static bool uc32_cpu_has_work(CPUState *cs) -{ - return cs->interrupt_request & - (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB); -} - -static inline void set_feature(CPUUniCore32State *env, int feature) -{ - env->features |= feature; -} - -/* CPU models */ - -static ObjectClass *uc32_cpu_class_by_name(const char *cpu_model) -{ - ObjectClass *oc; - char *typename; - - typename = g_strdup_printf(UNICORE32_CPU_TYPE_NAME("%s"), cpu_model); - oc = object_class_by_name(typename); - g_free(typename); - if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_UNICORE32_CPU) || - object_class_is_abstract(oc))) { - oc = NULL; - } - return oc; -} - -static void unicore_ii_cpu_initfn(Object *obj) -{ - UniCore32CPU *cpu = UNICORE32_CPU(obj); - CPUUniCore32State *env = &cpu->env; - - env->cp0.c0_cpuid = 0x4d000863; - env->cp0.c0_cachetype = 0x0d152152; - env->cp0.c1_sys = 0x2000; - env->cp0.c2_base = 0x0; - env->cp0.c3_faultstatus = 0x0; - env->cp0.c4_faultaddr = 0x0; - env->ucf64.xregs[UC32_UCF64_FPSCR] = 0; - - set_feature(env, UC32_HWCAP_CMOV); - set_feature(env, UC32_HWCAP_UCF64); -} - -static void uc32_any_cpu_initfn(Object *obj) -{ - UniCore32CPU *cpu = UNICORE32_CPU(obj); - CPUUniCore32State *env = &cpu->env; - - env->cp0.c0_cpuid = 0xffffffff; - env->ucf64.xregs[UC32_UCF64_FPSCR] = 0; - - set_feature(env, UC32_HWCAP_CMOV); - set_feature(env, UC32_HWCAP_UCF64); -} - -static void uc32_cpu_realizefn(DeviceState *dev, Error **errp) -{ - CPUState *cs = CPU(dev); - UniCore32CPUClass *ucc = UNICORE32_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); - - ucc->parent_realize(dev, errp); -} - -static void uc32_cpu_initfn(Object *obj) -{ - UniCore32CPU *cpu = UNICORE32_CPU(obj); - CPUUniCore32State *env = &cpu->env; - - cpu_set_cpustate_pointers(cpu); - -#ifdef CONFIG_USER_ONLY - env->uncached_asr = ASR_MODE_USER; - env->regs[31] = 0; -#else - env->uncached_asr = ASR_MODE_PRIV; - env->regs[31] = 0x03000000; -#endif -} - -static const VMStateDescription vmstate_uc32_cpu = { - .name = "cpu", - .unmigratable = 1, -}; - -#include "hw/core/tcg-cpu-ops.h" - -static struct TCGCPUOps uc32_tcg_ops = { - .initialize = uc32_translate_init, - .cpu_exec_interrupt = uc32_cpu_exec_interrupt, - .tlb_fill = uc32_cpu_tlb_fill, - -#ifndef CONFIG_USER_ONLY - .do_interrupt = uc32_cpu_do_interrupt, -#endif /* !CONFIG_USER_ONLY */ -}; - -static void uc32_cpu_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - CPUClass *cc = CPU_CLASS(oc); - UniCore32CPUClass *ucc = UNICORE32_CPU_CLASS(oc); - - device_class_set_parent_realize(dc, uc32_cpu_realizefn, - &ucc->parent_realize); - - cc->class_by_name = uc32_cpu_class_by_name; - cc->has_work = uc32_cpu_has_work; - cc->dump_state = uc32_cpu_dump_state; - cc->set_pc = uc32_cpu_set_pc; - cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug; - dc->vmsd = &vmstate_uc32_cpu; - cc->tcg_ops = &uc32_tcg_ops; -} - -#define DEFINE_UNICORE32_CPU_TYPE(cpu_model, initfn) \ - { \ - .parent = TYPE_UNICORE32_CPU, \ - .instance_init = initfn, \ - .name = UNICORE32_CPU_TYPE_NAME(cpu_model), \ - } - -static const TypeInfo uc32_cpu_type_infos[] = { - { - .name = TYPE_UNICORE32_CPU, - .parent = TYPE_CPU, - .instance_size = sizeof(UniCore32CPU), - .instance_init = uc32_cpu_initfn, - .abstract = true, - .class_size = sizeof(UniCore32CPUClass), - .class_init = uc32_cpu_class_init, - }, - DEFINE_UNICORE32_CPU_TYPE("UniCore-II", unicore_ii_cpu_initfn), - DEFINE_UNICORE32_CPU_TYPE("any", uc32_any_cpu_initfn), -}; - -DEFINE_TYPES(uc32_cpu_type_infos) diff --git a/target/unicore32/cpu.h b/target/unicore32/cpu.h deleted file mode 100644 index 7a32e086ed..0000000000 --- a/target/unicore32/cpu.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * UniCore32 virtual CPU header - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or (at your option) any - * later version. See the COPYING file in the top-level directory. - */ - -#ifndef UNICORE32_CPU_H -#define UNICORE32_CPU_H - -#include "cpu-qom.h" -#include "exec/cpu-defs.h" - -typedef struct CPUUniCore32State { - /* Regs for current mode. */ - uint32_t regs[32]; - /* Frequently accessed ASR bits are stored separately for efficiently. - This contains all the other bits. Use asr_{read,write} to access - the whole ASR. */ - uint32_t uncached_asr; - uint32_t bsr; - - /* Banked registers. */ - uint32_t banked_bsr[6]; - uint32_t banked_r29[6]; - uint32_t banked_r30[6]; - - /* asr flag cache for faster execution */ - uint32_t CF; /* 0 or 1 */ - uint32_t VF; /* V is the bit 31. All other bits are undefined */ - uint32_t NF; /* N is bit 31. All other bits are undefined. */ - uint32_t ZF; /* Z set if zero. */ - - /* System control coprocessor (cp0) */ - struct { - uint32_t c0_cpuid; - uint32_t c0_cachetype; - uint32_t c1_sys; /* System control register. */ - uint32_t c2_base; /* MMU translation table base. */ - uint32_t c3_faultstatus; /* Fault status registers. */ - uint32_t c4_faultaddr; /* Fault address registers. */ - uint32_t c5_cacheop; /* Cache operation registers. */ - uint32_t c6_tlbop; /* TLB operation registers. */ - } cp0; - - /* UniCore-F64 coprocessor state. */ - struct { - float64 regs[16]; - uint32_t xregs[32]; - float_status fp_status; - } ucf64; - - /* Internal CPU feature flags. */ - uint32_t features; - -} CPUUniCore32State; - -/** - * UniCore32CPU: - * @env: #CPUUniCore32State - * - * A UniCore32 CPU. - */ -struct UniCore32CPU { - /*< private >*/ - CPUState parent_obj; - /*< public >*/ - - CPUNegativeOffsetState neg; - CPUUniCore32State env; -}; - - -void uc32_cpu_do_interrupt(CPUState *cpu); -bool uc32_cpu_exec_interrupt(CPUState *cpu, int int_req); -void uc32_cpu_dump_state(CPUState *cpu, FILE *f, int flags); -hwaddr uc32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); - -#define ASR_M (0x1f) -#define ASR_MODE_USER (0x10) -#define ASR_MODE_INTR (0x12) -#define ASR_MODE_PRIV (0x13) -#define ASR_MODE_TRAP (0x17) -#define ASR_MODE_EXTN (0x1b) -#define ASR_MODE_SUSR (0x1f) -#define ASR_I (1 << 7) -#define ASR_V (1 << 28) -#define ASR_C (1 << 29) -#define ASR_Z (1 << 30) -#define ASR_N (1 << 31) -#define ASR_NZCV (ASR_N | ASR_Z | ASR_C | ASR_V) -#define ASR_RESERVED (~(ASR_M | ASR_I | ASR_NZCV)) - -#define UC32_EXCP_PRIV (1) -#define UC32_EXCP_ITRAP (2) -#define UC32_EXCP_DTRAP (3) -#define UC32_EXCP_INTR (4) - -/* Return the current ASR value. */ -target_ulong cpu_asr_read(CPUUniCore32State *env1); -/* Set the ASR. Note that some bits of mask must be all-set or all-clear. */ -void cpu_asr_write(CPUUniCore32State *env1, target_ulong val, target_ulong mask); - -/* UniCore-F64 system registers. */ -#define UC32_UCF64_FPSCR (31) -#define UCF64_FPSCR_MASK (0x27ffffff) -#define UCF64_FPSCR_RND_MASK (0x7) -#define UCF64_FPSCR_RND(r) (((r) >> 0) & UCF64_FPSCR_RND_MASK) -#define UCF64_FPSCR_TRAPEN_MASK (0x7f) -#define UCF64_FPSCR_TRAPEN(r) (((r) >> 10) & UCF64_FPSCR_TRAPEN_MASK) -#define UCF64_FPSCR_FLAG_MASK (0x3ff) -#define UCF64_FPSCR_FLAG(r) (((r) >> 17) & UCF64_FPSCR_FLAG_MASK) -#define UCF64_FPSCR_FLAG_ZERO (1 << 17) -#define UCF64_FPSCR_FLAG_INFINITY (1 << 18) -#define UCF64_FPSCR_FLAG_INVALID (1 << 19) -#define UCF64_FPSCR_FLAG_UNDERFLOW (1 << 20) -#define UCF64_FPSCR_FLAG_OVERFLOW (1 << 21) -#define UCF64_FPSCR_FLAG_INEXACT (1 << 22) -#define UCF64_FPSCR_FLAG_HUGEINT (1 << 23) -#define UCF64_FPSCR_FLAG_DENORMAL (1 << 24) -#define UCF64_FPSCR_FLAG_UNIMP (1 << 25) -#define UCF64_FPSCR_FLAG_DIVZERO (1 << 26) - -#define UC32_HWCAP_CMOV 4 /* 1 << 2 */ -#define UC32_HWCAP_UCF64 8 /* 1 << 3 */ - -#define cpu_signal_handler uc32_cpu_signal_handler - -int uc32_cpu_signal_handler(int host_signum, void *pinfo, void *puc); - -/* MMU modes definitions */ -#define MMU_USER_IDX 1 -static inline int cpu_mmu_index(CPUUniCore32State *env, bool ifetch) -{ - return (env->uncached_asr & ASR_M) == ASR_MODE_USER ? 1 : 0; -} - -typedef CPUUniCore32State CPUArchState; -typedef UniCore32CPU ArchCPU; - -#include "exec/cpu-all.h" - -#define UNICORE32_CPU_TYPE_SUFFIX "-" TYPE_UNICORE32_CPU -#define UNICORE32_CPU_TYPE_NAME(model) model UNICORE32_CPU_TYPE_SUFFIX -#define CPU_RESOLVING_TYPE TYPE_UNICORE32_CPU - -static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) -{ - *pc = env->regs[31]; - *cs_base = 0; - *flags = 0; - if ((env->uncached_asr & ASR_M) != ASR_MODE_USER) { - *flags |= (1 << 6); - } -} - -bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr); -void uc32_translate_init(void); -void switch_mode(CPUUniCore32State *, int); - -#endif /* UNICORE32_CPU_H */ diff --git a/target/unicore32/helper.c b/target/unicore32/helper.c deleted file mode 100644 index 704393c27f..0000000000 --- a/target/unicore32/helper.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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. - * - * Contributions from 2012-04-01 on are considered under GPL version 2, - * or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qemu/log.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exec/helper-proto.h" -#include "semihosting/console.h" - -#undef DEBUG_UC32 - -#ifdef DEBUG_UC32 -#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif - -#ifndef CONFIG_USER_ONLY -void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg, - uint32_t cop) -{ - /* - * movc pp.nn, rn, #imm9 - * rn: UCOP_REG_D - * nn: UCOP_REG_N - * 1: sys control reg. - * 2: page table base reg. - * 3: data fault status reg. - * 4: insn fault status reg. - * 5: cache op. reg. - * 6: tlb op. reg. - * imm9: split UCOP_IMM10 with bit5 is 0 - */ - switch (creg) { - case 1: - if (cop != 0) { - goto unrecognized; - } - env->cp0.c1_sys = val; - break; - case 2: - if (cop != 0) { - goto unrecognized; - } - env->cp0.c2_base = val; - break; - case 3: - if (cop != 0) { - goto unrecognized; - } - env->cp0.c3_faultstatus = val; - break; - case 4: - if (cop != 0) { - goto unrecognized; - } - env->cp0.c4_faultaddr = val; - break; - case 5: - switch (cop) { - case 28: - DPRINTF("Invalidate Entire I&D cache\n"); - return; - case 20: - DPRINTF("Invalidate Entire Icache\n"); - return; - case 12: - DPRINTF("Invalidate Entire Dcache\n"); - return; - case 10: - DPRINTF("Clean Entire Dcache\n"); - return; - case 14: - DPRINTF("Flush Entire Dcache\n"); - return; - case 13: - DPRINTF("Invalidate Dcache line\n"); - return; - case 11: - DPRINTF("Clean Dcache line\n"); - return; - case 15: - DPRINTF("Flush Dcache line\n"); - return; - } - break; - case 6: - if ((cop <= 6) && (cop >= 2)) { - /* invalid all tlb */ - tlb_flush(env_cpu(env)); - return; - } - break; - default: - goto unrecognized; - } - return; -unrecognized: - 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) -{ - /* - * movc rd, pp.nn, #imm9 - * rd: UCOP_REG_D - * nn: UCOP_REG_N - * 0: cpuid and cachetype - * 1: sys control reg. - * 2: page table base reg. - * 3: data fault status reg. - * 4: insn fault status reg. - * imm9: split UCOP_IMM10 with bit5 is 0 - */ - switch (creg) { - case 0: - switch (cop) { - case 0: - return env->cp0.c0_cpuid; - case 1: - return env->cp0.c0_cachetype; - } - break; - case 1: - if (cop == 0) { - return env->cp0.c1_sys; - } - break; - case 2: - if (cop == 0) { - return env->cp0.c2_base; - } - break; - case 3: - if (cop == 0) { - return env->cp0.c3_faultstatus; - } - break; - case 4: - if (cop == 0) { - return env->cp0.c4_faultaddr; - } - break; - } - qemu_log_mask(LOG_GUEST_ERROR, - "Wrong register (%d) or wrong operation (%d) in cp0_set!\n", - creg, cop); - return 0; -} - -void helper_cp1_putc(target_ulong regval) -{ - const char c = regval; - - qemu_semihosting_log_out(&c, sizeof(c)); -} -#endif /* !CONFIG_USER_ONLY */ - -bool uc32_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - if (interrupt_request & CPU_INTERRUPT_HARD) { - UniCore32CPU *cpu = UNICORE32_CPU(cs); - CPUUniCore32State *env = &cpu->env; - - if (!(env->uncached_asr & ASR_I)) { - cs->exception_index = UC32_EXCP_INTR; - uc32_cpu_do_interrupt(cs); - return true; - } - } - return false; -} diff --git a/target/unicore32/helper.h b/target/unicore32/helper.h deleted file mode 100644 index a4a5d45d1d..0000000000 --- a/target/unicore32/helper.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or (at your option) any - * later version. See the COPYING file in the top-level directory. - */ - -#ifndef CONFIG_USER_ONLY -DEF_HELPER_4(cp0_set, void, env, i32, i32, i32) -DEF_HELPER_3(cp0_get, i32, env, i32, i32) -DEF_HELPER_1(cp1_putc, void, i32) -#endif - -DEF_HELPER_2(exception, void, env, i32) - -DEF_HELPER_3(asr_write, void, env, i32, i32) -DEF_HELPER_1(asr_read, i32, env) - -DEF_HELPER_2(get_user_reg, i32, env, i32) -DEF_HELPER_3(set_user_reg, void, env, i32, i32) - -DEF_HELPER_3(add_cc, i32, env, i32, i32) -DEF_HELPER_3(adc_cc, i32, env, i32, i32) -DEF_HELPER_3(sub_cc, i32, env, i32, i32) -DEF_HELPER_3(sbc_cc, i32, env, i32, i32) - -DEF_HELPER_2(shl, i32, i32, i32) -DEF_HELPER_2(shr, i32, i32, i32) -DEF_HELPER_2(sar, i32, i32, i32) -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_1(ucf64_get_fpscr, i32, env) -DEF_HELPER_2(ucf64_set_fpscr, void, env, i32) - -DEF_HELPER_3(ucf64_adds, f32, f32, f32, env) -DEF_HELPER_3(ucf64_addd, f64, f64, f64, env) -DEF_HELPER_3(ucf64_subs, f32, f32, f32, env) -DEF_HELPER_3(ucf64_subd, f64, f64, f64, env) -DEF_HELPER_3(ucf64_muls, f32, f32, f32, env) -DEF_HELPER_3(ucf64_muld, f64, f64, f64, env) -DEF_HELPER_3(ucf64_divs, f32, f32, f32, env) -DEF_HELPER_3(ucf64_divd, f64, f64, f64, env) -DEF_HELPER_1(ucf64_negs, f32, f32) -DEF_HELPER_1(ucf64_negd, f64, f64) -DEF_HELPER_1(ucf64_abss, f32, f32) -DEF_HELPER_1(ucf64_absd, f64, f64) -DEF_HELPER_4(ucf64_cmps, void, f32, f32, i32, env) -DEF_HELPER_4(ucf64_cmpd, void, f64, f64, i32, env) - -DEF_HELPER_2(ucf64_sf2df, f64, f32, env) -DEF_HELPER_2(ucf64_df2sf, f32, f64, env) - -DEF_HELPER_2(ucf64_si2sf, f32, f32, env) -DEF_HELPER_2(ucf64_si2df, f64, f32, env) - -DEF_HELPER_2(ucf64_sf2si, f32, f32, env) -DEF_HELPER_2(ucf64_df2si, f32, f64, env) diff --git a/target/unicore32/meson.build b/target/unicore32/meson.build deleted file mode 100644 index 0fa78772eb..0000000000 --- a/target/unicore32/meson.build +++ /dev/null @@ -1,14 +0,0 @@ -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/unicore32/op_helper.c b/target/unicore32/op_helper.c deleted file mode 100644 index eeaa78601a..0000000000 --- a/target/unicore32/op_helper.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * UniCore32 helper routines - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or (at your option) any - * later version. See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "exec/exec-all.h" -#include "exec/cpu_ldst.h" - -#define SIGNBIT (uint32_t)0x80000000 -#define SIGNBIT64 ((uint64_t)1 << 63) - -void HELPER(exception)(CPUUniCore32State *env, uint32_t excp) -{ - CPUState *cs = env_cpu(env); - - cs->exception_index = excp; - cpu_loop_exit(cs); -} - -static target_ulong asr_read(CPUUniCore32State *env) -{ - int ZF; - ZF = (env->ZF == 0); - return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) | - (env->CF << 29) | ((env->VF & 0x80000000) >> 3); -} - -target_ulong cpu_asr_read(CPUUniCore32State *env) -{ - return asr_read(env); -} - -target_ulong HELPER(asr_read)(CPUUniCore32State *env) -{ - return asr_read(env); -} - -static void asr_write(CPUUniCore32State *env, target_ulong val, - target_ulong mask) -{ - if (mask & ASR_NZCV) { - env->ZF = (~val) & ASR_Z; - env->NF = val; - env->CF = (val >> 29) & 1; - env->VF = (val << 3) & 0x80000000; - } - - if ((env->uncached_asr ^ val) & mask & ASR_M) { - switch_mode(env, val & ASR_M); - } - mask &= ~ASR_NZCV; - env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask); -} - -void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask) -{ - asr_write(env, val, mask); -} - -void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val, - target_ulong mask) -{ - asr_write(env, val, mask); -} - -/* Access to user mode registers from privileged modes. */ -uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno) -{ - uint32_t val; - - if (regno == 29) { - val = env->banked_r29[0]; - } else if (regno == 30) { - val = env->banked_r30[0]; - } else { - val = env->regs[regno]; - } - return val; -} - -void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val) -{ - if (regno == 29) { - env->banked_r29[0] = val; - } else if (regno == 30) { - env->banked_r30[0] = val; - } else { - env->regs[regno] = val; - } -} - -/* ??? Flag setting arithmetic is awkward because we need to do comparisons. - The only way to do that in TCG is a conditional branch, which clobbers - all our temporaries. For now implement these as helper functions. */ - -uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) -{ - uint32_t result; - result = a + b; - env->NF = env->ZF = result; - env->CF = result < a; - env->VF = (a ^ b ^ -1) & (a ^ result); - return result; -} - -uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) -{ - uint32_t result; - if (!env->CF) { - result = a + b; - env->CF = result < a; - } else { - result = a + b + 1; - env->CF = result <= a; - } - env->VF = (a ^ b ^ -1) & (a ^ result); - env->NF = env->ZF = result; - return result; -} - -uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) -{ - uint32_t result; - result = a - b; - env->NF = env->ZF = result; - env->CF = a >= b; - env->VF = (a ^ b) & (a ^ result); - return result; -} - -uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b) -{ - uint32_t result; - if (!env->CF) { - result = a - b - 1; - env->CF = a > b; - } else { - result = a - b; - env->CF = a >= b; - } - env->VF = (a ^ b) & (a ^ result); - env->NF = env->ZF = result; - return result; -} - -/* Similarly for variable shift instructions. */ - -uint32_t HELPER(shl)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - return 0; - } - return x << shift; -} - -uint32_t HELPER(shr)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - return 0; - } - return (uint32_t)x >> shift; -} - -uint32_t HELPER(sar)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - shift = 31; - } - return (int32_t)x >> shift; -} - -uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - if (shift == 32) { - env->CF = x & 1; - } else { - env->CF = 0; - } - return 0; - } else if (shift != 0) { - env->CF = (x >> (32 - shift)) & 1; - return x << shift; - } - return x; -} - -uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - if (shift == 32) { - env->CF = (x >> 31) & 1; - } else { - env->CF = 0; - } - return 0; - } else if (shift != 0) { - env->CF = (x >> (shift - 1)) & 1; - return x >> shift; - } - return x; -} - -uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - env->CF = (x >> 31) & 1; - return (int32_t)x >> 31; - } else if (shift != 0) { - env->CF = (x >> (shift - 1)) & 1; - return (int32_t)x >> shift; - } - return x; -} - -uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) -{ - int shift1, shift; - shift1 = i & 0xff; - shift = shift1 & 0x1f; - if (shift == 0) { - if (shift1 != 0) { - env->CF = (x >> 31) & 1; - } - return x; - } else { - env->CF = (x >> (shift - 1)) & 1; - return ((uint32_t)x >> shift) | (x << (32 - shift)); - } -} diff --git a/target/unicore32/softmmu.c b/target/unicore32/softmmu.c deleted file mode 100644 index cbdaa500b7..0000000000 --- a/target/unicore32/softmmu.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Softmmu related functions - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ -#ifdef CONFIG_USER_ONLY -#error This file only exist under softmmu circumstance -#endif - -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "qemu/error-report.h" - -#undef DEBUG_UC32 - -#ifdef DEBUG_UC32 -#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif - -#define SUPERPAGE_SIZE (1 << 22) -#define UC32_PAGETABLE_READ (1 << 8) -#define UC32_PAGETABLE_WRITE (1 << 7) -#define UC32_PAGETABLE_EXEC (1 << 6) -#define UC32_PAGETABLE_EXIST (1 << 2) -#define PAGETABLE_TYPE(x) ((x) & 3) - - -/* Map CPU modes onto saved register banks. */ -static inline int bank_number(CPUUniCore32State *env, int mode) -{ - switch (mode) { - case ASR_MODE_USER: - case ASR_MODE_SUSR: - return 0; - case ASR_MODE_PRIV: - return 1; - case ASR_MODE_TRAP: - return 2; - case ASR_MODE_EXTN: - return 3; - case ASR_MODE_INTR: - return 4; - } - cpu_abort(env_cpu(env), "Bad mode %x\n", mode); - return -1; -} - -void switch_mode(CPUUniCore32State *env, int mode) -{ - int old_mode; - int i; - - old_mode = env->uncached_asr & ASR_M; - if (mode == old_mode) { - return; - } - - i = bank_number(env, old_mode); - env->banked_r29[i] = env->regs[29]; - env->banked_r30[i] = env->regs[30]; - env->banked_bsr[i] = env->bsr; - - i = bank_number(env, mode); - env->regs[29] = env->banked_r29[i]; - env->regs[30] = env->banked_r30[i]; - env->bsr = env->banked_bsr[i]; -} - -/* Handle a CPU exception. */ -void uc32_cpu_do_interrupt(CPUState *cs) -{ - UniCore32CPU *cpu = UNICORE32_CPU(cs); - CPUUniCore32State *env = &cpu->env; - uint32_t addr; - int new_mode; - - switch (cs->exception_index) { - case UC32_EXCP_PRIV: - new_mode = ASR_MODE_PRIV; - addr = 0x08; - break; - case UC32_EXCP_ITRAP: - DPRINTF("itrap happened at %x\n", env->regs[31]); - new_mode = ASR_MODE_TRAP; - addr = 0x0c; - break; - case UC32_EXCP_DTRAP: - DPRINTF("dtrap happened at %x\n", env->regs[31]); - new_mode = ASR_MODE_TRAP; - addr = 0x10; - break; - case UC32_EXCP_INTR: - new_mode = ASR_MODE_INTR; - addr = 0x18; - break; - default: - cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); - return; - } - /* High vectors. */ - if (env->cp0.c1_sys & (1 << 13)) { - addr += 0xffff0000; - } - - switch_mode(env, new_mode); - env->bsr = cpu_asr_read(env); - env->uncached_asr = (env->uncached_asr & ~ASR_M) | new_mode; - env->uncached_asr |= ASR_I; - /* The PC already points to the proper instruction. */ - env->regs[30] = env->regs[31]; - env->regs[31] = addr; - cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -} - -static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address, - int access_type, int is_user, uint32_t *phys_ptr, int *prot, - target_ulong *page_size) -{ - CPUState *cs = env_cpu(env); - int code; - uint32_t table; - uint32_t desc; - uint32_t phys_addr; - - /* Pagetable walk. */ - /* Lookup l1 descriptor. */ - table = env->cp0.c2_base & 0xfffff000; - table |= (address >> 20) & 0xffc; - desc = ldl_phys(cs->as, table); - code = 0; - switch (PAGETABLE_TYPE(desc)) { - case 3: - /* Superpage */ - if (!(desc & UC32_PAGETABLE_EXIST)) { - code = 0x0b; /* superpage miss */ - goto do_fault; - } - phys_addr = (desc & 0xffc00000) | (address & 0x003fffff); - *page_size = SUPERPAGE_SIZE; - break; - case 0: - /* Lookup l2 entry. */ - if (is_user) { - DPRINTF("PGD address %x, desc %x\n", table, desc); - } - if (!(desc & UC32_PAGETABLE_EXIST)) { - code = 0x05; /* second pagetable miss */ - goto do_fault; - } - table = (desc & 0xfffff000) | ((address >> 10) & 0xffc); - desc = ldl_phys(cs->as, table); - /* 4k page. */ - if (is_user) { - DPRINTF("PTE address %x, desc %x\n", table, desc); - } - if (!(desc & UC32_PAGETABLE_EXIST)) { - code = 0x08; /* page miss */ - goto do_fault; - } - switch (PAGETABLE_TYPE(desc)) { - case 0: - phys_addr = (desc & 0xfffff000) | (address & 0xfff); - *page_size = TARGET_PAGE_SIZE; - break; - default: - cpu_abort(cs, "wrong page type!"); - } - break; - default: - cpu_abort(cs, "wrong page type!"); - } - - *phys_ptr = phys_addr; - *prot = 0; - /* Check access permissions. */ - if (desc & UC32_PAGETABLE_READ) { - *prot |= PAGE_READ; - } else { - if (is_user && (access_type == 0)) { - code = 0x11; /* access unreadable area */ - goto do_fault; - } - } - - if (desc & UC32_PAGETABLE_WRITE) { - *prot |= PAGE_WRITE; - } else { - if (is_user && (access_type == 1)) { - code = 0x12; /* access unwritable area */ - goto do_fault; - } - } - - if (desc & UC32_PAGETABLE_EXEC) { - *prot |= PAGE_EXEC; - } else { - if (is_user && (access_type == 2)) { - code = 0x13; /* access unexecutable area */ - goto do_fault; - } - } - -do_fault: - return code; -} - -bool uc32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr) -{ - UniCore32CPU *cpu = UNICORE32_CPU(cs); - CPUUniCore32State *env = &cpu->env; - uint32_t phys_addr; - target_ulong page_size; - int prot; - int ret, is_user; - - ret = 1; - is_user = mmu_idx == MMU_USER_IDX; - - if ((env->cp0.c1_sys & 1) == 0) { - /* MMU disabled. */ - phys_addr = address; - prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - page_size = TARGET_PAGE_SIZE; - ret = 0; - } else { - if ((address & (1 << 31)) || (is_user)) { - ret = get_phys_addr_ucv2(env, address, access_type, is_user, - &phys_addr, &prot, &page_size); - if (is_user) { - DPRINTF("user space access: ret %x, address %" VADDR_PRIx ", " - "access_type %x, phys_addr %x, prot %x\n", - ret, address, access_type, phys_addr, prot); - } - } else { - /*IO memory */ - phys_addr = address | (1 << 31); - prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - page_size = TARGET_PAGE_SIZE; - ret = 0; - } - } - - if (ret == 0) { - /* Map a single page. */ - phys_addr &= TARGET_PAGE_MASK; - address &= TARGET_PAGE_MASK; - tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size); - return true; - } - - if (probe) { - return false; - } - - env->cp0.c3_faultstatus = ret; - env->cp0.c4_faultaddr = address; - if (access_type == 2) { - cs->exception_index = UC32_EXCP_ITRAP; - } else { - cs->exception_index = UC32_EXCP_DTRAP; - } - cpu_loop_exit_restore(cs, retaddr); -} - -hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - error_report("function uc32_cpu_get_phys_page_debug not " - "implemented, aborting"); - return -1; -} diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c deleted file mode 100644 index 370709c9ea..0000000000 --- a/target/unicore32/translate.c +++ /dev/null @@ -1,2083 +0,0 @@ -/* - * UniCore32 translation - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or (at your option) any - * later version. See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" - -#include "cpu.h" -#include "disas/disas.h" -#include "exec/exec-all.h" -#include "tcg/tcg-op.h" -#include "qemu/log.h" -#include "exec/cpu_ldst.h" -#include "exec/translator.h" -#include "qemu/qemu-print.h" - -#include "exec/helper-proto.h" -#include "exec/helper-gen.h" - -#include "trace-tcg.h" -#include "exec/log.h" - - -/* internal defines */ -typedef struct DisasContext { - target_ulong pc; - int is_jmp; - /* Nonzero if this instruction has been conditionally skipped. */ - int condjmp; - /* The label that will be jumped to when the instruction is skipped. */ - TCGLabel *condlabel; - TranslationBlock *tb; - int singlestep_enabled; -#ifndef CONFIG_USER_ONLY - int user; -#endif -} DisasContext; - -#ifndef CONFIG_USER_ONLY -#define IS_USER(s) (s->user) -#else -#define IS_USER(s) 1 -#endif - -/* 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 */ -/* These instructions trap after executing, so defer them until after the - conditional executions state has been updated. */ -#define DISAS_SYSCALL DISAS_TARGET_3 - -static TCGv_i32 cpu_R[32]; - -/* FIXME: These should be removed. */ -static TCGv cpu_F0s, cpu_F1s; -static TCGv_i64 cpu_F0d, cpu_F1d; - -#include "exec/gen-icount.h" - -static const char *regnames[] = { - "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07", - "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "pc" }; - -/* initialize TCG globals. */ -void uc32_translate_init(void) -{ - int i; - - for (i = 0; i < 32; i++) { - cpu_R[i] = tcg_global_mem_new_i32(cpu_env, - offsetof(CPUUniCore32State, regs[i]), regnames[i]); - } -} - -static int num_temps; - -/* Allocate a temporary variable. */ -static TCGv_i32 new_tmp(void) -{ - num_temps++; - return tcg_temp_new_i32(); -} - -/* Release a temporary variable. */ -static void dead_tmp(TCGv tmp) -{ - tcg_temp_free(tmp); - num_temps--; -} - -static inline TCGv load_cpu_offset(int offset) -{ - TCGv tmp = new_tmp(); - tcg_gen_ld_i32(tmp, cpu_env, offset); - return tmp; -} - -#define load_cpu_field(name) load_cpu_offset(offsetof(CPUUniCore32State, name)) - -static inline void store_cpu_offset(TCGv var, int offset) -{ - tcg_gen_st_i32(var, cpu_env, offset); - dead_tmp(var); -} - -#define store_cpu_field(var, name) \ - store_cpu_offset(var, offsetof(CPUUniCore32State, name)) - -/* Set a variable to the value of a CPU register. */ -static void load_reg_var(DisasContext *s, TCGv var, int reg) -{ - if (reg == 31) { - uint32_t addr; - /* normaly, since we updated PC */ - addr = (long)s->pc; - tcg_gen_movi_i32(var, addr); - } else { - tcg_gen_mov_i32(var, cpu_R[reg]); - } -} - -/* Create a new temporary and set it to the value of a CPU register. */ -static inline TCGv load_reg(DisasContext *s, int reg) -{ - TCGv tmp = new_tmp(); - load_reg_var(s, tmp, reg); - return tmp; -} - -/* Set a CPU register. The source must be a temporary and will be - marked as dead. */ -static void store_reg(DisasContext *s, int reg, TCGv var) -{ - if (reg == 31) { - tcg_gen_andi_i32(var, var, ~3); - s->is_jmp = DISAS_JUMP; - } - tcg_gen_mov_i32(cpu_R[reg], var); - dead_tmp(var); -} - -/* Value extensions. */ -#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) -#define gen_uxth(var) tcg_gen_ext16u_i32(var, var) -#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) -#define gen_sxth(var) tcg_gen_ext16s_i32(var, var) - -#define UCOP_REG_M (((insn) >> 0) & 0x1f) -#define UCOP_REG_N (((insn) >> 19) & 0x1f) -#define UCOP_REG_D (((insn) >> 14) & 0x1f) -#define UCOP_REG_S (((insn) >> 9) & 0x1f) -#define UCOP_REG_LO (((insn) >> 14) & 0x1f) -#define UCOP_REG_HI (((insn) >> 9) & 0x1f) -#define UCOP_SH_OP (((insn) >> 6) & 0x03) -#define UCOP_SH_IM (((insn) >> 9) & 0x1f) -#define UCOP_OPCODES (((insn) >> 25) & 0x0f) -#define UCOP_IMM_9 (((insn) >> 0) & 0x1ff) -#define UCOP_IMM10 (((insn) >> 0) & 0x3ff) -#define UCOP_IMM14 (((insn) >> 0) & 0x3fff) -#define UCOP_COND (((insn) >> 25) & 0x0f) -#define UCOP_CMOV_COND (((insn) >> 19) & 0x0f) -#define UCOP_CPNUM (((insn) >> 10) & 0x0f) -#define UCOP_UCF64_FMT (((insn) >> 24) & 0x03) -#define UCOP_UCF64_FUNC (((insn) >> 6) & 0x0f) -#define UCOP_UCF64_COND (((insn) >> 6) & 0x0f) - -#define UCOP_SET(i) ((insn) & (1 << (i))) -#define UCOP_SET_P UCOP_SET(28) -#define UCOP_SET_U UCOP_SET(27) -#define UCOP_SET_B UCOP_SET(26) -#define UCOP_SET_W UCOP_SET(25) -#define UCOP_SET_L UCOP_SET(24) -#define UCOP_SET_S UCOP_SET(24) - -#define ILLEGAL cpu_abort(env_cpu(env), \ - "Illegal UniCore32 instruction %x at line %d!", \ - insn, __LINE__) - -#ifndef CONFIG_USER_ONLY -static void disas_cp0_insn(CPUUniCore32State *env, DisasContext *s, - uint32_t insn) -{ - TCGv tmp, tmp2, tmp3; - if ((insn & 0xfe000000) == 0xe0000000) { - tmp2 = new_tmp(); - tmp3 = new_tmp(); - tcg_gen_movi_i32(tmp2, UCOP_REG_N); - tcg_gen_movi_i32(tmp3, UCOP_IMM10); - if (UCOP_SET_L) { - tmp = new_tmp(); - gen_helper_cp0_get(tmp, cpu_env, tmp2, tmp3); - store_reg(s, UCOP_REG_D, tmp); - } else { - tmp = load_reg(s, UCOP_REG_D); - gen_helper_cp0_set(cpu_env, tmp, tmp2, tmp3); - dead_tmp(tmp); - } - dead_tmp(tmp2); - dead_tmp(tmp3); - return; - } - ILLEGAL; -} - -static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s, - uint32_t insn) -{ - TCGv tmp; - - if ((insn & 0xff003fff) == 0xe1000400) { - /* - * movc rd, pp.nn, #imm9 - * rd: UCOP_REG_D - * nn: UCOP_REG_N (must be 0) - * imm9: 0 - */ - if (UCOP_REG_N == 0) { - tmp = new_tmp(); - tcg_gen_movi_i32(tmp, 0); - store_reg(s, UCOP_REG_D, tmp); - return; - } else { - ILLEGAL; - } - } - if ((insn & 0xff003fff) == 0xe0000401) { - /* - * movc pp.nn, rn, #imm9 - * rn: UCOP_REG_D - * nn: UCOP_REG_N (must be 1) - * imm9: 1 - */ - if (UCOP_REG_N == 1) { - tmp = load_reg(s, UCOP_REG_D); - gen_helper_cp1_putc(tmp); - dead_tmp(tmp); - return; - } else { - ILLEGAL; - } - } - ILLEGAL; -} -#endif - -static inline void gen_set_asr(TCGv var, uint32_t mask) -{ - TCGv tmp_mask = tcg_const_i32(mask); - gen_helper_asr_write(cpu_env, var, tmp_mask); - tcg_temp_free_i32(tmp_mask); -} -/* Set NZCV flags from the high 4 bits of var. */ -#define gen_set_nzcv(var) gen_set_asr(var, ASR_NZCV) - -static void gen_exception(int excp) -{ - TCGv tmp = new_tmp(); - tcg_gen_movi_i32(tmp, excp); - gen_helper_exception(cpu_env, tmp); - dead_tmp(tmp); -} - -#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, CF)) - -/* Set CF to the top bit of var. */ -static void gen_set_CF_bit31(TCGv var) -{ - TCGv tmp = new_tmp(); - tcg_gen_shri_i32(tmp, var, 31); - gen_set_CF(tmp); - dead_tmp(tmp); -} - -/* Set N and Z flags from var. */ -static inline void gen_logic_CC(TCGv var) -{ - tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, NF)); - tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, ZF)); -} - -/* dest = T0 + T1 + CF. */ -static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) -{ - TCGv tmp; - tcg_gen_add_i32(dest, t0, t1); - tmp = load_cpu_field(CF); - tcg_gen_add_i32(dest, dest, tmp); - dead_tmp(tmp); -} - -/* dest = T0 - T1 + CF - 1. */ -static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) -{ - TCGv tmp; - tcg_gen_sub_i32(dest, t0, t1); - tmp = load_cpu_field(CF); - tcg_gen_add_i32(dest, dest, tmp); - tcg_gen_subi_i32(dest, dest, 1); - dead_tmp(tmp); -} - -static void shifter_out_im(TCGv var, int shift) -{ - TCGv tmp = new_tmp(); - if (shift == 0) { - tcg_gen_andi_i32(tmp, var, 1); - } else { - tcg_gen_shri_i32(tmp, var, shift); - if (shift != 31) { - tcg_gen_andi_i32(tmp, tmp, 1); - } - } - gen_set_CF(tmp); - dead_tmp(tmp); -} - -/* Shift by immediate. Includes special handling for shift == 0. */ -static inline void gen_uc32_shift_im(TCGv var, int shiftop, int shift, - int flags) -{ - switch (shiftop) { - case 0: /* LSL */ - if (shift != 0) { - if (flags) { - shifter_out_im(var, 32 - shift); - } - tcg_gen_shli_i32(var, var, shift); - } - break; - case 1: /* LSR */ - if (shift == 0) { - if (flags) { - tcg_gen_shri_i32(var, var, 31); - gen_set_CF(var); - } - tcg_gen_movi_i32(var, 0); - } else { - if (flags) { - shifter_out_im(var, shift - 1); - } - tcg_gen_shri_i32(var, var, shift); - } - break; - case 2: /* ASR */ - if (shift == 0) { - shift = 32; - } - if (flags) { - shifter_out_im(var, shift - 1); - } - if (shift == 32) { - shift = 31; - } - tcg_gen_sari_i32(var, var, shift); - break; - case 3: /* ROR/RRX */ - if (shift != 0) { - if (flags) { - shifter_out_im(var, shift - 1); - } - tcg_gen_rotri_i32(var, var, shift); break; - } else { - TCGv tmp = load_cpu_field(CF); - if (flags) { - shifter_out_im(var, 0); - } - tcg_gen_shri_i32(var, var, 1); - tcg_gen_shli_i32(tmp, tmp, 31); - tcg_gen_or_i32(var, var, tmp); - dead_tmp(tmp); - } - } -}; - -static inline void gen_uc32_shift_reg(TCGv var, int shiftop, - TCGv shift, int flags) -{ - if (flags) { - switch (shiftop) { - case 0: - gen_helper_shl_cc(var, cpu_env, var, shift); - break; - case 1: - gen_helper_shr_cc(var, cpu_env, var, shift); - break; - case 2: - gen_helper_sar_cc(var, cpu_env, var, shift); - break; - case 3: - gen_helper_ror_cc(var, cpu_env, var, shift); - break; - } - } else { - switch (shiftop) { - case 0: - gen_helper_shl(var, var, shift); - break; - case 1: - gen_helper_shr(var, var, shift); - break; - case 2: - gen_helper_sar(var, var, shift); - break; - case 3: - tcg_gen_andi_i32(shift, shift, 0x1f); - tcg_gen_rotr_i32(var, var, shift); - break; - } - } - dead_tmp(shift); -} - -static void gen_test_cc(int cc, TCGLabel *label) -{ - TCGv tmp; - TCGv tmp2; - TCGLabel *inv; - - switch (cc) { - case 0: /* eq: Z */ - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - break; - case 1: /* ne: !Z */ - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); - break; - case 2: /* cs: C */ - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); - break; - case 3: /* cc: !C */ - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - break; - case 4: /* mi: N */ - tmp = load_cpu_field(NF); - tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); - break; - case 5: /* pl: !N */ - tmp = load_cpu_field(NF); - tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); - break; - case 6: /* vs: V */ - tmp = load_cpu_field(VF); - tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); - break; - case 7: /* vc: !V */ - tmp = load_cpu_field(VF); - tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); - break; - case 8: /* hi: C && !Z */ - inv = gen_new_label(); - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); - dead_tmp(tmp); - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); - gen_set_label(inv); - break; - case 9: /* ls: !C || Z */ - tmp = load_cpu_field(CF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - dead_tmp(tmp); - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - break; - case 10: /* ge: N == V -> N ^ V == 0 */ - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - dead_tmp(tmp2); - tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); - break; - case 11: /* lt: N != V -> N ^ V != 0 */ - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - dead_tmp(tmp2); - tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); - break; - case 12: /* gt: !Z && N == V */ - inv = gen_new_label(); - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); - dead_tmp(tmp); - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - dead_tmp(tmp2); - tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); - gen_set_label(inv); - break; - case 13: /* le: Z || N != V */ - tmp = load_cpu_field(ZF); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); - dead_tmp(tmp); - tmp = load_cpu_field(VF); - tmp2 = load_cpu_field(NF); - tcg_gen_xor_i32(tmp, tmp, tmp2); - dead_tmp(tmp2); - tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); - break; - default: - fprintf(stderr, "Bad condition code 0x%x\n", cc); - abort(); - } - dead_tmp(tmp); -} - -static const uint8_t table_logic_cc[16] = { - 1, /* and */ 1, /* xor */ 0, /* sub */ 0, /* rsb */ - 0, /* add */ 0, /* adc */ 0, /* sbc */ 0, /* rsc */ - 1, /* andl */ 1, /* xorl */ 0, /* cmp */ 0, /* cmn */ - 1, /* orr */ 1, /* mov */ 1, /* bic */ 1, /* mvn */ -}; - -/* Set PC state from an immediate address. */ -static inline void gen_bx_im(DisasContext *s, uint32_t addr) -{ - s->is_jmp = DISAS_UPDATE; - tcg_gen_movi_i32(cpu_R[31], addr & ~3); -} - -/* Set PC state from var. var is marked as dead. */ -static inline void gen_bx(DisasContext *s, TCGv var) -{ - s->is_jmp = DISAS_UPDATE; - tcg_gen_andi_i32(cpu_R[31], var, ~3); - dead_tmp(var); -} - -static inline void store_reg_bx(DisasContext *s, int reg, TCGv var) -{ - store_reg(s, reg, var); -} - -static inline TCGv gen_ld8s(TCGv addr, int index) -{ - TCGv tmp = new_tmp(); - tcg_gen_qemu_ld8s(tmp, addr, index); - return tmp; -} - -static inline TCGv gen_ld8u(TCGv addr, int index) -{ - TCGv tmp = new_tmp(); - tcg_gen_qemu_ld8u(tmp, addr, index); - return tmp; -} - -static inline TCGv gen_ld16s(TCGv addr, int index) -{ - TCGv tmp = new_tmp(); - tcg_gen_qemu_ld16s(tmp, addr, index); - return tmp; -} - -static inline TCGv gen_ld16u(TCGv addr, int index) -{ - TCGv tmp = new_tmp(); - tcg_gen_qemu_ld16u(tmp, addr, index); - return tmp; -} - -static inline TCGv gen_ld32(TCGv addr, int index) -{ - TCGv tmp = new_tmp(); - tcg_gen_qemu_ld32u(tmp, addr, index); - return tmp; -} - -static inline void gen_st8(TCGv val, TCGv addr, int index) -{ - tcg_gen_qemu_st8(val, addr, index); - dead_tmp(val); -} - -static inline void gen_st16(TCGv val, TCGv addr, int index) -{ - tcg_gen_qemu_st16(val, addr, index); - dead_tmp(val); -} - -static inline void gen_st32(TCGv val, TCGv addr, int index) -{ - tcg_gen_qemu_st32(val, addr, index); - dead_tmp(val); -} - -static inline void gen_set_pc_im(uint32_t val) -{ - tcg_gen_movi_i32(cpu_R[31], val); -} - -/* Force a TB lookup after an instruction that changes the CPU state. */ -static inline void gen_lookup_tb(DisasContext *s) -{ - tcg_gen_movi_i32(cpu_R[31], s->pc & ~1); - s->is_jmp = DISAS_UPDATE; -} - -static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, - TCGv var) -{ - int val; - TCGv offset; - - if (UCOP_SET(29)) { - /* immediate */ - val = UCOP_IMM14; - if (!UCOP_SET_U) { - val = -val; - } - if (val != 0) { - tcg_gen_addi_i32(var, var, val); - } - } else { - /* shift/register */ - offset = load_reg(s, UCOP_REG_M); - gen_uc32_shift_im(offset, UCOP_SH_OP, UCOP_SH_IM, 0); - if (!UCOP_SET_U) { - tcg_gen_sub_i32(var, var, offset); - } else { - tcg_gen_add_i32(var, var, offset); - } - dead_tmp(offset); - } -} - -static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, - TCGv var) -{ - int val; - TCGv offset; - - if (UCOP_SET(26)) { - /* immediate */ - val = (insn & 0x1f) | ((insn >> 4) & 0x3e0); - if (!UCOP_SET_U) { - val = -val; - } - if (val != 0) { - tcg_gen_addi_i32(var, var, val); - } - } else { - /* register */ - offset = load_reg(s, UCOP_REG_M); - if (!UCOP_SET_U) { - tcg_gen_sub_i32(var, var, offset); - } else { - tcg_gen_add_i32(var, var, offset); - } - dead_tmp(offset); - } -} - -static inline long ucf64_reg_offset(int reg) -{ - if (reg & 1) { - return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1]) - + offsetof(CPU_DoubleU, l.upper); - } else { - return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1]) - + offsetof(CPU_DoubleU, l.lower); - } -} - -#define ucf64_gen_ld32(reg) load_cpu_offset(ucf64_reg_offset(reg)) -#define ucf64_gen_st32(var, reg) store_cpu_offset(var, ucf64_reg_offset(reg)) - -/* UniCore-F64 single load/store I_offset */ -static void do_ucf64_ldst_i(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - int offset; - TCGv tmp; - TCGv addr; - - addr = load_reg(s, UCOP_REG_N); - if (!UCOP_SET_P && !UCOP_SET_W) { - ILLEGAL; - } - - if (UCOP_SET_P) { - offset = UCOP_IMM10 << 2; - if (!UCOP_SET_U) { - offset = -offset; - } - if (offset != 0) { - tcg_gen_addi_i32(addr, addr, offset); - } - } - - if (UCOP_SET_L) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); - ucf64_gen_st32(tmp, UCOP_REG_D); - } else { /* store */ - tmp = ucf64_gen_ld32(UCOP_REG_D); - gen_st32(tmp, addr, IS_USER(s)); - } - - if (!UCOP_SET_P) { - offset = UCOP_IMM10 << 2; - if (!UCOP_SET_U) { - offset = -offset; - } - if (offset != 0) { - tcg_gen_addi_i32(addr, addr, offset); - } - } - if (UCOP_SET_W) { - store_reg(s, UCOP_REG_N, addr); - } else { - dead_tmp(addr); - } -} - -/* UniCore-F64 load/store multiple words */ -static void do_ucf64_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - unsigned int i; - int j, n, freg; - TCGv tmp; - TCGv addr; - - if (UCOP_REG_D != 0) { - ILLEGAL; - } - if (UCOP_REG_N == 31) { - ILLEGAL; - } - if ((insn << 24) == 0) { - ILLEGAL; - } - - addr = load_reg(s, UCOP_REG_N); - - n = 0; - for (i = 0; i < 8; i++) { - if (UCOP_SET(i)) { - n++; - } - } - - if (UCOP_SET_U) { - if (UCOP_SET_P) { /* pre increment */ - tcg_gen_addi_i32(addr, addr, 4); - } /* unnecessary to do anything when post increment */ - } else { - if (UCOP_SET_P) { /* pre decrement */ - tcg_gen_addi_i32(addr, addr, -(n * 4)); - } else { /* post decrement */ - if (n != 1) { - tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); - } - } - } - - freg = ((insn >> 8) & 3) << 3; /* freg should be 0, 8, 16, 24 */ - - for (i = 0, j = 0; i < 8; i++, freg++) { - if (!UCOP_SET(i)) { - continue; - } - - if (UCOP_SET_L) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); - ucf64_gen_st32(tmp, freg); - } else { /* store */ - tmp = ucf64_gen_ld32(freg); - gen_st32(tmp, addr, IS_USER(s)); - } - - j++; - /* unnecessary to add after the last transfer */ - if (j != n) { - tcg_gen_addi_i32(addr, addr, 4); - } - } - - if (UCOP_SET_W) { /* write back */ - if (UCOP_SET_U) { - if (!UCOP_SET_P) { /* post increment */ - tcg_gen_addi_i32(addr, addr, 4); - } /* unnecessary to do anything when pre increment */ - } else { - if (UCOP_SET_P) { - /* pre decrement */ - if (n != 1) { - tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); - } - } else { - /* post decrement */ - tcg_gen_addi_i32(addr, addr, -(n * 4)); - } - } - store_reg(s, UCOP_REG_N, addr); - } else { - dead_tmp(addr); - } -} - -/* UniCore-F64 mrc/mcr */ -static void do_ucf64_trans(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - TCGv tmp; - - if ((insn & 0xfe0003ff) == 0xe2000000) { - /* control register */ - if ((UCOP_REG_N != UC32_UCF64_FPSCR) || (UCOP_REG_D == 31)) { - ILLEGAL; - } - if (UCOP_SET(24)) { - /* CFF */ - tmp = new_tmp(); - gen_helper_ucf64_get_fpscr(tmp, cpu_env); - store_reg(s, UCOP_REG_D, tmp); - } else { - /* CTF */ - tmp = load_reg(s, UCOP_REG_D); - gen_helper_ucf64_set_fpscr(cpu_env, tmp); - dead_tmp(tmp); - gen_lookup_tb(s); - } - return; - } - if ((insn & 0xfe0003ff) == 0xe0000000) { - /* general register */ - if (UCOP_REG_D == 31) { - ILLEGAL; - } - if (UCOP_SET(24)) { /* MFF */ - tmp = ucf64_gen_ld32(UCOP_REG_N); - store_reg(s, UCOP_REG_D, tmp); - } else { /* MTF */ - tmp = load_reg(s, UCOP_REG_D); - ucf64_gen_st32(tmp, UCOP_REG_N); - } - return; - } - if ((insn & 0xfb000000) == 0xe9000000) { - /* MFFC */ - if (UCOP_REG_D != 31) { - ILLEGAL; - } - if (UCOP_UCF64_COND & 0x8) { - ILLEGAL; - } - - tmp = new_tmp(); - tcg_gen_movi_i32(tmp, UCOP_UCF64_COND); - if (UCOP_SET(26)) { - tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N)); - tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, tmp, cpu_env); - } else { - tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N)); - tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, tmp, cpu_env); - } - dead_tmp(tmp); - return; - } - ILLEGAL; -} - -/* UniCore-F64 convert instructions */ -static void do_ucf64_fcvt(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - if (UCOP_UCF64_FMT == 3) { - ILLEGAL; - } - if (UCOP_REG_N != 0) { - ILLEGAL; - } - switch (UCOP_UCF64_FUNC) { - case 0: /* cvt.s */ - switch (UCOP_UCF64_FMT) { - case 1 /* d */: - tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_df2sf(cpu_F0s, cpu_F0d, cpu_env); - tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); - break; - case 2 /* w */: - tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_si2sf(cpu_F0s, cpu_F0s, cpu_env); - tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); - break; - default /* s */: - ILLEGAL; - break; - } - break; - case 1: /* cvt.d */ - switch (UCOP_UCF64_FMT) { - case 0 /* s */: - tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_sf2df(cpu_F0d, cpu_F0s, cpu_env); - tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D)); - break; - case 2 /* w */: - tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_si2df(cpu_F0d, cpu_F0s, cpu_env); - tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D)); - break; - default /* d */: - ILLEGAL; - break; - } - break; - case 4: /* cvt.w */ - switch (UCOP_UCF64_FMT) { - case 0 /* s */: - tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_sf2si(cpu_F0s, cpu_F0s, cpu_env); - tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); - break; - case 1 /* d */: - tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - gen_helper_ucf64_df2si(cpu_F0s, cpu_F0d, cpu_env); - tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D)); - break; - default /* w */: - ILLEGAL; - break; - } - break; - default: - ILLEGAL; - } -} - -/* UniCore-F64 compare instructions */ -static void do_ucf64_fcmp(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - if (UCOP_SET(25)) { - ILLEGAL; - } - if (UCOP_REG_D != 0) { - ILLEGAL; - } - - ILLEGAL; /* TODO */ - if (UCOP_SET(24)) { - tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N)); - tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - /* gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, cpu_env); */ - } else { - tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N)); - tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M)); - /* gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, cpu_env); */ - } -} - -#define gen_helper_ucf64_movs(x, y) do { } while (0) -#define gen_helper_ucf64_movd(x, y) do { } while (0) - -#define UCF64_OP1(name) do { \ - if (UCOP_REG_N != 0) { \ - ILLEGAL; \ - } \ - switch (UCOP_UCF64_FMT) { \ - case 0 /* s */: \ - tcg_gen_ld_i32(cpu_F0s, cpu_env, \ - ucf64_reg_offset(UCOP_REG_M)); \ - gen_helper_ucf64_##name##s(cpu_F0s, cpu_F0s); \ - tcg_gen_st_i32(cpu_F0s, cpu_env, \ - ucf64_reg_offset(UCOP_REG_D)); \ - break; \ - case 1 /* d */: \ - tcg_gen_ld_i64(cpu_F0d, cpu_env, \ - ucf64_reg_offset(UCOP_REG_M)); \ - gen_helper_ucf64_##name##d(cpu_F0d, cpu_F0d); \ - tcg_gen_st_i64(cpu_F0d, cpu_env, \ - ucf64_reg_offset(UCOP_REG_D)); \ - break; \ - case 2 /* w */: \ - ILLEGAL; \ - break; \ - } \ - } while (0) - -#define UCF64_OP2(name) do { \ - switch (UCOP_UCF64_FMT) { \ - case 0 /* s */: \ - tcg_gen_ld_i32(cpu_F0s, cpu_env, \ - ucf64_reg_offset(UCOP_REG_N)); \ - tcg_gen_ld_i32(cpu_F1s, cpu_env, \ - ucf64_reg_offset(UCOP_REG_M)); \ - gen_helper_ucf64_##name##s(cpu_F0s, \ - cpu_F0s, cpu_F1s, cpu_env); \ - tcg_gen_st_i32(cpu_F0s, cpu_env, \ - ucf64_reg_offset(UCOP_REG_D)); \ - break; \ - case 1 /* d */: \ - tcg_gen_ld_i64(cpu_F0d, cpu_env, \ - ucf64_reg_offset(UCOP_REG_N)); \ - tcg_gen_ld_i64(cpu_F1d, cpu_env, \ - ucf64_reg_offset(UCOP_REG_M)); \ - gen_helper_ucf64_##name##d(cpu_F0d, \ - cpu_F0d, cpu_F1d, cpu_env); \ - tcg_gen_st_i64(cpu_F0d, cpu_env, \ - ucf64_reg_offset(UCOP_REG_D)); \ - break; \ - case 2 /* w */: \ - ILLEGAL; \ - break; \ - } \ - } while (0) - -/* UniCore-F64 data processing */ -static void do_ucf64_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - if (UCOP_UCF64_FMT == 3) { - ILLEGAL; - } - switch (UCOP_UCF64_FUNC) { - case 0: /* add */ - UCF64_OP2(add); - break; - case 1: /* sub */ - UCF64_OP2(sub); - break; - case 2: /* mul */ - UCF64_OP2(mul); - break; - case 4: /* div */ - UCF64_OP2(div); - break; - case 5: /* abs */ - UCF64_OP1(abs); - break; - case 6: /* mov */ - UCF64_OP1(mov); - break; - case 7: /* neg */ - UCF64_OP1(neg); - break; - default: - ILLEGAL; - } -} - -/* Disassemble an F64 instruction */ -static void disas_ucf64_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - if (!UCOP_SET(29)) { - if (UCOP_SET(26)) { - do_ucf64_ldst_m(env, s, insn); - } else { - do_ucf64_ldst_i(env, s, insn); - } - } else { - if (UCOP_SET(5)) { - switch ((insn >> 26) & 0x3) { - case 0: - do_ucf64_datap(env, s, insn); - break; - case 1: - ILLEGAL; - break; - case 2: - do_ucf64_fcvt(env, s, insn); - break; - case 3: - do_ucf64_fcmp(env, s, insn); - break; - } - } else { - do_ucf64_trans(env, s, insn); - } - } -} - -static inline bool use_goto_tb(DisasContext *s, uint32_t dest) -{ -#ifndef CONFIG_USER_ONLY - return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); -#else - return true; -#endif -} - -static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) -{ - if (use_goto_tb(s, dest)) { - tcg_gen_goto_tb(n); - gen_set_pc_im(dest); - tcg_gen_exit_tb(s->tb, n); - } else { - gen_set_pc_im(dest); - tcg_gen_exit_tb(NULL, 0); - } -} - -static inline void gen_jmp(DisasContext *s, uint32_t dest) -{ - if (unlikely(s->singlestep_enabled)) { - /* An indirect jump so that we still trigger the debug exception. */ - gen_bx_im(s, dest); - } else { - gen_goto_tb(s, 0, dest); - s->is_jmp = DISAS_TB_JUMP; - } -} - -/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */ -static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0) -{ - TCGv tmp; - if (bsr) { - /* ??? This is also undefined in system mode. */ - if (IS_USER(s)) { - return 1; - } - - tmp = load_cpu_field(bsr); - tcg_gen_andi_i32(tmp, tmp, ~mask); - tcg_gen_andi_i32(t0, t0, mask); - tcg_gen_or_i32(tmp, tmp, t0); - store_cpu_field(tmp, bsr); - } else { - gen_set_asr(t0, mask); - } - dead_tmp(t0); - gen_lookup_tb(s); - return 0; -} - -/* Generate an old-style exception return. Marks pc as dead. */ -static void gen_exception_return(DisasContext *s, TCGv pc) -{ - TCGv tmp; - store_reg(s, 31, pc); - tmp = load_cpu_field(bsr); - gen_set_asr(tmp, 0xffffffff); - dead_tmp(tmp); - s->is_jmp = DISAS_UPDATE; -} - -static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s, - uint32_t insn) -{ - switch (UCOP_CPNUM) { -#ifndef CONFIG_USER_ONLY - case 0: - disas_cp0_insn(env, s, insn); - break; - case 1: - disas_ocd_insn(env, s, insn); - break; -#endif - case 2: - disas_ucf64_insn(env, s, insn); - break; - default: - /* Unknown coprocessor. */ - cpu_abort(env_cpu(env), "Unknown coprocessor!"); - } -} - -/* data processing instructions */ -static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - TCGv tmp; - TCGv tmp2; - int logic_cc; - - if (UCOP_OPCODES == 0x0f || UCOP_OPCODES == 0x0d) { - if (UCOP_SET(23)) { /* CMOV instructions */ - if ((UCOP_CMOV_COND == 0xe) || (UCOP_CMOV_COND == 0xf)) { - ILLEGAL; - } - /* if not always execute, we generate a conditional jump to - next instruction */ - s->condlabel = gen_new_label(); - gen_test_cc(UCOP_CMOV_COND ^ 1, s->condlabel); - s->condjmp = 1; - } - } - - logic_cc = table_logic_cc[UCOP_OPCODES] & (UCOP_SET_S >> 24); - - if (UCOP_SET(29)) { - unsigned int val; - /* immediate operand */ - val = UCOP_IMM_9; - if (UCOP_SH_IM) { - val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM)); - } - tmp2 = new_tmp(); - tcg_gen_movi_i32(tmp2, val); - if (logic_cc && UCOP_SH_IM) { - gen_set_CF_bit31(tmp2); - } - } else { - /* register */ - tmp2 = load_reg(s, UCOP_REG_M); - if (UCOP_SET(5)) { - tmp = load_reg(s, UCOP_REG_S); - gen_uc32_shift_reg(tmp2, UCOP_SH_OP, tmp, logic_cc); - } else { - gen_uc32_shift_im(tmp2, UCOP_SH_OP, UCOP_SH_IM, logic_cc); - } - } - - if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) { - tmp = load_reg(s, UCOP_REG_N); - } else { - tmp = NULL; - } - - switch (UCOP_OPCODES) { - case 0x00: - tcg_gen_and_i32(tmp, tmp, tmp2); - if (logic_cc) { - gen_logic_CC(tmp); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x01: - tcg_gen_xor_i32(tmp, tmp, tmp2); - if (logic_cc) { - gen_logic_CC(tmp); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x02: - if (UCOP_SET_S && UCOP_REG_D == 31) { - /* SUBS r31, ... is used for exception return. */ - if (IS_USER(s)) { - ILLEGAL; - } - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); - gen_exception_return(s, tmp); - } else { - if (UCOP_SET_S) { - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); - } else { - tcg_gen_sub_i32(tmp, tmp, tmp2); - } - store_reg_bx(s, UCOP_REG_D, tmp); - } - break; - case 0x03: - if (UCOP_SET_S) { - gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp); - } else { - tcg_gen_sub_i32(tmp, tmp2, tmp); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x04: - if (UCOP_SET_S) { - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); - } else { - tcg_gen_add_i32(tmp, tmp, tmp2); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x05: - if (UCOP_SET_S) { - gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); - } else { - gen_add_carry(tmp, tmp, tmp2); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x06: - if (UCOP_SET_S) { - gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); - } else { - gen_sub_carry(tmp, tmp, tmp2); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x07: - if (UCOP_SET_S) { - gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp); - } else { - gen_sub_carry(tmp, tmp2, tmp); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x08: - if (UCOP_SET_S) { - tcg_gen_and_i32(tmp, tmp, tmp2); - gen_logic_CC(tmp); - } - dead_tmp(tmp); - break; - case 0x09: - if (UCOP_SET_S) { - tcg_gen_xor_i32(tmp, tmp, tmp2); - gen_logic_CC(tmp); - } - dead_tmp(tmp); - break; - case 0x0a: - if (UCOP_SET_S) { - gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); - } - dead_tmp(tmp); - break; - case 0x0b: - if (UCOP_SET_S) { - gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); - } - dead_tmp(tmp); - break; - case 0x0c: - tcg_gen_or_i32(tmp, tmp, tmp2); - if (logic_cc) { - gen_logic_CC(tmp); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - case 0x0d: - if (logic_cc && UCOP_REG_D == 31) { - /* MOVS r31, ... is used for exception return. */ - if (IS_USER(s)) { - ILLEGAL; - } - gen_exception_return(s, tmp2); - } else { - if (logic_cc) { - gen_logic_CC(tmp2); - } - store_reg_bx(s, UCOP_REG_D, tmp2); - } - break; - case 0x0e: - tcg_gen_andc_i32(tmp, tmp, tmp2); - if (logic_cc) { - gen_logic_CC(tmp); - } - store_reg_bx(s, UCOP_REG_D, tmp); - break; - default: - case 0x0f: - tcg_gen_not_i32(tmp2, tmp2); - if (logic_cc) { - gen_logic_CC(tmp2); - } - store_reg_bx(s, UCOP_REG_D, tmp2); - break; - } - if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) { - dead_tmp(tmp2); - } -} - -/* multiply */ -static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - TCGv tmp, tmp2, tmp3, tmp4; - - if (UCOP_SET(27)) { - /* 64 bit mul */ - tmp = load_reg(s, UCOP_REG_M); - tmp2 = load_reg(s, UCOP_REG_N); - if (UCOP_SET(26)) { - tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2); - } else { - tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2); - } - if (UCOP_SET(25)) { /* mult accumulate */ - tmp3 = load_reg(s, UCOP_REG_LO); - tmp4 = load_reg(s, UCOP_REG_HI); - tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, tmp3, tmp4); - dead_tmp(tmp3); - dead_tmp(tmp4); - } - store_reg(s, UCOP_REG_LO, tmp); - store_reg(s, UCOP_REG_HI, tmp2); - } else { - /* 32 bit mul */ - tmp = load_reg(s, UCOP_REG_M); - tmp2 = load_reg(s, UCOP_REG_N); - tcg_gen_mul_i32(tmp, tmp, tmp2); - dead_tmp(tmp2); - if (UCOP_SET(25)) { - /* Add */ - tmp2 = load_reg(s, UCOP_REG_S); - tcg_gen_add_i32(tmp, tmp, tmp2); - dead_tmp(tmp2); - } - if (UCOP_SET_S) { - gen_logic_CC(tmp); - } - store_reg(s, UCOP_REG_D, tmp); - } -} - -/* miscellaneous instructions */ -static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - unsigned int val; - TCGv tmp; - - if ((insn & 0xffffffe0) == 0x10ffc120) { - /* Trivial implementation equivalent to bx. */ - tmp = load_reg(s, UCOP_REG_M); - gen_bx(s, tmp); - return; - } - - if ((insn & 0xfbffc000) == 0x30ffc000) { - /* PSR = immediate */ - val = UCOP_IMM_9; - if (UCOP_SH_IM) { - val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM)); - } - tmp = new_tmp(); - tcg_gen_movi_i32(tmp, val); - if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) { - ILLEGAL; - } - return; - } - - if ((insn & 0xfbffffe0) == 0x12ffc020) { - /* PSR.flag = reg */ - tmp = load_reg(s, UCOP_REG_M); - if (gen_set_psr(s, ASR_NZCV, UCOP_SET_B, tmp)) { - ILLEGAL; - } - return; - } - - if ((insn & 0xfbffffe0) == 0x10ffc020) { - /* PSR = reg */ - tmp = load_reg(s, UCOP_REG_M); - if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) { - ILLEGAL; - } - return; - } - - if ((insn & 0xfbf83fff) == 0x10f80000) { - /* reg = PSR */ - if (UCOP_SET_B) { - if (IS_USER(s)) { - ILLEGAL; - } - tmp = load_cpu_field(bsr); - } else { - tmp = new_tmp(); - gen_helper_asr_read(tmp, cpu_env); - } - store_reg(s, UCOP_REG_D, tmp); - return; - } - - if ((insn & 0xfbf83fe0) == 0x12f80120) { - /* clz */ - tmp = load_reg(s, UCOP_REG_M); - if (UCOP_SET(26)) { - /* clo */ - tcg_gen_not_i32(tmp, tmp); - } - tcg_gen_clzi_i32(tmp, tmp, 32); - store_reg(s, UCOP_REG_D, tmp); - return; - } - - /* otherwise */ - ILLEGAL; -} - -/* load/store I_offset and R_offset */ -static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - unsigned int mmu_idx; - TCGv tmp; - TCGv tmp2; - - tmp2 = load_reg(s, UCOP_REG_N); - mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); - - /* immediate */ - if (UCOP_SET_P) { - gen_add_data_offset(s, insn, tmp2); - } - - if (UCOP_SET_L) { - /* load */ - if (UCOP_SET_B) { - tmp = gen_ld8u(tmp2, mmu_idx); - } else { - tmp = gen_ld32(tmp2, mmu_idx); - } - } else { - /* store */ - tmp = load_reg(s, UCOP_REG_D); - if (UCOP_SET_B) { - gen_st8(tmp, tmp2, mmu_idx); - } else { - gen_st32(tmp, tmp2, mmu_idx); - } - } - if (!UCOP_SET_P) { - gen_add_data_offset(s, insn, tmp2); - store_reg(s, UCOP_REG_N, tmp2); - } else if (UCOP_SET_W) { - store_reg(s, UCOP_REG_N, tmp2); - } else { - dead_tmp(tmp2); - } - if (UCOP_SET_L) { - /* Complete the load. */ - if (UCOP_REG_D == 31) { - gen_bx(s, tmp); - } else { - store_reg(s, UCOP_REG_D, tmp); - } - } -} - -/* SWP instruction */ -static void do_swap(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - TCGv addr; - TCGv tmp; - TCGv tmp2; - - if ((insn & 0xff003fe0) != 0x40000120) { - ILLEGAL; - } - - /* ??? This is not really atomic. However we know - we never have multiple CPUs running in parallel, - so it is good enough. */ - addr = load_reg(s, UCOP_REG_N); - tmp = load_reg(s, UCOP_REG_M); - if (UCOP_SET_B) { - tmp2 = gen_ld8u(addr, IS_USER(s)); - gen_st8(tmp, addr, IS_USER(s)); - } else { - tmp2 = gen_ld32(addr, IS_USER(s)); - gen_st32(tmp, addr, IS_USER(s)); - } - dead_tmp(addr); - store_reg(s, UCOP_REG_D, tmp2); -} - -/* load/store hw/sb */ -static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - TCGv addr; - TCGv tmp; - - if (UCOP_SH_OP == 0) { - do_swap(env, s, insn); - return; - } - - addr = load_reg(s, UCOP_REG_N); - if (UCOP_SET_P) { - gen_add_datah_offset(s, insn, addr); - } - - if (UCOP_SET_L) { /* load */ - switch (UCOP_SH_OP) { - case 1: - tmp = gen_ld16u(addr, IS_USER(s)); - break; - case 2: - tmp = gen_ld8s(addr, IS_USER(s)); - break; - default: /* see do_swap */ - case 3: - tmp = gen_ld16s(addr, IS_USER(s)); - break; - } - } else { /* store */ - if (UCOP_SH_OP != 1) { - ILLEGAL; - } - tmp = load_reg(s, UCOP_REG_D); - gen_st16(tmp, addr, IS_USER(s)); - } - /* Perform base writeback before the loaded value to - ensure correct behavior with overlapping index registers. */ - if (!UCOP_SET_P) { - gen_add_datah_offset(s, insn, addr); - store_reg(s, UCOP_REG_N, addr); - } else if (UCOP_SET_W) { - store_reg(s, UCOP_REG_N, addr); - } else { - dead_tmp(addr); - } - if (UCOP_SET_L) { - /* Complete the load. */ - store_reg(s, UCOP_REG_D, tmp); - } -} - -/* load/store multiple words */ -static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - unsigned int val, i, mmu_idx; - int j, n, reg, user, loaded_base; - TCGv tmp; - TCGv tmp2; - TCGv addr; - TCGv loaded_var; - - if (UCOP_SET(7)) { - ILLEGAL; - } - /* XXX: store correct base if write back */ - user = 0; - if (UCOP_SET_B) { /* S bit in instruction table */ - if (IS_USER(s)) { - ILLEGAL; /* only usable in supervisor mode */ - } - if (UCOP_SET(18) == 0) { /* pc reg */ - user = 1; - } - } - - mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); - addr = load_reg(s, UCOP_REG_N); - - /* compute total size */ - loaded_base = 0; - loaded_var = NULL; - n = 0; - for (i = 0; i < 6; i++) { - if (UCOP_SET(i)) { - n++; - } - } - for (i = 9; i < 19; i++) { - if (UCOP_SET(i)) { - n++; - } - } - /* XXX: test invalid n == 0 case ? */ - if (UCOP_SET_U) { - if (UCOP_SET_P) { - /* pre increment */ - tcg_gen_addi_i32(addr, addr, 4); - } else { - /* post increment */ - } - } else { - if (UCOP_SET_P) { - /* pre decrement */ - tcg_gen_addi_i32(addr, addr, -(n * 4)); - } else { - /* post decrement */ - if (n != 1) { - tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); - } - } - } - - j = 0; - reg = UCOP_SET(6) ? 16 : 0; - for (i = 0; i < 19; i++, reg++) { - if (i == 6) { - i = i + 3; - } - if (UCOP_SET(i)) { - if (UCOP_SET_L) { /* load */ - tmp = gen_ld32(addr, mmu_idx); - if (reg == 31) { - gen_bx(s, tmp); - } else if (user) { - tmp2 = tcg_const_i32(reg); - gen_helper_set_user_reg(cpu_env, tmp2, tmp); - tcg_temp_free_i32(tmp2); - dead_tmp(tmp); - } else if (reg == UCOP_REG_N) { - loaded_var = tmp; - loaded_base = 1; - } else { - store_reg(s, reg, tmp); - } - } else { /* store */ - if (reg == 31) { - /* special case: r31 = PC + 4 */ - val = (long)s->pc; - tmp = new_tmp(); - tcg_gen_movi_i32(tmp, val); - } else if (user) { - tmp = new_tmp(); - tmp2 = tcg_const_i32(reg); - gen_helper_get_user_reg(tmp, cpu_env, tmp2); - tcg_temp_free_i32(tmp2); - } else { - tmp = load_reg(s, reg); - } - gen_st32(tmp, addr, mmu_idx); - } - j++; - /* no need to add after the last transfer */ - if (j != n) { - tcg_gen_addi_i32(addr, addr, 4); - } - } - } - if (UCOP_SET_W) { /* write back */ - if (UCOP_SET_U) { - if (UCOP_SET_P) { - /* pre increment */ - } else { - /* post increment */ - tcg_gen_addi_i32(addr, addr, 4); - } - } else { - if (UCOP_SET_P) { - /* pre decrement */ - if (n != 1) { - tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); - } - } else { - /* post decrement */ - tcg_gen_addi_i32(addr, addr, -(n * 4)); - } - } - store_reg(s, UCOP_REG_N, addr); - } else { - dead_tmp(addr); - } - if (loaded_base) { - store_reg(s, UCOP_REG_N, loaded_var); - } - if (UCOP_SET_B && !user) { - /* Restore ASR from BSR. */ - tmp = load_cpu_field(bsr); - gen_set_asr(tmp, 0xffffffff); - dead_tmp(tmp); - s->is_jmp = DISAS_UPDATE; - } -} - -/* branch (and link) */ -static void do_branch(CPUUniCore32State *env, DisasContext *s, uint32_t insn) -{ - unsigned int val; - int32_t offset; - TCGv tmp; - - if (UCOP_COND == 0xf) { - ILLEGAL; - } - - if (UCOP_COND != 0xe) { - /* if not always execute, we generate a conditional jump to - next instruction */ - s->condlabel = gen_new_label(); - gen_test_cc(UCOP_COND ^ 1, s->condlabel); - s->condjmp = 1; - } - - val = (int32_t)s->pc; - if (UCOP_SET_L) { - tmp = new_tmp(); - tcg_gen_movi_i32(tmp, val); - store_reg(s, 30, tmp); - } - offset = (((int32_t)insn << 8) >> 8); - val += (offset << 2); /* unicore is pc+4 */ - gen_jmp(s, val); -} - -static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) -{ - unsigned int insn; - - insn = cpu_ldl_code(env, s->pc); - s->pc += 4; - - /* UniCore instructions class: - * AAAB BBBC xxxx xxxx xxxx xxxD xxEx xxxx - * AAA : see switch case - * BBBB : opcodes or cond or PUBW - * C : S OR L - * D : 8 - * E : 5 - */ - switch (insn >> 29) { - case 0x0: - if (UCOP_SET(5) && UCOP_SET(8) && !UCOP_SET(28)) { - do_mult(env, s, insn); - break; - } - - if (UCOP_SET(8)) { - do_misc(env, s, insn); - break; - } - /* fallthrough */ - case 0x1: - if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) { - do_misc(env, s, insn); - break; - } - do_datap(env, s, insn); - break; - - case 0x2: - if (UCOP_SET(8) && UCOP_SET(5)) { - do_ldst_hwsb(env, s, insn); - break; - } - if (UCOP_SET(8) || UCOP_SET(5)) { - ILLEGAL; - } - /* fallthrough */ - case 0x3: - do_ldst_ir(env, s, insn); - break; - - case 0x4: - if (UCOP_SET(8)) { - ILLEGAL; /* extended instructions */ - } - do_ldst_m(env, s, insn); - break; - case 0x5: - do_branch(env, s, insn); - break; - case 0x6: - /* Coprocessor. */ - disas_coproc_insn(env, s, insn); - break; - case 0x7: - if (!UCOP_SET(28)) { - disas_coproc_insn(env, s, insn); - break; - } - if ((insn & 0xff000000) == 0xff000000) { /* syscall */ - gen_set_pc_im(s->pc); - s->is_jmp = DISAS_SYSCALL; - break; - } - ILLEGAL; - } -} - -/* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) -{ - CPUUniCore32State *env = cs->env_ptr; - DisasContext dc1, *dc = &dc1; - target_ulong pc_start; - uint32_t page_start; - int num_insns; - - /* generate intermediate code */ - num_temps = 0; - - pc_start = tb->pc; - - dc->tb = tb; - - dc->is_jmp = DISAS_NEXT; - dc->pc = pc_start; - dc->singlestep_enabled = cs->singlestep_enabled; - dc->condjmp = 0; - cpu_F0s = tcg_temp_new_i32(); - cpu_F1s = tcg_temp_new_i32(); - cpu_F0d = tcg_temp_new_i64(); - cpu_F1d = tcg_temp_new_i64(); - page_start = pc_start & TARGET_PAGE_MASK; - num_insns = 0; - -#ifndef CONFIG_USER_ONLY - if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) { - dc->user = 1; - } else { - dc->user = 0; - } -#endif - - gen_tb_start(tb); - do { - tcg_gen_insn_start(dc->pc); - num_insns++; - - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - gen_set_pc_im(dc->pc); - gen_exception(EXCP_DEBUG); - dc->is_jmp = DISAS_JUMP; - /* 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; - goto done_generating; - } - - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } - - disas_uc32_insn(env, dc); - - if (num_temps) { - fprintf(stderr, "Internal resource leak before %08x\n", dc->pc); - num_temps = 0; - } - - if (dc->condjmp && !dc->is_jmp) { - gen_set_label(dc->condlabel); - dc->condjmp = 0; - } - /* Translation stops when a conditional branch is encountered. - * Otherwise the subsequent code could get translated several times. - * Also stop translation when a page boundary is reached. This - * ensures prefetch aborts occur at the right place. */ - } while (!dc->is_jmp && !tcg_op_buf_full() && - !cs->singlestep_enabled && - !singlestep && - dc->pc - page_start < TARGET_PAGE_SIZE && - num_insns < max_insns); - - if (tb_cflags(tb) & CF_LAST_IO) { - if (dc->condjmp) { - /* FIXME: This can theoretically happen with self-modifying - code. */ - cpu_abort(cs, "IO on conditional branch instruction"); - } - } - - /* At this stage dc->condjmp will only be set when the skipped - instruction was a conditional branch or trap, and the PC has - already been written. */ - if (unlikely(cs->singlestep_enabled)) { - /* Make sure the pc is updated, and raise a debug exception. */ - if (dc->condjmp) { - if (dc->is_jmp == DISAS_SYSCALL) { - gen_exception(UC32_EXCP_PRIV); - } else { - gen_exception(EXCP_DEBUG); - } - gen_set_label(dc->condlabel); - } - if (dc->condjmp || !dc->is_jmp) { - gen_set_pc_im(dc->pc); - dc->condjmp = 0; - } - if (dc->is_jmp == DISAS_SYSCALL && !dc->condjmp) { - gen_exception(UC32_EXCP_PRIV); - } else { - gen_exception(EXCP_DEBUG); - } - } else { - /* While branches must always occur at the end of an IT block, - there are a few other things that can cause us to terminate - the TB in the middel of an IT block: - - Exception generating instructions (bkpt, swi, undefined). - - Page boundaries. - - Hardware watchpoints. - Hardware breakpoints have already been handled and skip this code. - */ - switch (dc->is_jmp) { - case DISAS_NEXT: - gen_goto_tb(dc, 1, dc->pc); - 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; - case DISAS_SYSCALL: - gen_exception(UC32_EXCP_PRIV); - break; - } - if (dc->condjmp) { - gen_set_label(dc->condlabel); - gen_goto_tb(dc, 1, dc->pc); - dc->condjmp = 0; - } - } - -done_generating: - gen_tb_end(tb, num_insns); - -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - FILE *logfile = qemu_log_lock(); - qemu_log("----------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, dc->pc - pc_start); - qemu_log("\n"); - qemu_log_unlock(logfile); - } -#endif - tb->size = dc->pc - pc_start; - tb->icount = num_insns; -} - -static const char *cpu_mode_names[16] = { - "USER", "REAL", "INTR", "PRIV", "UM14", "UM15", "UM16", "TRAP", - "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR" -}; - -#undef UCF64_DUMP_STATE -#ifdef UCF64_DUMP_STATE -static void cpu_dump_state_ucf64(CPUUniCore32State *env, int flags) -{ - int i; - union { - uint32_t i; - float s; - } s0, s1; - CPU_DoubleU d; - /* ??? This assumes float64 and double have the same layout. - Oh well, it's only debug dumps. */ - union { - float64 f64; - double d; - } d0; - - for (i = 0; i < 16; i++) { - d.d = env->ucf64.regs[i]; - s0.i = d.l.lower; - s1.i = d.l.upper; - d0.f64 = d.d; - qemu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g)", - i * 2, (int)s0.i, s0.s, - i * 2 + 1, (int)s1.i, s1.s); - qemu_fprintf(f, " d%02d=%" PRIx64 "(%8g)\n", - i, (uint64_t)d0.f64, d0.d); - } - qemu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]); -} -#else -#define cpu_dump_state_ucf64(env, file, pr, flags) do { } while (0) -#endif - -void uc32_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ - UniCore32CPU *cpu = UNICORE32_CPU(cs); - CPUUniCore32State *env = &cpu->env; - int i; - uint32_t psr; - - for (i = 0; i < 32; i++) { - qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]); - if ((i % 4) == 3) { - qemu_fprintf(f, "\n"); - } else { - qemu_fprintf(f, " "); - } - } - psr = cpu_asr_read(env); - qemu_fprintf(f, "PSR=%08x %c%c%c%c %s\n", - psr, - psr & (1 << 31) ? 'N' : '-', - psr & (1 << 30) ? 'Z' : '-', - psr & (1 << 29) ? 'C' : '-', - psr & (1 << 28) ? 'V' : '-', - cpu_mode_names[psr & 0xf]); - - if (flags & CPU_DUMP_FPU) { - cpu_dump_state_ucf64(env, f, cpu_fprintf, flags); - } -} - -void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, - target_ulong *data) -{ - env->regs[31] = data[0]; -} diff --git a/target/unicore32/ucf64_helper.c b/target/unicore32/ucf64_helper.c deleted file mode 100644 index 12a91900f6..0000000000 --- a/target/unicore32/ucf64_helper.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * UniCore-F64 simulation helpers for QEMU. - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * 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, or any later version. - * See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/helper-proto.h" -#include "fpu/softfloat.h" - -/* - * The convention used for UniCore-F64 instructions: - * Single precition routines have a "s" suffix - * Double precision routines have a "d" suffix. - */ - -/* Convert host exception flags to f64 form. */ -static inline int ucf64_exceptbits_from_host(int host_bits) -{ - int target_bits = 0; - - if (host_bits & float_flag_invalid) { - target_bits |= UCF64_FPSCR_FLAG_INVALID; - } - if (host_bits & float_flag_divbyzero) { - target_bits |= UCF64_FPSCR_FLAG_DIVZERO; - } - if (host_bits & float_flag_overflow) { - target_bits |= UCF64_FPSCR_FLAG_OVERFLOW; - } - if (host_bits & float_flag_underflow) { - target_bits |= UCF64_FPSCR_FLAG_UNDERFLOW; - } - if (host_bits & float_flag_inexact) { - target_bits |= UCF64_FPSCR_FLAG_INEXACT; - } - return target_bits; -} - -uint32_t HELPER(ucf64_get_fpscr)(CPUUniCore32State *env) -{ - int i; - uint32_t fpscr; - - fpscr = (env->ucf64.xregs[UC32_UCF64_FPSCR] & UCF64_FPSCR_MASK); - i = get_float_exception_flags(&env->ucf64.fp_status); - fpscr |= ucf64_exceptbits_from_host(i); - return fpscr; -} - -/* Convert ucf64 exception flags to target form. */ -static inline int ucf64_exceptbits_to_host(int target_bits) -{ - int host_bits = 0; - - if (target_bits & UCF64_FPSCR_FLAG_INVALID) { - host_bits |= float_flag_invalid; - } - if (target_bits & UCF64_FPSCR_FLAG_DIVZERO) { - host_bits |= float_flag_divbyzero; - } - if (target_bits & UCF64_FPSCR_FLAG_OVERFLOW) { - host_bits |= float_flag_overflow; - } - if (target_bits & UCF64_FPSCR_FLAG_UNDERFLOW) { - host_bits |= float_flag_underflow; - } - if (target_bits & UCF64_FPSCR_FLAG_INEXACT) { - host_bits |= float_flag_inexact; - } - return host_bits; -} - -void HELPER(ucf64_set_fpscr)(CPUUniCore32State *env, uint32_t val) -{ - UniCore32CPU *cpu = env_archcpu(env); - int i; - uint32_t changed; - - changed = env->ucf64.xregs[UC32_UCF64_FPSCR]; - env->ucf64.xregs[UC32_UCF64_FPSCR] = (val & UCF64_FPSCR_MASK); - - changed ^= val; - if (changed & (UCF64_FPSCR_RND_MASK)) { - i = UCF64_FPSCR_RND(val); - switch (i) { - case 0: - i = float_round_nearest_even; - break; - case 1: - i = float_round_to_zero; - break; - case 2: - i = float_round_up; - break; - case 3: - i = float_round_down; - break; - default: /* 100 and 101 not implement */ - cpu_abort(CPU(cpu), "Unsupported UniCore-F64 round mode"); - } - set_float_rounding_mode(i, &env->ucf64.fp_status); - } - - i = ucf64_exceptbits_to_host(UCF64_FPSCR_TRAPEN(val)); - set_float_exception_flags(i, &env->ucf64.fp_status); -} - -float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUUniCore32State *env) -{ - return float32_add(a, b, &env->ucf64.fp_status); -} - -float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUUniCore32State *env) -{ - return float64_add(a, b, &env->ucf64.fp_status); -} - -float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUUniCore32State *env) -{ - return float32_sub(a, b, &env->ucf64.fp_status); -} - -float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUUniCore32State *env) -{ - return float64_sub(a, b, &env->ucf64.fp_status); -} - -float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUUniCore32State *env) -{ - return float32_mul(a, b, &env->ucf64.fp_status); -} - -float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUUniCore32State *env) -{ - return float64_mul(a, b, &env->ucf64.fp_status); -} - -float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUUniCore32State *env) -{ - return float32_div(a, b, &env->ucf64.fp_status); -} - -float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUUniCore32State *env) -{ - return float64_div(a, b, &env->ucf64.fp_status); -} - -float32 HELPER(ucf64_negs)(float32 a) -{ - return float32_chs(a); -} - -float64 HELPER(ucf64_negd)(float64 a) -{ - return float64_chs(a); -} - -float32 HELPER(ucf64_abss)(float32 a) -{ - return float32_abs(a); -} - -float64 HELPER(ucf64_absd)(float64 a) -{ - return float64_abs(a); -} - -void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, - CPUUniCore32State *env) -{ - FloatRelation flag = float32_compare_quiet(a, b, &env->ucf64.fp_status); - env->CF = 0; - switch (c & 0x7) { - case 0: /* F */ - break; - case 1: /* UN */ - if (flag == 2) { - env->CF = 1; - } - break; - case 2: /* EQ */ - if (flag == 0) { - env->CF = 1; - } - break; - case 3: /* UEQ */ - if ((flag == 0) || (flag == 2)) { - env->CF = 1; - } - break; - case 4: /* OLT */ - if (flag == -1) { - env->CF = 1; - } - break; - case 5: /* ULT */ - if ((flag == -1) || (flag == 2)) { - env->CF = 1; - } - break; - case 6: /* OLE */ - if ((flag == -1) || (flag == 0)) { - env->CF = 1; - } - break; - case 7: /* ULE */ - if (flag != 1) { - env->CF = 1; - } - break; - } - env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29) - | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff); -} - -void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c, - CPUUniCore32State *env) -{ - FloatRelation flag = float64_compare_quiet(a, b, &env->ucf64.fp_status); - env->CF = 0; - switch (c & 0x7) { - case 0: /* F */ - break; - case 1: /* UN */ - if (flag == 2) { - env->CF = 1; - } - break; - case 2: /* EQ */ - if (flag == 0) { - env->CF = 1; - } - break; - case 3: /* UEQ */ - if ((flag == 0) || (flag == 2)) { - env->CF = 1; - } - break; - case 4: /* OLT */ - if (flag == -1) { - env->CF = 1; - } - break; - case 5: /* ULT */ - if ((flag == -1) || (flag == 2)) { - env->CF = 1; - } - break; - case 6: /* OLE */ - if ((flag == -1) || (flag == 0)) { - env->CF = 1; - } - break; - case 7: /* ULE */ - if (flag != 1) { - env->CF = 1; - } - break; - } - env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29) - | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff); -} - -/* Helper routines to perform bitwise copies between float and int. */ -static inline float32 ucf64_itos(uint32_t i) -{ - union { - uint32_t i; - float32 s; - } v; - - v.i = i; - return v.s; -} - -static inline uint32_t ucf64_stoi(float32 s) -{ - union { - uint32_t i; - float32 s; - } v; - - v.s = s; - return v.i; -} - -/* Integer to float conversion. */ -float32 HELPER(ucf64_si2sf)(float32 x, CPUUniCore32State *env) -{ - return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status); -} - -float64 HELPER(ucf64_si2df)(float32 x, CPUUniCore32State *env) -{ - return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status); -} - -/* Float to integer conversion. */ -float32 HELPER(ucf64_sf2si)(float32 x, CPUUniCore32State *env) -{ - return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status)); -} - -float32 HELPER(ucf64_df2si)(float64 x, CPUUniCore32State *env) -{ - return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status)); -} - -/* floating point conversion */ -float64 HELPER(ucf64_sf2df)(float32 x, CPUUniCore32State *env) -{ - return float32_to_float64(x, &env->ucf64.fp_status); -} - -float32 HELPER(ucf64_df2sf)(float64 x, CPUUniCore32State *env) -{ - return float64_to_float32(x, &env->ucf64.fp_status); -} diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index d63a269aef..0ac46ddd91 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -9,6 +9,7 @@ ENV PACKAGES \ alsa-lib-dev \ bash \ binutils \ + ccache \ coreutils \ curl-dev \ g++ \ @@ -39,6 +40,7 @@ ENV PACKAGES \ pulseaudio-dev \ python3 \ py3-sphinx \ + py3-sphinx_rtd_theme \ shadow \ snappy-dev \ spice-dev \ diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker index d034acbd25..63cf835ec5 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -32,6 +32,7 @@ RUN apt update && \ psmisc \ python3 \ python3-sphinx \ + python3-sphinx-rtd-theme \ $(apt-get -s build-dep --arch-only qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) ENV FEATURES docs diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/docker/dockerfiles/fedora-i386-cross.docker index 966072c08e..66cdb06c19 100644 --- a/tests/docker/dockerfiles/fedora-i386-cross.docker +++ b/tests/docker/dockerfiles/fedora-i386-cross.docker @@ -1,6 +1,7 @@ FROM fedora:33 ENV PACKAGES \ bzip2 \ + ccache \ diffutils \ findutils \ gcc \ diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker index 81b5659e9c..3733df63e9 100644 --- a/tests/docker/dockerfiles/fedora-win32-cross.docker +++ b/tests/docker/dockerfiles/fedora-win32-cross.docker @@ -4,6 +4,7 @@ FROM fedora:33 ENV PACKAGES \ bc \ bzip2 \ + ccache \ diffutils \ findutils \ gcc \ diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker index bcb428e724..2564ce4979 100644 --- a/tests/docker/dockerfiles/fedora-win64-cross.docker +++ b/tests/docker/dockerfiles/fedora-win64-cross.docker @@ -4,6 +4,7 @@ FROM fedora:33 ENV PACKAGES \ bc \ bzip2 \ + ccache \ diffutils \ findutils \ gcc \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index 915fdc1845..d8fa16372d 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -92,6 +92,7 @@ ENV PACKAGES \ python3-pillow \ python3-pip \ python3-sphinx \ + python3-sphinx_rtd_theme \ python3-virtualenv \ rdma-core-devel \ SDL2-devel \ diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 0e64893e4a..f7e1cbfbe6 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -5,6 +5,7 @@ ENV PACKAGES \ bc \ brlapi-devel \ bzip2 \ + ccache \ cyrus-sasl-devel \ gcc \ gcc-c++ \ diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker index b5ef7a8198..98a527361c 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -63,6 +63,7 @@ ENV PACKAGES \ ninja-build \ python3-yaml \ python3-sphinx \ + python3-sphinx-rtd-theme \ sparse \ xfslibs-dev RUN apt-get update && \ diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker index 9b0a19ba5e..c0d3642507 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -48,6 +48,7 @@ ENV PACKAGES \ make \ python3-yaml \ python3-sphinx \ + python3-sphinx-rtd-theme \ ninja-build \ sparse \ xfslibs-dev diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index 9750016e51..f1e0ebad49 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -58,6 +58,7 @@ ENV PACKAGES flex bison \ python3-pil \ python3-pip \ python3-sphinx \ + python3-sphinx-rtd-theme \ python3-venv \ python3-yaml \ rpm2cpio \ diff --git a/tests/migration/guestperf/comparison.py b/tests/migration/guestperf/comparison.py index ba2edbe546..c03b3f6d7e 100644 --- a/tests/migration/guestperf/comparison.py +++ b/tests/migration/guestperf/comparison.py @@ -121,4 +121,18 @@ COMPARISONS = [ Scenario("compr-xbzrle-cache-50", compression_xbzrle=True, compression_xbzrle_cache=50), ]), + + + # Looking at effect of multifd with + # varying numbers of channels + Comparison("compr-multifd", scenarios = [ + Scenario("compr-multifd-channels-4", + multifd=True, multifd_channels=2), + Scenario("compr-multifd-channels-8", + multifd=True, multifd_channels=8), + Scenario("compr-multifd-channels-32", + multifd=True, multifd_channels=32), + Scenario("compr-multifd-channels-64", + multifd=True, multifd_channels=64), + ]), ] diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py index 6b49aed579..208e095794 100644 --- a/tests/migration/guestperf/engine.py +++ b/tests/migration/guestperf/engine.py @@ -188,6 +188,22 @@ class Engine(object): 1024 * 1024 * 1024 / 100 * scenario._compression_xbzrle_cache)) + if scenario._multifd: + resp = src.command("migrate-set-capabilities", + capabilities = [ + { "capability": "multifd", + "state": True } + ]) + resp = src.command("migrate-set-parameters", + multifd_channels=scenario._multifd_channels) + resp = dst.command("migrate-set-capabilities", + capabilities = [ + { "capability": "multifd", + "state": True } + ]) + resp = dst.command("migrate-set-parameters", + multifd_channels=scenario._multifd_channels) + resp = src.command("migrate", uri=connect_uri) post_copy = False diff --git a/tests/migration/guestperf/scenario.py b/tests/migration/guestperf/scenario.py index 28ef36c26d..de70d9b2f5 100644 --- a/tests/migration/guestperf/scenario.py +++ b/tests/migration/guestperf/scenario.py @@ -29,7 +29,8 @@ class Scenario(object): post_copy=False, post_copy_iters=5, auto_converge=False, auto_converge_step=10, compression_mt=False, compression_mt_threads=1, - compression_xbzrle=False, compression_xbzrle_cache=10): + compression_xbzrle=False, compression_xbzrle_cache=10, + multifd=False, multifd_channels=2): self._name = name @@ -56,6 +57,9 @@ class Scenario(object): self._compression_xbzrle = compression_xbzrle self._compression_xbzrle_cache = compression_xbzrle_cache # percentage of guest RAM + self._multifd = multifd + self._multifd_channels = multifd_channels + def serialize(self): return { "name": self._name, @@ -73,6 +77,8 @@ class Scenario(object): "compression_mt_threads": self._compression_mt_threads, "compression_xbzrle": self._compression_xbzrle, "compression_xbzrle_cache": self._compression_xbzrle_cache, + "multifd": self._multifd, + "multifd_channels": self._multifd_channels, } @classmethod @@ -92,4 +98,6 @@ class Scenario(object): data["compression_mt"], data["compression_mt_threads"], data["compression_xbzrle"], - data["compression_xbzrle_cache"]) + data["compression_xbzrle_cache"], + data["multifd"], + data["multifd_channels"]) diff --git a/tests/migration/guestperf/shell.py b/tests/migration/guestperf/shell.py index f838888809..8a809e3dda 100644 --- a/tests/migration/guestperf/shell.py +++ b/tests/migration/guestperf/shell.py @@ -122,6 +122,11 @@ class Shell(BaseShell): parser.add_argument("--compression-xbzrle", dest="compression_xbzrle", default=False, action="store_true") parser.add_argument("--compression-xbzrle-cache", dest="compression_xbzrle_cache", default=10, type=int) + parser.add_argument("--multifd", dest="multifd", default=False, + action="store_true") + parser.add_argument("--multifd-channels", dest="multifd_channels", + default=2, type=int) + def get_scenario(self, args): return Scenario(name="perfreport", downtime=args.downtime, @@ -142,7 +147,10 @@ class Shell(BaseShell): compression_mt_threads=args.compression_mt_threads, compression_xbzrle=args.compression_xbzrle, - compression_xbzrle_cache=args.compression_xbzrle_cache) + compression_xbzrle_cache=args.compression_xbzrle_cache, + + multifd=args.multifd, + multifd_channels=args.multifd_channels) def run(self, argv): args = self._parser.parse_args(argv) diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005 index 40e64a9a8f..ba377543b0 100755 --- a/tests/qemu-iotests/005 +++ b/tests/qemu-iotests/005 @@ -52,11 +52,6 @@ if [ "$IMGFMT" = "vpc" ]; then _notrun "image format $IMGFMT does not support large image sizes" fi -# sheepdog image is limited to 4TB, so we can't test it here -if [ "$IMGPROTO" = "sheepdog" ]; then - _notrun "image protocol $IMGPROTO does not support large image sizes" -fi - # Sanity check: For raw, we require a file system that permits the creation # of a HUGE (but very sparse) file. Check we can create it before continuing. if [ "$IMGFMT" = "raw" ]; then diff --git a/tests/qemu-iotests/025 b/tests/qemu-iotests/025 index da77ed3154..80686a30d5 100755 --- a/tests/qemu-iotests/025 +++ b/tests/qemu-iotests/025 @@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.pattern _supported_fmt raw qcow2 qed luks -_supported_proto file sheepdog rbd nfs fuse +_supported_proto file rbd nfs fuse echo "=== Creating image" echo diff --git a/tests/qemu-iotests/231 b/tests/qemu-iotests/231 index 0f66d0ca36..8e6c6447c1 100755 --- a/tests/qemu-iotests/231 +++ b/tests/qemu-iotests/231 @@ -55,6 +55,10 @@ _filter_conf() $QEMU_IMG info "json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=${BOGUS_CONF}'}" 2>&1 | _filter_conf $QEMU_IMG info "json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'${BOGUS_CONF}'}" 2>&1 | _filter_conf +# Regression test: the qemu-img invocation is expected to fail, but it should +# not seg fault the parser. +$QEMU_IMG create "rbd:rbd/aa\/bb:conf=${BOGUS_CONF}" 1M 2>&1 | _filter_conf + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/231.out b/tests/qemu-iotests/231.out index 579ba11c16..a785a6e859 100644 --- a/tests/qemu-iotests/231.out +++ b/tests/qemu-iotests/231.out @@ -1,9 +1,10 @@ QA output created by 231 -qemu-img: RBD options encoded in the filename as keyvalue pairs is deprecated. Future versions may cease to parse these options in the future. +qemu-img: warning: RBD options encoded in the filename as keyvalue pairs is deprecated unable to get monitor info from DNS SRV with service name: ceph-mon -no monitors specified to connect to. qemu-img: Could not open 'json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=BOGUS_CONF'}': error connecting: No such file or directory unable to get monitor info from DNS SRV with service name: ceph-mon -no monitors specified to connect to. qemu-img: Could not open 'json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'BOGUS_CONF'}': error connecting: No such file or directory +Formatting 'rbd:rbd/aa\/bb:conf=BOGUS_CONF', fmt=raw size=1048576 +unable to get monitor info from DNS SRV with service name: ceph-mon +qemu-img: rbd:rbd/aa\/bb:conf=BOGUS_CONF: error connecting: No such file or directory *** done diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out index e0982831ae..89ed25e506 100644 --- a/tests/qemu-iotests/240.out +++ b/tests/qemu-iotests/240.out @@ -15,7 +15,7 @@ {"return": {}} {"execute": "blockdev-del", "arguments": {"node-name": "hd0"}} {"return": {}} -==Attach two SCSI disks using the same block device and the same iothread== +.==Attach two SCSI disks using the same block device and the same iothread== {"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true, "read-zeroes": true}} {"return": {}} {"execute": "object-add", "arguments": {"id": "iothread0", "qom-type": "iothread"}} @@ -32,7 +32,7 @@ {"return": {}} {"execute": "blockdev-del", "arguments": {"node-name": "hd0"}} {"return": {}} -==Attach two SCSI disks using the same block device but different iothreads== +.==Attach two SCSI disks using the same block device but different iothreads== {"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true, "read-zeroes": true}} {"return": {}} {"execute": "object-add", "arguments": {"id": "iothread0", "qom-type": "iothread"}} @@ -55,7 +55,7 @@ {"return": {}} {"execute": "blockdev-del", "arguments": {"node-name": "hd0"}} {"return": {}} -==Attach a SCSI disks using the same block device as a NBD server== +.==Attach a SCSI disks using the same block device as a NBD server== {"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true, "read-zeroes": true}} {"return": {}} {"execute": "nbd-server-start", "arguments": {"addr": {"data": {"path": "SOCK_DIR/PID-nbd.sock"}, "type": "unix"}}} @@ -68,7 +68,7 @@ {"return": {}} {"execute": "device_add", "arguments": {"drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd0"}} {"return": {}} -.... +. ---------------------------------------------------------------------- Ran 4 tests diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out index 4b33dcaf5c..99c12f4f98 100644 --- a/tests/qemu-iotests/245.out +++ b/tests/qemu-iotests/245.out @@ -1,16 +1,16 @@ -{"execute": "job-finalize", "arguments": {"id": "commit0"}} +..{"execute": "job-finalize", "arguments": {"id": "commit0"}} {"return": {}} {"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} {"data": {"device": "commit0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -{"execute": "job-finalize", "arguments": {"id": "stream0"}} +...{"execute": "job-finalize", "arguments": {"id": "stream0"}} {"return": {}} {"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} {"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -{"execute": "job-finalize", "arguments": {"id": "stream0"}} +.{"execute": "job-finalize", "arguments": {"id": "stream0"}} {"return": {}} {"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} {"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -..................... +............... ---------------------------------------------------------------------- Ran 21 tests diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264 index 4f96825a22..bc431d1a19 100755 --- a/tests/qemu-iotests/264 +++ b/tests/qemu-iotests/264 @@ -95,7 +95,7 @@ class TestNbdReconnect(iotests.QMPTestCase): self.assert_qmp(result, 'return', {}) def cancel_job(self): - result = self.vm.qmp('block-job-cancel', device='drive0') + result = self.vm.qmp('block-job-cancel', device='drive0', force=True) self.assert_qmp(result, 'return', {}) start_t = time.time() diff --git a/tests/qemu-iotests/295.out b/tests/qemu-iotests/295.out index ad34b2ca2c..5ff91f116c 100644 --- a/tests/qemu-iotests/295.out +++ b/tests/qemu-iotests/295.out @@ -4,7 +4,7 @@ {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} {"return": {}} -{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +.{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} {"return": {}} @@ -13,7 +13,7 @@ Job failed: Invalid password, cannot unlock any keyslot {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} {"return": {}} -{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} +.{"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job_add_key"}} {"return": {}} @@ -33,7 +33,7 @@ Job failed: All the active keyslots match the (old) password that was given and {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job_erase_key"}} {"return": {}} -... +. ---------------------------------------------------------------------- Ran 3 tests diff --git a/tests/qemu-iotests/296.out b/tests/qemu-iotests/296.out index cb2859a15c..6c69735604 100644 --- a/tests/qemu-iotests/296.out +++ b/tests/qemu-iotests/296.out @@ -13,7 +13,7 @@ Job failed: Failed to get shared "consistent read" lock 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 +.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"}} @@ -26,15 +26,15 @@ Job failed: Failed to get shared "consistent read" lock {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10 +.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 +.Formatting 'TEST_DIR/test.img', fmt=luks size=1048576 key-secret=keysec0 iter-time=10 {"return": {}} {"return": {}} -.... +. ---------------------------------------------------------------------- Ran 4 tests diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index d1c87ceaf1..2dd529eb75 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -19,6 +19,9 @@ import os import sys import argparse +import shutil +from pathlib import Path + from findtests import TestFinder from testenv import TestEnv from testrunner import TestRunner @@ -65,8 +68,7 @@ def make_argparser() -> argparse.ArgumentParser: mg.add_argument('-' + fmt, dest='imgfmt', action='store_const', const=fmt, help=f'test {fmt}') - protocol_list = ['file', 'rbd', 'sheepdog', 'nbd', 'ssh', 'nfs', - 'fuse'] + protocol_list = ['file', 'rbd', 'nbd', 'ssh', 'nfs', 'fuse'] g_prt = p.add_argument_group( ' image protocol options', 'The following options set the IMGPROTO environment variable. ' @@ -101,7 +103,7 @@ def make_argparser() -> argparse.ArgumentParser: 'rerun failed ./check command, starting from the ' 'middle of the process.') g_sel.add_argument('tests', metavar='TEST_FILES', nargs='*', - help='tests to run') + help='tests to run, or "--" followed by a command') return p @@ -114,6 +116,20 @@ if __name__ == '__main__': imgopts=args.imgopts, misalign=args.misalign, debug=args.debug, valgrind=args.valgrind) + if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--': + if not args.tests: + sys.exit("missing command after '--'") + cmd = args.tests + env.print_env() + exec_pathstr = shutil.which(cmd[0]) + if exec_pathstr is None: + sys.exit('command not found: ' + cmd[0]) + exec_path = Path(exec_pathstr).resolve() + cmd[0] = str(exec_path) + full_env = env.prepare_subprocess(cmd) + os.chdir(exec_path.parent) + os.execve(cmd[0], cmd, full_env) + testfinder = TestFinder(test_dir=env.source_iotests) groups = args.groups.split(',') if args.groups else None diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 7f49c9716d..cbbf6d7c7f 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -641,10 +641,6 @@ _cleanup_test_img() rbd --no-progress rm "$TEST_DIR/t.$IMGFMT" > /dev/null ;; - sheepdog) - collie vdi delete "$TEST_DIR/t.$IMGFMT" - ;; - esac } diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 5af0182895..777fa2ec0e 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -20,7 +20,6 @@ import atexit import bz2 from collections import OrderedDict import faulthandler -import io import json import logging import os @@ -32,7 +31,7 @@ import subprocess import sys import time from typing import (Any, Callable, Dict, Iterable, - List, Optional, Sequence, Tuple, TypeVar) + List, Optional, Sequence, TextIO, Tuple, Type, TypeVar) import unittest from contextlib import contextmanager @@ -113,15 +112,14 @@ def qemu_tool_pipe_and_status(tool: str, args: Sequence[str], 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: - cmd = ' '.join(args) - sys.stderr.write(f'{tool} received signal {-subp.returncode}: {cmd}\n') - return (output, subp.returncode) + with subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=stderr, universal_newlines=True) as subp: + output = subp.communicate()[0] + if subp.returncode < 0: + cmd = ' '.join(args) + sys.stderr.write(f'{tool} received signal \ + {-subp.returncode}: {cmd}\n') + return (output, subp.returncode) def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]: """ @@ -237,6 +235,9 @@ def qemu_io_silent_check(*args): class QemuIoInteractive: def __init__(self, *args): self.args = qemu_io_args_no_fmt + list(args) + # We need to keep the Popen objext around, and not + # close it immediately. Therefore, disable the pylint check: + # pylint: disable=consider-using-with self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -310,22 +311,22 @@ def qemu_nbd_popen(*args): cmd.extend(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: - if os.path.exists(pid_file): - os.remove(pid_file) - log('Kill NBD server') - p.kill() - p.wait() + with subprocess.Popen(cmd) as p: + 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: + if os.path.exists(pid_file): + os.remove(pid_file) + 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''' @@ -334,13 +335,12 @@ def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): def create_image(name, size): '''Create a fully-allocated raw image with sector markers''' - file = open(name, 'wb') - i = 0 - while i < size: - sector = struct.pack('>l504xl', i // 512, i // 512) - file.write(sector) - i = i + 512 - file.close() + with open(name, 'wb') as file: + i = 0 + while i < size: + sector = struct.pack('>l504xl', i // 512, i // 512) + file.write(sector) + i = i + 512 def image_size(img): '''Return image's virtual size''' @@ -1271,37 +1271,54 @@ def skip_if_user_is_root(func): return func(*args, **kwargs) return func_wrapper -def execute_unittest(debug=False): +# We need to filter out the time taken from the output so that +# qemu-iotest can reliably diff the results against master output, +# and hide skipped tests from the reference output. + +class ReproducibleTestResult(unittest.TextTestResult): + def addSkip(self, test, reason): + # Same as TextTestResult, but print dot instead of "s" + unittest.TestResult.addSkip(self, test, reason) + if self.showAll: + self.stream.writeln("skipped {0!r}".format(reason)) + elif self.dots: + self.stream.write(".") + self.stream.flush() + +class ReproducibleStreamWrapper: + def __init__(self, stream: TextIO): + self.stream = stream + + def __getattr__(self, attr): + if attr in ('stream', '__getstate__'): + raise AttributeError(attr) + return getattr(self.stream, attr) + + def write(self, arg=None): + arg = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', arg) + arg = re.sub(r' \(skipped=\d+\)', r'', arg) + self.stream.write(arg) + +class ReproducibleTestRunner(unittest.TextTestRunner): + def __init__(self, stream: Optional[TextIO] = None, + resultclass: Type[unittest.TestResult] = ReproducibleTestResult, + **kwargs: Any) -> None: + rstream = ReproducibleStreamWrapper(stream or sys.stdout) + super().__init__(stream=rstream, # type: ignore + descriptions=True, + resultclass=resultclass, + **kwargs) + +def execute_unittest(argv: List[str], debug: bool = False) -> None: """Executes unittests within the calling module.""" - verbosity = 2 if debug else 1 - - if debug: - output = sys.stdout - else: - # We need to filter out the time taken from the output so that - # qemu-iotest can reliably diff the results against master output. - output = io.StringIO() - - runner = unittest.TextTestRunner(stream=output, descriptions=True, - verbosity=verbosity) - try: - # unittest.main() will use sys.exit(); so expect a SystemExit - # exception - unittest.main(testRunner=runner) - finally: - # We need to filter out the time taken from the output so that - # qemu-iotest can reliably diff the results against master output. - if not debug: - out = output.getvalue() - out = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', out) - - # Hide skipped tests from the reference output - out = re.sub(r'OK \(skipped=\d+\)', 'OK', out) - out_first_line, out_rest = out.split('\n', 1) - out = out_first_line.replace('s', '.') + '\n' + out_rest - - sys.stderr.write(out) + # Some tests have warnings, especially ResourceWarnings for unclosed + # files and sockets. Ignore them for now to ensure reproducibility of + # the test output. + unittest.main(argv=argv, + testRunner=ReproducibleTestRunner, + verbosity=2 if debug else 1, + warnings=None if sys.warnoptions else 'ignore') def execute_setup_common(supported_fmts: Sequence[str] = (), supported_platforms: Sequence[str] = (), @@ -1338,7 +1355,7 @@ def execute_test(*args, test_function=None, **kwargs): debug = execute_setup_common(*args, **kwargs) if not test_function: - execute_unittest(debug) + execute_unittest(sys.argv, debug) else: test_function() diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc index 7a6c0a9474..f2c0b522ac 100644 --- a/tests/qemu-iotests/pylintrc +++ b/tests/qemu-iotests/pylintrc @@ -19,6 +19,9 @@ disable=invalid-name, too-many-public-methods, # pylint warns about Optional[] etc. as unsubscriptable in 3.9 unsubscriptable-object, + # Sometimes we need to disable a newly introduced pylint warning. + # Doing so should not produce a warning in older versions of pylint. + bad-option-value, # These are temporary, and should be removed: missing-docstring, too-many-return-statements, diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py index 6d27712617..0c3fe75636 100644 --- a/tests/qemu-iotests/testenv.py +++ b/tests/qemu-iotests/testenv.py @@ -25,7 +25,7 @@ import collections import random import subprocess import glob -from typing import Dict, Any, Optional, ContextManager +from typing import List, Dict, Any, Optional, ContextManager def isxfile(path: str) -> bool: @@ -74,6 +74,21 @@ class TestEnv(ContextManager['TestEnv']): 'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX', 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_'] + def prepare_subprocess(self, args: List[str]) -> Dict[str, str]: + if self.debug: + args.append('-d') + + with open(args[0], encoding="utf-8") as f: + try: + if f.readline().rstrip() == '#!/usr/bin/env python3': + args.insert(0, self.python) + except UnicodeDecodeError: # binary test? for future. + pass + + os_env = os.environ.copy() + os_env.update(self.get_env()) + return os_env + def get_env(self) -> Dict[str, str]: env = {} for v in self.env_variables: @@ -105,7 +120,7 @@ class TestEnv(ContextManager['TestEnv']): try: self.sock_dir = os.environ['SOCK_DIR'] self.tmp_sock_dir = False - Path(self.test_dir).mkdir(parents=True, exist_ok=True) + Path(self.sock_dir).mkdir(parents=True, exist_ok=True) except KeyError: self.sock_dir = tempfile.mkdtemp() self.tmp_sock_dir = True @@ -269,7 +284,8 @@ IMGPROTO -- {IMGPROTO} PLATFORM -- {platform} TEST_DIR -- {TEST_DIR} SOCK_DIR -- {SOCK_DIR} -SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}""" +SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER} +""" args = collections.defaultdict(str, self.get_env()) diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py index 1fc61fcaa3..4a6ec421ed 100644 --- a/tests/qemu-iotests/testrunner.py +++ b/tests/qemu-iotests/testrunner.py @@ -129,7 +129,6 @@ class TestRunner(ContextManager['TestRunner']): def __init__(self, env: TestEnv, makecheck: bool = False, color: str = 'auto') -> None: self.env = env - self.test_run_env = self.env.get_env() self.makecheck = makecheck self.last_elapsed = LastElapsedTime('.last-elapsed-cache', env) @@ -243,32 +242,21 @@ class TestRunner(ContextManager['TestRunner']): silent_unlink(p) args = [str(f_test.resolve())] - if self.env.debug: - args.append('-d') - - with f_test.open(encoding="utf-8") as f: - try: - if f.readline().rstrip() == '#!/usr/bin/env python3': - args.insert(0, self.env.python) - except UnicodeDecodeError: # binary test? for future. - pass - - env = os.environ.copy() - env.update(self.test_run_env) + env = self.env.prepare_subprocess(args) t0 = time.time() with f_bad.open('w', encoding="utf-8") as f: - proc = subprocess.Popen(args, cwd=str(f_test.parent), env=env, - stdout=f, stderr=subprocess.STDOUT) - try: - proc.wait() - except KeyboardInterrupt: - proc.terminate() - proc.wait() - return TestResult(status='not run', - description='Interrupted by user', - interrupted=True) - ret = proc.returncode + with subprocess.Popen(args, cwd=str(f_test.parent), env=env, + stdout=f, stderr=subprocess.STDOUT) as proc: + try: + proc.wait() + except KeyboardInterrupt: + proc.terminate() + proc.wait() + return TestResult(status='not run', + description='Interrupted by user', + interrupted=True) + ret = proc.returncode elapsed = round(time.time() - t0, 1) @@ -328,7 +316,6 @@ class TestRunner(ContextManager['TestRunner']): if not self.makecheck: self.env.print_env() - print() test_field_width = max(len(os.path.basename(t)) for t in tests) + 2 diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c index 5e1954852e..8073ccc205 100644 --- a/tests/qtest/ahci-test.c +++ b/tests/qtest/ahci-test.c @@ -1491,14 +1491,14 @@ static void ahci_test_cdrom(int nsectors, bool dma, uint8_t cmd, char *iso; int fd; AHCIOpts opts = { - .size = (ATAPI_SECTOR_SIZE * nsectors), + .size = ((uint64_t)ATAPI_SECTOR_SIZE * nsectors), .atapi = true, .atapi_dma = dma, .post_cb = ahci_cb_cmp_buff, .set_bcl = override_bcl, .bcl = bcl, }; - uint64_t iso_size = ATAPI_SECTOR_SIZE * (nsectors + 1); + uint64_t iso_size = (uint64_t)ATAPI_SECTOR_SIZE * (nsectors + 1); /* Prepare ISO and fill 'tx' buffer */ fd = prepare_iso(iso_size, &tx, &iso); diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index d74509b1c5..d40adddafa 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -61,13 +61,6 @@ static const uint8_t kernel_plml605[] = { 0xfc, 0xff, 0x00, 0xb8 /* bri -4 loop */ }; -static const uint8_t bios_moxiesim[] = { - 0x20, 0x10, 0x00, 0x00, 0x03, 0xf8, /* ldi.s r1,0x3f8 */ - 0x1b, 0x20, 0x00, 0x00, 0x00, 0x54, /* ldi.b r2,'T' */ - 0x1e, 0x12, /* st.b r1,r2 */ - 0x1a, 0x00, 0x00, 0x00, 0x10, 0x00 /* jmpa 0x1000 */ -}; - static const uint8_t bios_raspi2[] = { 0x08, 0x30, 0x9f, 0xe5, /* ldr r3,[pc,#8] Get base */ 0x54, 0x20, 0xa0, 0xe3, /* mov r2,#'T' */ @@ -145,7 +138,6 @@ static testdef_t tests[] = { sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 }, { "microblazeel", "petalogix-ml605", "", "TT", sizeof(kernel_plml605), kernel_plml605 }, - { "moxie", "moxiesim", "", "TT", sizeof(bios_moxiesim), 0, bios_moxiesim }, { "arm", "raspi2", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 }, /* For hppa, force bios to output to serial by disabling graphics. */ { "hppa", "hppa", "-vga none", "SeaBIOS wants SYSTEM HALT" }, diff --git a/tests/qtest/ipmi-bt-test.c b/tests/qtest/ipmi-bt-test.c index a42207d416..8492f02a9c 100644 --- a/tests/qtest/ipmi-bt-test.c +++ b/tests/qtest/ipmi-bt-test.c @@ -98,7 +98,8 @@ static void bt_wait_b_busy(void) { unsigned int count = 1000; while (IPMI_BT_CTLREG_GET_B_BUSY() != 0) { - g_assert(--count != 0); + --count; + g_assert(count != 0); usleep(100); } } @@ -107,7 +108,8 @@ static void bt_wait_b2h_atn(void) { unsigned int count = 1000; while (IPMI_BT_CTLREG_GET_B2H_ATN() == 0) { - g_assert(--count != 0); + --count; + g_assert(count != 0); usleep(100); } } diff --git a/tests/qtest/ipmi-kcs-test.c b/tests/qtest/ipmi-kcs-test.c index fc0a918c8d..afc24dd3e4 100644 --- a/tests/qtest/ipmi-kcs-test.c +++ b/tests/qtest/ipmi-kcs-test.c @@ -73,7 +73,8 @@ static void kcs_wait_ibf(void) { unsigned int count = 1000; while (IPMI_KCS_CMDREG_GET_IBF() != 0) { - g_assert(--count != 0); + --count; + g_assert(count != 0); } } diff --git a/tests/qtest/libqos/qgraph.c b/tests/qtest/libqos/qgraph.c index b3b1a31f81..d1dc491930 100644 --- a/tests/qtest/libqos/qgraph.c +++ b/tests/qtest/libqos/qgraph.c @@ -844,7 +844,7 @@ void qos_dump_graph(void) } qos_printf_literal("type=%d cmd_line='%s' [%s]\n", node->type, node->command_line, - node->available ? "available" : "UNAVAILBLE" + node->available ? "available" : "UNAVAILABLE" ); } g_list_free(keys); diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 71e359efcd..825b13a44c 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -907,7 +907,14 @@ const char *qtest_get_arch(void) if (!end) { fprintf(stderr, "Can't determine architecture from binary name.\n"); - abort(); + exit(1); + } + + if (!strstr(qemu, "-system-")) { + fprintf(stderr, "QTEST_QEMU_BINARY must end with *-system-<arch> " + "where 'arch' is the target\narchitecture (x86_64, aarch64, " + "etc).\n"); + exit(1); } return end + 1; diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c index aab06b9fc2..138101b46a 100644 --- a/tests/qtest/machine-none-test.c +++ b/tests/qtest/machine-none-test.c @@ -32,7 +32,6 @@ static struct arch2cpu cpus_map[] = { { "i386", "qemu32,apic-id=0" }, { "alpha", "ev67" }, { "cris", "crisv32" }, - { "lm32", "lm32-full" }, { "m68k", "m5206" }, { "microblaze", "any" }, { "microblazeel", "any" }, @@ -40,7 +39,6 @@ static struct arch2cpu cpus_map[] = { { "mipsel", "I7200" }, { "mips64", "20Kc" }, { "mips64el", "I6500" }, - { "moxie", "MoxieLite" }, { "nios2", "FIXME" }, { "or1k", "or1200" }, { "ppc", "604" }, @@ -51,7 +49,6 @@ static struct arch2cpu cpus_map[] = { { "sparc", "LEON2" }, { "sparc64", "Fujitsu Sparc64" }, { "tricore", "tc1796" }, - { "unicore32", "UniCore-II" }, { "xtensa", "dc233c" }, { "xtensaeb", "fsf" }, { "hppa", "hppa" }, diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 966bc93efa..49de74ff59 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -126,8 +126,6 @@ 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'] : []) + \ diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 3a711bb492..2b028df687 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -110,13 +110,12 @@ static void init_bootfile(const char *bootpath, void *content, size_t len) */ static void wait_for_serial(const char *side) { - char *serialpath = g_strdup_printf("%s/%s", tmpfs, side); + g_autofree char *serialpath = g_strdup_printf("%s/%s", tmpfs, side); FILE *serialfile = fopen(serialpath, "r"); const char *arch = qtest_get_arch(); int started = (strcmp(side, "src_serial") == 0 && strcmp(arch, "ppc64") == 0) ? 0 : 1; - g_free(serialpath); do { int readvalue = fgetc(serialfile); @@ -274,10 +273,9 @@ static void check_guests_ram(QTestState *who) static void cleanup(const char *filename) { - char *path = g_strdup_printf("%s/%s", tmpfs, filename); + g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, filename); unlink(path); - g_free(path); } static char *SocketAddress_to_str(SocketAddress *addr) @@ -374,11 +372,8 @@ static char *migrate_get_parameter_str(QTestState *who, static void migrate_check_parameter_str(QTestState *who, const char *parameter, const char *value) { - char *result; - - result = migrate_get_parameter_str(who, parameter); + g_autofree char *result = migrate_get_parameter_str(who, parameter); g_assert_cmpstr(result, ==, value); - g_free(result); } static void migrate_set_parameter_str(QTestState *who, const char *parameter, @@ -495,12 +490,14 @@ static void migrate_start_destroy(MigrateStart *args) static int test_migrate_start(QTestState **from, QTestState **to, const char *uri, MigrateStart *args) { - gchar *arch_source, *arch_target; - gchar *cmd_source, *cmd_target; + g_autofree gchar *arch_source = NULL; + g_autofree gchar *arch_target = NULL; + g_autofree gchar *cmd_source = NULL; + g_autofree gchar *cmd_target = NULL; const gchar *ignore_stderr; - char *bootpath = NULL; - char *shmem_opts; - char *shmem_path; + g_autofree char *bootpath = NULL; + g_autofree char *shmem_opts = NULL; + g_autofree char *shmem_path = NULL; const char *arch = qtest_get_arch(); const char *machine_opts = NULL; const char *memory_size; @@ -559,8 +556,6 @@ static int test_migrate_start(QTestState **from, QTestState **to, g_assert_not_reached(); } - g_free(bootpath); - if (!getenv("QTEST_LOG") && args->hide_stderr) { ignore_stderr = "2>/dev/null"; } else { @@ -588,11 +583,9 @@ static int test_migrate_start(QTestState **from, QTestState **to, memory_size, tmpfs, arch_source, shmem_opts, args->opts_source, ignore_stderr); - g_free(arch_source); if (!args->only_target) { *from = qtest_init(cmd_source); } - g_free(cmd_source); cmd_target = g_strdup_printf("-accel kvm -accel tcg%s%s " "-name target,debug-threads=on " @@ -605,18 +598,14 @@ static int test_migrate_start(QTestState **from, QTestState **to, memory_size, tmpfs, uri, arch_target, shmem_opts, args->opts_target, ignore_stderr); - g_free(arch_target); *to = qtest_init(cmd_target); - g_free(cmd_target); - g_free(shmem_opts); /* * Remove shmem file immediately to avoid memory leak in test failed case. * It's valid becase QEMU has already opened this file */ if (args->use_shmem) { unlink(shmem_path); - g_free(shmem_path); } out: @@ -662,7 +651,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr, QTestState **to_ptr, MigrateStart *args) { - char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); QTestState *from, *to; if (test_migrate_start(&from, &to, uri, args)) { @@ -684,7 +673,6 @@ static int migrate_postcopy_prepare(QTestState **from_ptr, wait_for_serial("src_serial"); migrate_qmp(from, uri, "{}"); - g_free(uri); wait_for_migration_pass(from); @@ -724,7 +712,7 @@ static void test_postcopy_recovery(void) { MigrateStart *args = migrate_start_new(); QTestState *from, *to; - char *uri; + g_autofree char *uri = NULL; args->hide_stderr = true; @@ -775,7 +763,6 @@ static void test_postcopy_recovery(void) (const char * []) { "failed", "active", "completed", NULL }); migrate_qmp(from, uri, "{'resume': true}"); - g_free(uri); /* Restore the postcopy bandwidth to unlimited */ migrate_set_parameter_int(from, "max-postcopy-bandwidth", 0); @@ -800,7 +787,7 @@ static void test_baddest(void) static void test_precopy_unix(void) { - char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); MigrateStart *args = migrate_start_new(); QTestState *from, *to; @@ -836,14 +823,13 @@ static void test_precopy_unix(void) wait_for_migration_complete(from); test_migrate_end(from, to, true); - g_free(uri); } #if 0 /* Currently upset on aarch64 TCG */ static void test_ignore_shared(void) { - char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); QTestState *from, *to; if (test_migrate_start(&from, &to, uri, false, true, NULL, NULL)) { @@ -873,7 +859,6 @@ static void test_ignore_shared(void) g_assert_cmpint(read_ram_property_int(from, "transferred"), <, 1024 * 1024); test_migrate_end(from, to, true); - g_free(uri); } #endif @@ -898,8 +883,8 @@ static void test_xbzrle(const char *uri) migrate_set_parameter_int(from, "xbzrle-cache-size", 33554432); - migrate_set_capability(from, "xbzrle", "true"); - migrate_set_capability(to, "xbzrle", "true"); + migrate_set_capability(from, "xbzrle", true); + migrate_set_capability(to, "xbzrle", true); /* Wait for the first serial output from the source */ wait_for_serial("src_serial"); @@ -925,16 +910,15 @@ static void test_xbzrle(const char *uri) static void test_xbzrle_unix(void) { - char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); test_xbzrle(uri); - g_free(uri); } static void test_precopy_tcp(void) { MigrateStart *args = migrate_start_new(); - char *uri; + g_autofree char *uri = NULL; QTestState *from, *to; if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", args)) { @@ -971,7 +955,6 @@ static void test_precopy_tcp(void) wait_for_migration_complete(from); test_migrate_end(from, to, true); - g_free(uri); } static void test_migrate_fd_proto(void) @@ -1060,7 +1043,7 @@ static void test_migrate_fd_proto(void) static void do_test_validate_uuid(MigrateStart *args, bool should_fail) { - char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); QTestState *from, *to; if (test_migrate_start(&from, &to, uri, args)) { @@ -1088,7 +1071,6 @@ static void do_test_validate_uuid(MigrateStart *args, bool should_fail) } test_migrate_end(from, to, false); - g_free(uri); } static void test_validate_uuid(void) @@ -1136,7 +1118,7 @@ static void test_validate_uuid_dst_not_set(void) static void test_migrate_auto_converge(void) { - char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); MigrateStart *args = migrate_start_new(); QTestState *from, *to; int64_t remaining, percentage; @@ -1214,7 +1196,6 @@ static void test_migrate_auto_converge(void) wait_for_serial("dest_serial"); wait_for_migration_complete(from); - g_free(uri); test_migrate_end(from, to, true); } @@ -1224,7 +1205,7 @@ static void test_multifd_tcp(const char *method) MigrateStart *args = migrate_start_new(); QTestState *from, *to; QDict *rsp; - char *uri; + g_autofree char *uri = NULL; if (test_migrate_start(&from, &to, "defer", args)) { return; @@ -1246,8 +1227,8 @@ static void test_multifd_tcp(const char *method) migrate_set_parameter_str(from, "multifd-compression", method); migrate_set_parameter_str(to, "multifd-compression", method); - migrate_set_capability(from, "multifd", "true"); - migrate_set_capability(to, "multifd", "true"); + migrate_set_capability(from, "multifd", true); + migrate_set_capability(to, "multifd", true); /* Start incoming migration from the 1st socket */ rsp = wait_command(to, "{ 'execute': 'migrate-incoming'," @@ -1273,7 +1254,6 @@ static void test_multifd_tcp(const char *method) wait_for_serial("dest_serial"); wait_for_migration_complete(from); test_migrate_end(from, to, true); - g_free(uri); } static void test_multifd_tcp_none(void) @@ -1309,7 +1289,7 @@ static void test_multifd_tcp_cancel(void) MigrateStart *args = migrate_start_new(); QTestState *from, *to, *to2; QDict *rsp; - char *uri; + g_autofree char *uri = NULL; args->hide_stderr = true; @@ -1330,8 +1310,8 @@ static void test_multifd_tcp_cancel(void) migrate_set_parameter_int(from, "multifd-channels", 16); migrate_set_parameter_int(to, "multifd-channels", 16); - migrate_set_capability(from, "multifd", "true"); - migrate_set_capability(to, "multifd", "true"); + migrate_set_capability(from, "multifd", true); + migrate_set_capability(to, "multifd", true); /* Start incoming migration from the 1st socket */ rsp = wait_command(to, "{ 'execute': 'migrate-incoming'," @@ -1358,7 +1338,7 @@ static void test_multifd_tcp_cancel(void) migrate_set_parameter_int(to2, "multifd-channels", 16); - migrate_set_capability(to2, "multifd", "true"); + migrate_set_capability(to2, "multifd", true); /* Start incoming migration from the 1st socket */ rsp = wait_command(to2, "{ 'execute': 'migrate-incoming'," @@ -1387,7 +1367,6 @@ static void test_multifd_tcp_cancel(void) wait_for_serial("dest_serial"); wait_for_migration_complete(from); test_migrate_end(from, to2, true); - g_free(uri); } int main(int argc, char **argv) diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c index bd15a1c294..a54fd70d27 100644 --- a/tests/qtest/npcm7xx_pwm-test.c +++ b/tests/qtest/npcm7xx_pwm-test.c @@ -201,7 +201,7 @@ static int pwm_module_index(const PWMModule *module) { ptrdiff_t diff = module - pwm_module_list; - g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list)); + g_assert(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list)); return diff; } @@ -211,7 +211,7 @@ static int pwm_index(const PWM *pwm) { ptrdiff_t diff = pwm - pwm_list; - g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list)); + g_assert(diff >= 0 && diff < ARRAY_SIZE(pwm_list)); return diff; } diff --git a/tests/qtest/rtc-test.c b/tests/qtest/rtc-test.c index 402ce2c609..8126ab1bdb 100644 --- a/tests/qtest/rtc-test.c +++ b/tests/qtest/rtc-test.c @@ -686,7 +686,7 @@ static void periodic_timer(void) int main(int argc, char **argv) { - QTestState *s = NULL; + QTestState *s; int ret; g_test_init(&argc, &argv, NULL); @@ -712,9 +712,7 @@ int main(int argc, char **argv) ret = g_test_run(); - if (s) { - qtest_quit(s); - } + qtest_quit(s); return ret; } diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c index b70cc32d60..3a40ff3f96 100644 --- a/tests/qtest/tpm-util.c +++ b/tests/qtest/tpm-util.c @@ -289,6 +289,6 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu, *dst_qemu = qtest_init(dst_qemu_args); - free(src_qemu_args); - free(dst_qemu_args); + g_free(src_qemu_args); + g_free(dst_qemu_args); } diff --git a/tests/tcg/README b/tests/tcg/README index 2a58f9a058..706bb185b4 100644 --- a/tests/tcg/README +++ b/tests/tcg/README @@ -7,9 +7,3 @@ CRIS ==== The testsuite for CRIS is in tests/tcg/cris. You can run it with "make test-cris". - -LM32 -==== -The testsuite for LM32 is in tests/tcg/lm32. You can run it -with "make test-lm32". - diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index fa1a4261a4..8f20ce065d 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -96,7 +96,7 @@ for target in $target_list; do xtensa|xtensaeb) arches=xtensa ;; - alpha|cris|hexagon|hppa|i386|lm32|microblaze|microblazeel|m68k|openrisc|riscv64|s390x|sh4|sparc64) + alpha|cris|hexagon|hppa|i386|microblaze|microblazeel|m68k|openrisc|riscv64|s390x|sh4|sparc64) arches=$target ;; *) diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile deleted file mode 100644 index 57e7363b2c..0000000000 --- a/tests/tcg/lm32/Makefile +++ /dev/null @@ -1,106 +0,0 @@ --include ../../../config-host.mak - -CROSS=lm32-elf- - -SIM = qemu-system-lm32 -SIMFLAGS = -M lm32-evr -nographic -semihosting -net none -kernel - -CC = $(CROSS)gcc -AS = $(CROSS)as -AS = $(CC) -x assembler -SIZE = $(CROSS)size -LD = $(CC) -OBJCOPY = $(CROSS)objcopy - -TSRC_PATH = $(SRC_PATH)/tests/tcg/lm32 - -LDFLAGS = -T$(TSRC_PATH)/linker.ld -ASFLAGS += -Wa,-I,$(TSRC_PATH)/ - -CRT = crt.o -HELPER = helper.o -TESTCASES += test_add.tst -TESTCASES += test_addi.tst -TESTCASES += test_and.tst -TESTCASES += test_andhi.tst -TESTCASES += test_andi.tst -TESTCASES += test_b.tst -TESTCASES += test_be.tst -TESTCASES += test_bg.tst -TESTCASES += test_bge.tst -TESTCASES += test_bgeu.tst -TESTCASES += test_bgu.tst -TESTCASES += test_bi.tst -TESTCASES += test_bne.tst -TESTCASES += test_break.tst -TESTCASES += test_bret.tst -TESTCASES += test_call.tst -TESTCASES += test_calli.tst -TESTCASES += test_cmpe.tst -TESTCASES += test_cmpei.tst -TESTCASES += test_cmpg.tst -TESTCASES += test_cmpgi.tst -TESTCASES += test_cmpge.tst -TESTCASES += test_cmpgei.tst -TESTCASES += test_cmpgeu.tst -TESTCASES += test_cmpgeui.tst -TESTCASES += test_cmpgu.tst -TESTCASES += test_cmpgui.tst -TESTCASES += test_cmpne.tst -TESTCASES += test_cmpnei.tst -TESTCASES += test_divu.tst -TESTCASES += test_eret.tst -TESTCASES += test_lb.tst -TESTCASES += test_lbu.tst -TESTCASES += test_lh.tst -TESTCASES += test_lhu.tst -TESTCASES += test_lw.tst -TESTCASES += test_modu.tst -TESTCASES += test_mul.tst -TESTCASES += test_muli.tst -TESTCASES += test_nor.tst -TESTCASES += test_nori.tst -TESTCASES += test_or.tst -TESTCASES += test_ori.tst -TESTCASES += test_orhi.tst -#TESTCASES += test_rcsr.tst -TESTCASES += test_ret.tst -TESTCASES += test_sb.tst -TESTCASES += test_scall.tst -TESTCASES += test_sextb.tst -TESTCASES += test_sexth.tst -TESTCASES += test_sh.tst -TESTCASES += test_sl.tst -TESTCASES += test_sli.tst -TESTCASES += test_sr.tst -TESTCASES += test_sri.tst -TESTCASES += test_sru.tst -TESTCASES += test_srui.tst -TESTCASES += test_sub.tst -TESTCASES += test_sw.tst -#TESTCASES += test_wcsr.tst -TESTCASES += test_xnor.tst -TESTCASES += test_xnori.tst -TESTCASES += test_xor.tst -TESTCASES += test_xori.tst - -all: build - -%.o: $(TSRC_PATH)/%.c - $(CC) $(CFLAGS) -c $< -o $@ - -%.o: $(TSRC_PATH)/%.S - $(AS) $(ASFLAGS) -c $< -o $@ - -%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT) $(HELPER) - $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $(HELPER) $< -o $@ - -build: $(TESTCASES) - -check: $(TESTCASES:test_%.tst=check_%) - -check_%: test_%.tst - @$(SIM) $(SIMFLAGS) $< - -clean: - $(RM) -fr $(TESTCASES) $(CRT) $(HELPER) diff --git a/tests/tcg/lm32/crt.S b/tests/tcg/lm32/crt.S deleted file mode 100644 index fc437a3de1..0000000000 --- a/tests/tcg/lm32/crt.S +++ /dev/null @@ -1,84 +0,0 @@ -.text -.global _start - -_start: -_reset_handler: - xor r0, r0, r0 - mvhi r1, hi(_start) - ori r1, r1, lo(_start) - wcsr eba, r1 - wcsr deba, r1 - mvhi sp, hi(_fstack) - ori sp, sp, lo(_fstack) - bi _main - -_breakpoint_handler: - ori r25, r25, 1 - addi ra, ba, 4 - ret - nop - nop - nop - nop - nop - -_instruction_bus_error_handler: - ori r25, r25, 2 - addi ra, ea, 4 - ret - nop - nop - nop - nop - nop - -_watchpoint_handler: - ori r25, r25, 4 - addi ra, ba, 4 - ret - nop - nop - nop - nop - nop - -_data_bus_error_handler: - ori r25, r25, 8 - addi ra, ea, 4 - ret - nop - nop - nop - nop - nop - -_divide_by_zero_handler: - ori r25, r25, 16 - addi ra, ea, 4 - ret - nop - nop - nop - nop - nop - -_interrupt_handler: - ori r25, r25, 32 - addi ra, ea, 4 - ret - nop - nop - nop - nop - nop - -_system_call_handler: - ori r25, r25, 64 - addi ra, ea, 4 - ret - nop - nop - nop - nop - nop - diff --git a/tests/tcg/lm32/helper.S b/tests/tcg/lm32/helper.S deleted file mode 100644 index 3351d41e84..0000000000 --- a/tests/tcg/lm32/helper.S +++ /dev/null @@ -1,65 +0,0 @@ -.text -.global _start, _write, _exit -.global _tc_fail, _tc_pass - -_write: - addi sp, sp, -4 - sw (sp+4), r8 - mvi r8, 5 - scall - lw r8, (sp+4) - addi sp, sp, 4 - ret - -_exit: - mvi r8, 1 - scall -1: - bi 1b - -_tc_pass: -.data -1: - .ascii "OK\n" -2: -.text - addi sp, sp, -16 - sw (sp+4), ra - sw (sp+8), r1 - sw (sp+12), r2 - sw (sp+16), r3 - mvi r1, 1 - mvhi r2, hi(1b) - ori r2, r2, lo(1b) - mvi r3, (2b - 1b) - calli _write - lw r3, (sp+16) - lw r2, (sp+12) - lw r1, (sp+8) - lw ra, (sp+4) - addi sp, sp, 16 - ret - -_tc_fail: -.data -1: - .ascii "FAILED\n" -2: -.text - addi sp, sp, -16 - sw (sp+4), ra - sw (sp+8), r1 - sw (sp+12), r2 - sw (sp+16), r3 - sw (sp+4), ra - mvi r1, 1 - mvhi r2, hi(1b) - ori r2, r2, lo(1b) - mvi r3, (2b - 1b) - calli _write - lw r3, (sp+16) - lw r2, (sp+12) - lw r1, (sp+8) - lw ra, (sp+4) - addi sp, sp, 16 - ret diff --git a/tests/tcg/lm32/linker.ld b/tests/tcg/lm32/linker.ld deleted file mode 100644 index 52d43a4c74..0000000000 --- a/tests/tcg/lm32/linker.ld +++ /dev/null @@ -1,55 +0,0 @@ -OUTPUT_FORMAT("elf32-lm32") -ENTRY(_start) - -__DYNAMIC = 0; - -MEMORY { - ram : ORIGIN = 0x08000000, LENGTH = 0x04000000 /* 64M */ -} - -SECTIONS -{ - .text : - { - _ftext = .; - *(.text .stub .text.* .gnu.linkonce.t.*) - _etext = .; - } > ram - - .rodata : - { - . = ALIGN(4); - _frodata = .; - *(.rodata .rodata.* .gnu.linkonce.r.*) - *(.rodata1) - _erodata = .; - } > ram - - .data : - { - . = ALIGN(4); - _fdata = .; - *(.data .data.* .gnu.linkonce.d.*) - *(.data1) - _gp = ALIGN(16); - *(.sdata .sdata.* .gnu.linkonce.s.*) - _edata = .; - } > ram - - .bss : - { - . = ALIGN(4); - _fbss = .; - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - _ebss = .; - _end = .; - } > ram -} - -PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4); - diff --git a/tests/tcg/lm32/macros.inc b/tests/tcg/lm32/macros.inc deleted file mode 100644 index 360ad53c9f..0000000000 --- a/tests/tcg/lm32/macros.inc +++ /dev/null @@ -1,90 +0,0 @@ - -.equ MAX_TESTNAME_LEN, 32 -.macro test_name name - .data -tn_\name: - .ascii "\name" - .space MAX_TESTNAME_LEN - (. - tn_\name), ' ' - .text - .global \name -\name: - addi sp, sp, -12 - sw (sp+4), r1 - sw (sp+8), r2 - sw (sp+12), r3 - mvi r1, 1 - mvhi r2, hi(tn_\name) - ori r2, r2, lo(tn_\name) - mvi r3, MAX_TESTNAME_LEN - calli _write - lw r3, (sp+12) - lw r2, (sp+8) - lw r1, (sp+4) - addi sp, sp, 12 -.endm - -.macro load reg val - mvhi \reg, hi(\val) - ori \reg, \reg, lo(\val) -.endm - -.macro tc_pass - calli _tc_pass -.endm - -.macro tc_fail - addi r12, r12, 1 - calli _tc_fail -.endm - -.macro check_r3 val - mvhi r13, hi(\val) - ori r13, r13, lo(\val) - be r3, r13, 1f - tc_fail - bi 2f -1: - tc_pass -2: -.endm - -.macro check_mem adr val - mvhi r13, hi(\adr) - ori r13, r13, lo(\adr) - mvhi r14, hi(\val) - ori r14, r14, lo(\val) - lw r13, (r13+0) - be r13, r14, 1f - tc_fail - bi 2f -1: - tc_pass -2: -.endm - -.macro check_excp excp - andi r13, r25, \excp - bne r13, r0, 1f - tc_fail - bi 2f -1: - tc_pass -2: -.endm - -.macro start - .global _main - .text -_main: - mvi r12, 0 -.endm - -.macro end - mv r1, r12 - calli _exit -.endm - -# base + -# 0 ctrl -# 4 pass/fail -# 8 ptr to test name diff --git a/tests/tcg/lm32/test_add.S b/tests/tcg/lm32/test_add.S deleted file mode 100644 index 030ad197bb..0000000000 --- a/tests/tcg/lm32/test_add.S +++ /dev/null @@ -1,75 +0,0 @@ -.include "macros.inc" - -start - -test_name ADD_1 -mvi r1, 0 -mvi r2, 0 -add r3, r1, r2 -check_r3 0 - -test_name ADD_2 -mvi r1, 0 -mvi r2, 1 -add r3, r1, r2 -check_r3 1 - -test_name ADD_3 -mvi r1, 1 -mvi r2, 0 -add r3, r1, r2 -check_r3 1 - -test_name ADD_4 -mvi r1, 1 -mvi r2, -1 -add r3, r1, r2 -check_r3 0 - -test_name ADD_5 -mvi r1, -1 -mvi r2, 1 -add r3, r1, r2 -check_r3 0 - -test_name ADD_6 -mvi r1, -1 -mvi r2, 0 -add r3, r1, r2 -check_r3 -1 - -test_name ADD_7 -mvi r1, 0 -mvi r2, -1 -add r3, r1, r2 -check_r3 -1 - -test_name ADD_8 -mvi r3, 2 -add r3, r3, r3 -check_r3 4 - -test_name ADD_9 -mvi r1, 4 -mvi r3, 2 -add r3, r1, r3 -check_r3 6 - -test_name ADD_10 -mvi r1, 4 -mvi r3, 2 -add r3, r3, r1 -check_r3 6 - -test_name ADD_11 -mvi r1, 4 -add r3, r1, r1 -check_r3 8 - -test_name ADD_12 -load r1 0x12345678 -load r2 0xabcdef97 -add r3, r1, r2 -check_r3 0xbe02460f - -end diff --git a/tests/tcg/lm32/test_addi.S b/tests/tcg/lm32/test_addi.S deleted file mode 100644 index 68e766d1e5..0000000000 --- a/tests/tcg/lm32/test_addi.S +++ /dev/null @@ -1,56 +0,0 @@ -.include "macros.inc" - -start - -test_name ADDI_1 -mvi r1, 0 -addi r3, r1, 0 -check_r3 0 - -test_name ADDI_2 -mvi r1, 0 -addi r3, r1, 1 -check_r3 1 - -test_name ADDI_3 -mvi r1, 1 -addi r3, r1, 0 -check_r3 1 - -test_name ADDI_4 -mvi r1, 1 -addi r3, r1, -1 -check_r3 0 - -test_name ADDI_5 -mvi r1, -1 -addi r3, r1, 1 -check_r3 0 - -test_name ADDI_6 -mvi r1, -1 -addi r3, r1, 0 -check_r3 -1 - -test_name ADDI_7 -mvi r1, 0 -addi r3, r1, -1 -check_r3 -1 - -test_name ADDI_8 -mvi r3, 4 -addi r3, r3, 4 -check_r3 8 - -test_name ADDI_9 -mvi r3, 4 -addi r3, r3, -4 -check_r3 0 - -test_name ADDI_10 -mvi r3, 4 -addi r3, r3, -5 -check_r3 -1 - -end - diff --git a/tests/tcg/lm32/test_and.S b/tests/tcg/lm32/test_and.S deleted file mode 100644 index 80962ce7a2..0000000000 --- a/tests/tcg/lm32/test_and.S +++ /dev/null @@ -1,45 +0,0 @@ -.include "macros.inc" - -start - -test_name AND_1 -mvi r1, 0 -mvi r2, 0 -and r3, r1, r2 -check_r3 0 - -test_name AND_2 -mvi r1, 0 -mvi r2, 1 -and r3, r1, r2 -check_r3 0 - -test_name AND_3 -mvi r1, 1 -mvi r2, 1 -and r3, r1, r2 -check_r3 1 - -test_name AND_4 -mvi r3, 7 -and r3, r3, r3 -check_r3 7 - -test_name AND_5 -mvi r1, 7 -and r3, r1, r1 -check_r3 7 - -test_name AND_6 -mvi r1, 7 -mvi r3, 0 -and r3, r1, r3 -check_r3 0 - -test_name AND_7 -load r1 0xaa55aa55 -load r2 0x55aa55aa -and r3, r1, r2 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_andhi.S b/tests/tcg/lm32/test_andhi.S deleted file mode 100644 index 4f73af550b..0000000000 --- a/tests/tcg/lm32/test_andhi.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name ANDHI_1 -mvi r1, 0 -andhi r3, r1, 0 -check_r3 0 - -test_name ANDHI_2 -mvi r1, 1 -andhi r3, r1, 1 -check_r3 0 - -test_name ANDHI_3 -load r1 0x000f0000 -andhi r3, r1, 1 -check_r3 0x00010000 - -test_name ANDHI_4 -load r1 0xffffffff -andhi r3, r1, 0xffff -check_r3 0xffff0000 - -test_name ANDHI_5 -load r1 0xffffffff -andhi r3, r1, 0 -check_r3 0 - -test_name ANDHI_6 -load r3 0x55aaffff -andhi r3, r3, 0xaaaa -check_r3 0x00aa0000 - -end diff --git a/tests/tcg/lm32/test_andi.S b/tests/tcg/lm32/test_andi.S deleted file mode 100644 index da1b0a32f7..0000000000 --- a/tests/tcg/lm32/test_andi.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name ANDI_1 -mvi r1, 0 -andi r3, r1, 0 -check_r3 0 - -test_name ANDI_2 -mvi r1, 1 -andi r3, r1, 1 -check_r3 1 - -test_name ANDI_3 -load r1 0x000f0000 -andi r3, r1, 1 -check_r3 0 - -test_name ANDI_4 -load r1 0xffffffff -andi r3, r1, 0xffff -check_r3 0xffff - -test_name ANDI_5 -load r1 0xffffffff -andi r3, r1, 0 -check_r3 0 - -test_name ANDI_6 -load r3 0xffff55aa -andi r3, r3, 0xaaaa -check_r3 0x000000aa - -end diff --git a/tests/tcg/lm32/test_b.S b/tests/tcg/lm32/test_b.S deleted file mode 100644 index 98172d8a95..0000000000 --- a/tests/tcg/lm32/test_b.S +++ /dev/null @@ -1,13 +0,0 @@ -.include "macros.inc" - -start - -test_name B_1 -load r1 jump -b r1 -tc_fail -end - -jump: -tc_pass -end diff --git a/tests/tcg/lm32/test_be.S b/tests/tcg/lm32/test_be.S deleted file mode 100644 index 635cabacad..0000000000 --- a/tests/tcg/lm32/test_be.S +++ /dev/null @@ -1,48 +0,0 @@ -.include "macros.inc" - -start - -test_name BE_1 -mvi r1, 0 -mvi r2, 0 -be r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BE_2 -mvi r1, 1 -mvi r2, 0 -be r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BE_3 -mvi r1, 0 -mvi r2, 1 -be r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -bi 2f -1: -tc_pass -bi 3f -2: -test_name BE_4 -mvi r1, 1 -mvi r2, 1 -be r1, r2, 1b -tc_fail -3: - -end - diff --git a/tests/tcg/lm32/test_bg.S b/tests/tcg/lm32/test_bg.S deleted file mode 100644 index 81823c2304..0000000000 --- a/tests/tcg/lm32/test_bg.S +++ /dev/null @@ -1,78 +0,0 @@ -.include "macros.inc" - -start - -test_name BG_1 -mvi r1, 0 -mvi r2, 0 -bg r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BG_2 -mvi r1, 1 -mvi r2, 0 -bg r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BG_3 -mvi r1, 0 -mvi r2, 1 -bg r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BG_4 -mvi r1, 0 -mvi r2, -1 -bg r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BG_5 -mvi r1, -1 -mvi r2, 0 -bg r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BG_6 -mvi r1, -1 -mvi r2, -1 -bg r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -bi 2f -1: -tc_pass -bi 3f -2: -test_name BG_7 -mvi r1, 1 -mvi r2, 0 -bg r1, r2, 1b -tc_fail -3: - -end - diff --git a/tests/tcg/lm32/test_bge.S b/tests/tcg/lm32/test_bge.S deleted file mode 100644 index 6684d15a55..0000000000 --- a/tests/tcg/lm32/test_bge.S +++ /dev/null @@ -1,78 +0,0 @@ -.include "macros.inc" - -start - -test_name BGE_1 -mvi r1, 0 -mvi r2, 0 -bge r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGE_2 -mvi r1, 1 -mvi r2, 0 -bge r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGE_3 -mvi r1, 0 -mvi r2, 1 -bge r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGE_4 -mvi r1, 0 -mvi r2, -1 -bge r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGE_5 -mvi r1, -1 -mvi r2, 0 -bge r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGE_6 -mvi r1, -1 -mvi r2, -1 -bge r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -bi 2f -1: -tc_pass -bi 3f -2: -test_name BGE_7 -mvi r1, 1 -mvi r2, 0 -bge r1, r2, 1b -tc_fail -3: - -end - diff --git a/tests/tcg/lm32/test_bgeu.S b/tests/tcg/lm32/test_bgeu.S deleted file mode 100644 index be440308fd..0000000000 --- a/tests/tcg/lm32/test_bgeu.S +++ /dev/null @@ -1,78 +0,0 @@ -.include "macros.inc" - -start - -test_name BGEU_1 -mvi r1, 0 -mvi r2, 0 -bgeu r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGEU_2 -mvi r1, 1 -mvi r2, 0 -bgeu r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGEU_3 -mvi r1, 0 -mvi r2, 1 -bgeu r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGEU_4 -mvi r1, 0 -mvi r2, -1 -bgeu r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGEU_5 -mvi r1, -1 -mvi r2, 0 -bgeu r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGEU_6 -mvi r1, -1 -mvi r2, -1 -bgeu r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -bi 2f -1: -tc_pass -bi 3f -2: -test_name BGEU_7 -mvi r1, 1 -mvi r2, 0 -bgeu r1, r2, 1b -tc_fail -3: - -end - diff --git a/tests/tcg/lm32/test_bgu.S b/tests/tcg/lm32/test_bgu.S deleted file mode 100644 index 8cc695b310..0000000000 --- a/tests/tcg/lm32/test_bgu.S +++ /dev/null @@ -1,78 +0,0 @@ -.include "macros.inc" - -start - -test_name BGU_1 -mvi r1, 0 -mvi r2, 0 -bgu r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGU_2 -mvi r1, 1 -mvi r2, 0 -bgu r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGU_3 -mvi r1, 0 -mvi r2, 1 -bgu r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGU_4 -mvi r1, 0 -mvi r2, -1 -bgu r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BGU_5 -mvi r1, -1 -mvi r2, 0 -bgu r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BGU_6 -mvi r1, -1 -mvi r2, -1 -bgu r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -bi 2f -1: -tc_pass -bi 3f -2: -test_name BGU_7 -mvi r1, 1 -mvi r2, 0 -bgu r1, r2, 1b -tc_fail -3: - -end - diff --git a/tests/tcg/lm32/test_bi.S b/tests/tcg/lm32/test_bi.S deleted file mode 100644 index a1fbd6fc07..0000000000 --- a/tests/tcg/lm32/test_bi.S +++ /dev/null @@ -1,23 +0,0 @@ -.include "macros.inc" - -start - -test_name BI_1 -bi jump -tc_fail -end - -jump_back: -tc_pass -end - -jump: -tc_pass - -test_name BI_2 -bi jump_back -tc_fail - -end - - diff --git a/tests/tcg/lm32/test_bne.S b/tests/tcg/lm32/test_bne.S deleted file mode 100644 index 871a006755..0000000000 --- a/tests/tcg/lm32/test_bne.S +++ /dev/null @@ -1,48 +0,0 @@ -.include "macros.inc" - -start - -test_name BNE_1 -mvi r1, 0 -mvi r2, 0 -bne r1, r2, 1f -tc_pass -bi 2f -1: -tc_fail -2: - -test_name BNE_2 -mvi r1, 1 -mvi r2, 0 -bne r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -test_name BNE_3 -mvi r1, 0 -mvi r2, 1 -bne r1, r2, 1f -tc_fail -bi 2f -1: -tc_pass -2: - -bi 2f -1: -tc_fail -bi 3f -2: -test_name BNE_4 -mvi r1, 1 -mvi r2, 1 -bne r1, r2, 1b -tc_pass -3: - -end - diff --git a/tests/tcg/lm32/test_break.S b/tests/tcg/lm32/test_break.S deleted file mode 100644 index 0384fc6128..0000000000 --- a/tests/tcg/lm32/test_break.S +++ /dev/null @@ -1,20 +0,0 @@ -.include "macros.inc" - -start - -test_name BREAK_1 -mvi r1, 1 -wcsr IE, r1 -insn: -break -check_excp 1 - -test_name BREAK_2 -mv r3, ba -check_r3 insn - -test_name BREAK_3 -rcsr r3, IE -check_r3 4 - -end diff --git a/tests/tcg/lm32/test_bret.S b/tests/tcg/lm32/test_bret.S deleted file mode 100644 index 645210e434..0000000000 --- a/tests/tcg/lm32/test_bret.S +++ /dev/null @@ -1,38 +0,0 @@ -.include "macros.inc" - -start - -test_name BRET_1 -mvi r1, 4 -wcsr IE, r1 -load ba mark -bret -tc_fail -bi 1f - -mark: -tc_pass - -1: -test_name BRET_2 -rcsr r3, IE -check_r3 5 - -test_name BRET_3 -mvi r1, 0 -wcsr IE, r1 -load ba mark2 -bret -tc_fail -bi 1f - -mark2: -tc_pass - -1: -test_name BRET_4 -rcsr r3, IE -check_r3 0 - -end - diff --git a/tests/tcg/lm32/test_call.S b/tests/tcg/lm32/test_call.S deleted file mode 100644 index 1b91a5f2be..0000000000 --- a/tests/tcg/lm32/test_call.S +++ /dev/null @@ -1,16 +0,0 @@ -.include "macros.inc" - -start - -test_name CALL_1 -load r1 mark -call r1 -return: - -tc_fail -end - -mark: -mv r3, ra -check_r3 return -end diff --git a/tests/tcg/lm32/test_calli.S b/tests/tcg/lm32/test_calli.S deleted file mode 100644 index 1d87ae6e21..0000000000 --- a/tests/tcg/lm32/test_calli.S +++ /dev/null @@ -1,15 +0,0 @@ -.include "macros.inc" - -start - -test_name CALLI_1 -calli mark -return: - -tc_fail -end - -mark: -mv r3, ra -check_r3 return -end diff --git a/tests/tcg/lm32/test_cmpe.S b/tests/tcg/lm32/test_cmpe.S deleted file mode 100644 index 60a885500b..0000000000 --- a/tests/tcg/lm32/test_cmpe.S +++ /dev/null @@ -1,40 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPE_1 -mvi r1, 0 -mvi r2, 0 -cmpe r3, r1, r2 -check_r3 1 - -test_name CMPE_2 -mvi r1, 0 -mvi r2, 1 -cmpe r3, r1, r2 -check_r3 0 - -test_name CMPE_3 -mvi r1, 1 -mvi r2, 0 -cmpe r3, r1, r2 -check_r3 0 - -test_name CMPE_4 -mvi r3, 0 -mvi r2, 1 -cmpe r3, r3, r2 -check_r3 0 - -test_name CMPE_5 -mvi r3, 0 -mvi r2, 0 -cmpe r3, r3, r2 -check_r3 1 - -test_name CMPE_6 -mvi r3, 0 -cmpe r3, r3, r3 -check_r3 1 - -end diff --git a/tests/tcg/lm32/test_cmpei.S b/tests/tcg/lm32/test_cmpei.S deleted file mode 100644 index c3d3566ad3..0000000000 --- a/tests/tcg/lm32/test_cmpei.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPEI_1 -mvi r1, 0 -cmpei r3, r1, 0 -check_r3 1 - -test_name CMPEI_2 -mvi r1, 0 -cmpei r3, r1, 1 -check_r3 0 - -test_name CMPEI_3 -mvi r1, 1 -cmpei r3, r1, 0 -check_r3 0 - -test_name CMPEI_4 -load r1 0xffffffff -cmpei r3, r1, -1 -check_r3 1 - -test_name CMPEI_5 -mvi r3, 0 -cmpei r3, r3, 0 -check_r3 1 - -test_name CMPEI_6 -mvi r3, 0 -cmpei r3, r3, 1 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_cmpg.S b/tests/tcg/lm32/test_cmpg.S deleted file mode 100644 index 012407874c..0000000000 --- a/tests/tcg/lm32/test_cmpg.S +++ /dev/null @@ -1,64 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPG_1 -mvi r1, 0 -mvi r2, 0 -cmpg r3, r1, r2 -check_r3 0 - -test_name CMPG_2 -mvi r1, 0 -mvi r2, 1 -cmpg r3, r1, r2 -check_r3 0 - -test_name CMPG_3 -mvi r1, 1 -mvi r2, 0 -cmpg r3, r1, r2 -check_r3 1 - -test_name CMPG_4 -mvi r1, 1 -mvi r2, 1 -cmpg r3, r1, r2 -check_r3 0 - -test_name CMPG_5 -mvi r1, 0 -mvi r2, -1 -cmpg r3, r1, r2 -check_r3 1 - -test_name CMPG_6 -mvi r1, -1 -mvi r2, 0 -cmpg r3, r1, r2 -check_r3 0 - -test_name CMPG_7 -mvi r1, -1 -mvi r2, -1 -cmpg r3, r1, r2 -check_r3 0 - -test_name CMPG_8 -mvi r3, 0 -mvi r2, 1 -cmpg r3, r3, r2 -check_r3 0 - -test_name CMPG_9 -mvi r3, 1 -mvi r2, 0 -cmpg r3, r3, r2 -check_r3 1 - -test_name CMPG_10 -mvi r3, 0 -cmpg r3, r3, r3 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_cmpge.S b/tests/tcg/lm32/test_cmpge.S deleted file mode 100644 index 84620a00e3..0000000000 --- a/tests/tcg/lm32/test_cmpge.S +++ /dev/null @@ -1,64 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGE_1 -mvi r1, 0 -mvi r2, 0 -cmpge r3, r1, r2 -check_r3 1 - -test_name CMPGE_2 -mvi r1, 0 -mvi r2, 1 -cmpge r3, r1, r2 -check_r3 0 - -test_name CMPGE_3 -mvi r1, 1 -mvi r2, 0 -cmpge r3, r1, r2 -check_r3 1 - -test_name CMPGE_4 -mvi r1, 1 -mvi r2, 1 -cmpge r3, r1, r2 -check_r3 1 - -test_name CMPGE_5 -mvi r1, 0 -mvi r2, -1 -cmpge r3, r1, r2 -check_r3 1 - -test_name CMPGE_6 -mvi r1, -1 -mvi r2, 0 -cmpge r3, r1, r2 -check_r3 0 - -test_name CMPGE_7 -mvi r1, -1 -mvi r2, -1 -cmpge r3, r1, r2 -check_r3 1 - -test_name CMPGE_8 -mvi r3, 0 -mvi r2, 1 -cmpge r3, r3, r2 -check_r3 0 - -test_name CMPGE_9 -mvi r3, 1 -mvi r2, 0 -cmpge r3, r3, r2 -check_r3 1 - -test_name CMPGE_10 -mvi r3, 0 -cmpge r3, r3, r3 -check_r3 1 - -end diff --git a/tests/tcg/lm32/test_cmpgei.S b/tests/tcg/lm32/test_cmpgei.S deleted file mode 100644 index 6e388a2a35..0000000000 --- a/tests/tcg/lm32/test_cmpgei.S +++ /dev/null @@ -1,70 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGEI_1 -mvi r1, 0 -cmpgei r3, r1, 0 -check_r3 1 - -test_name CMPGEI_2 -mvi r1, 0 -cmpgei r3, r1, 1 -check_r3 0 - -test_name CMPGEI_3 -mvi r1, 1 -cmpgei r3, r1, 0 -check_r3 1 - -test_name CMPGEI_4 -mvi r1, 1 -cmpgei r3, r1, 1 -check_r3 1 - -test_name CMPGEI_5 -mvi r1, 0 -cmpgei r3, r1, -1 -check_r3 1 - -test_name CMPGEI_6 -mvi r1, -1 -cmpgei r3, r1, 0 -check_r3 0 - -test_name CMPGEI_7 -mvi r1, -1 -cmpgei r3, r1, -1 -check_r3 1 - -test_name CMPGEI_8 -mvi r3, 0 -cmpgei r3, r3, 1 -check_r3 0 - -test_name CMPGEI_9 -mvi r3, 1 -cmpgei r3, r3, 0 -check_r3 1 - -test_name CMPGEI_10 -mvi r3, 0 -cmpgei r3, r3, 0 -check_r3 1 - -test_name CMPGEI_11 -mvi r1, 0 -cmpgei r3, r1, -32768 -check_r3 1 - -test_name CMPGEI_12 -mvi r1, -1 -cmpgei r3, r1, -32768 -check_r3 1 - -test_name CMPGEI_13 -mvi r1, -32768 -cmpgei r3, r1, -32768 -check_r3 1 - -end diff --git a/tests/tcg/lm32/test_cmpgeu.S b/tests/tcg/lm32/test_cmpgeu.S deleted file mode 100644 index 2110ccb6b7..0000000000 --- a/tests/tcg/lm32/test_cmpgeu.S +++ /dev/null @@ -1,64 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGEU_1 -mvi r1, 0 -mvi r2, 0 -cmpgeu r3, r1, r2 -check_r3 1 - -test_name CMPGEU_2 -mvi r1, 0 -mvi r2, 1 -cmpgeu r3, r1, r2 -check_r3 0 - -test_name CMPGEU_3 -mvi r1, 1 -mvi r2, 0 -cmpgeu r3, r1, r2 -check_r3 1 - -test_name CMPGEU_4 -mvi r1, 1 -mvi r2, 1 -cmpgeu r3, r1, r2 -check_r3 1 - -test_name CMPGEU_5 -mvi r1, 0 -mvi r2, -1 -cmpgeu r3, r1, r2 -check_r3 0 - -test_name CMPGEU_6 -mvi r1, -1 -mvi r2, 0 -cmpgeu r3, r1, r2 -check_r3 1 - -test_name CMPGEU_7 -mvi r1, -1 -mvi r2, -1 -cmpgeu r3, r1, r2 -check_r3 1 - -test_name CMPGEU_8 -mvi r3, 0 -mvi r2, 1 -cmpgeu r3, r3, r2 -check_r3 0 - -test_name CMPGEU_9 -mvi r3, 1 -mvi r2, 0 -cmpgeu r3, r3, r2 -check_r3 1 - -test_name CMPGEU_10 -mvi r3, 0 -cmpgeu r3, r3, r3 -check_r3 1 - -end diff --git a/tests/tcg/lm32/test_cmpgeui.S b/tests/tcg/lm32/test_cmpgeui.S deleted file mode 100644 index 3866d96cb7..0000000000 --- a/tests/tcg/lm32/test_cmpgeui.S +++ /dev/null @@ -1,70 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGEUI_1 -mvi r1, 0 -cmpgeui r3, r1, 0 -check_r3 1 - -test_name CMPGEUI_2 -mvi r1, 0 -cmpgeui r3, r1, 1 -check_r3 0 - -test_name CMPGEUI_3 -mvi r1, 1 -cmpgeui r3, r1, 0 -check_r3 1 - -test_name CMPGEUI_4 -mvi r1, 1 -cmpgeui r3, r1, 1 -check_r3 1 - -test_name CMPGEUI_5 -mvi r1, 0 -cmpgeui r3, r1, 0xffff -check_r3 0 - -test_name CMPGEUI_6 -mvi r1, -1 -cmpgeui r3, r1, 0 -check_r3 1 - -test_name CMPGEUI_7 -mvi r1, -1 -cmpgeui r3, r1, 0xffff -check_r3 1 - -test_name CMPGEUI_8 -mvi r3, 0 -cmpgeui r3, r3, 1 -check_r3 0 - -test_name CMPGEUI_9 -mvi r3, 1 -cmpgeui r3, r3, 0 -check_r3 1 - -test_name CMPGEUI_10 -mvi r3, 0 -cmpgeui r3, r3, 0 -check_r3 1 - -test_name CMPGEUI_11 -mvi r1, 0 -cmpgeui r3, r1, 0x8000 -check_r3 0 - -test_name CMPGEUI_12 -mvi r1, -1 -cmpgeui r3, r1, 0x8000 -check_r3 1 - -test_name CMPGEUI_13 -ori r1, r0, 0x8000 -cmpgeui r3, r1, 0x8000 -check_r3 1 - -end diff --git a/tests/tcg/lm32/test_cmpgi.S b/tests/tcg/lm32/test_cmpgi.S deleted file mode 100644 index 21695f97ab..0000000000 --- a/tests/tcg/lm32/test_cmpgi.S +++ /dev/null @@ -1,70 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGI_1 -mvi r1, 0 -cmpgi r3, r1, 0 -check_r3 0 - -test_name CMPGI_2 -mvi r1, 0 -cmpgi r3, r1, 1 -check_r3 0 - -test_name CMPGI_3 -mvi r1, 1 -cmpgi r3, r1, 0 -check_r3 1 - -test_name CMPGI_4 -mvi r1, 1 -cmpgi r3, r1, 1 -check_r3 0 - -test_name CMPGI_5 -mvi r1, 0 -cmpgi r3, r1, -1 -check_r3 1 - -test_name CMPGI_6 -mvi r1, -1 -cmpgi r3, r1, 0 -check_r3 0 - -test_name CMPGI_7 -mvi r1, -1 -cmpgi r3, r1, -1 -check_r3 0 - -test_name CMPGI_8 -mvi r3, 0 -cmpgi r3, r3, 1 -check_r3 0 - -test_name CMPGI_9 -mvi r3, 1 -cmpgi r3, r3, 0 -check_r3 1 - -test_name CMPGI_10 -mvi r3, 0 -cmpgi r3, r3, 0 -check_r3 0 - -test_name CMPGI_11 -mvi r1, 0 -cmpgi r3, r1, -32768 -check_r3 1 - -test_name CMPGI_12 -mvi r1, -1 -cmpgi r3, r1, -32768 -check_r3 1 - -test_name CMPGI_13 -mvi r1, -32768 -cmpgi r3, r1, -32768 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_cmpgu.S b/tests/tcg/lm32/test_cmpgu.S deleted file mode 100644 index dd465471ea..0000000000 --- a/tests/tcg/lm32/test_cmpgu.S +++ /dev/null @@ -1,64 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGU_1 -mvi r1, 0 -mvi r2, 0 -cmpgu r3, r1, r2 -check_r3 0 - -test_name CMPGU_2 -mvi r1, 0 -mvi r2, 1 -cmpgu r3, r1, r2 -check_r3 0 - -test_name CMPGU_3 -mvi r1, 1 -mvi r2, 0 -cmpgu r3, r1, r2 -check_r3 1 - -test_name CMPGU_4 -mvi r1, 1 -mvi r2, 1 -cmpgu r3, r1, r2 -check_r3 0 - -test_name CMPGU_5 -mvi r1, 0 -mvi r2, -1 -cmpgu r3, r1, r2 -check_r3 0 - -test_name CMPGU_6 -mvi r1, -1 -mvi r2, 0 -cmpgu r3, r1, r2 -check_r3 1 - -test_name CMPGU_7 -mvi r1, -1 -mvi r2, -1 -cmpgu r3, r1, r2 -check_r3 0 - -test_name CMPGU_8 -mvi r3, 0 -mvi r2, 1 -cmpgu r3, r3, r2 -check_r3 0 - -test_name CMPGU_9 -mvi r3, 1 -mvi r2, 0 -cmpgu r3, r3, r2 -check_r3 1 - -test_name CMPGU_10 -mvi r3, 0 -cmpgu r3, r3, r3 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_cmpgui.S b/tests/tcg/lm32/test_cmpgui.S deleted file mode 100644 index dd94001492..0000000000 --- a/tests/tcg/lm32/test_cmpgui.S +++ /dev/null @@ -1,70 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPGUI_1 -mvi r1, 0 -cmpgui r3, r1, 0 -check_r3 0 - -test_name CMPGUI_2 -mvi r1, 0 -cmpgui r3, r1, 1 -check_r3 0 - -test_name CMPGUI_3 -mvi r1, 1 -cmpgui r3, r1, 0 -check_r3 1 - -test_name CMPGUI_4 -mvi r1, 1 -cmpgui r3, r1, 1 -check_r3 0 - -test_name CMPGUI_5 -mvi r1, 0 -cmpgui r3, r1, 0xffff -check_r3 0 - -test_name CMPGUI_6 -mvi r1, -1 -cmpgui r3, r1, 0 -check_r3 1 - -test_name CMPGUI_7 -mvi r1, -1 -cmpgui r3, r1, 0xffff -check_r3 1 - -test_name CMPGUI_8 -mvi r3, 0 -cmpgui r3, r3, 1 -check_r3 0 - -test_name CMPGUI_9 -mvi r3, 1 -cmpgui r3, r3, 0 -check_r3 1 - -test_name CMPGUI_10 -mvi r3, 0 -cmpgui r3, r3, 0 -check_r3 0 - -test_name CMPGUI_11 -mvi r1, 0 -cmpgui r3, r1, 0x8000 -check_r3 0 - -test_name CMPGUI_12 -mvi r1, -1 -cmpgui r3, r1, 0x8000 -check_r3 1 - -test_name CMPGUI_13 -ori r1, r0, 0x8000 -cmpgui r3, r1, 0x8000 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_cmpne.S b/tests/tcg/lm32/test_cmpne.S deleted file mode 100644 index 0f1078114c..0000000000 --- a/tests/tcg/lm32/test_cmpne.S +++ /dev/null @@ -1,40 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPNE_1 -mvi r1, 0 -mvi r2, 0 -cmpne r3, r1, r2 -check_r3 0 - -test_name CMPNE_2 -mvi r1, 0 -mvi r2, 1 -cmpne r3, r1, r2 -check_r3 1 - -test_name CMPNE_3 -mvi r1, 1 -mvi r2, 0 -cmpne r3, r1, r2 -check_r3 1 - -test_name CMPNE_4 -mvi r3, 0 -mvi r2, 1 -cmpne r3, r3, r2 -check_r3 1 - -test_name CMPNE_5 -mvi r3, 0 -mvi r2, 0 -cmpne r3, r3, r2 -check_r3 0 - -test_name CMPNE_6 -mvi r3, 0 -cmpne r3, r3, r3 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_cmpnei.S b/tests/tcg/lm32/test_cmpnei.S deleted file mode 100644 index 060dd9d394..0000000000 --- a/tests/tcg/lm32/test_cmpnei.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name CMPNEI_1 -mvi r1, 0 -cmpnei r3, r1, 0 -check_r3 0 - -test_name CMPNEI_2 -mvi r1, 0 -cmpnei r3, r1, 1 -check_r3 1 - -test_name CMPNEI_3 -mvi r1, 1 -cmpnei r3, r1, 0 -check_r3 1 - -test_name CMPNEI_4 -load r1 0xffffffff -cmpnei r3, r1, -1 -check_r3 0 - -test_name CMPNEI_5 -mvi r3, 0 -cmpnei r3, r3, 0 -check_r3 0 - -test_name CMPNEI_6 -mvi r3, 0 -cmpnei r3, r3, 1 -check_r3 1 - -end diff --git a/tests/tcg/lm32/test_divu.S b/tests/tcg/lm32/test_divu.S deleted file mode 100644 index f381d095c5..0000000000 --- a/tests/tcg/lm32/test_divu.S +++ /dev/null @@ -1,29 +0,0 @@ -.include "macros.inc" - -start - -test_name DIVU_1 -mvi r1, 0 -mvi r2, 1 -divu r3, r1, r2 -check_r3 0 - -test_name DIVU_2 -mvi r1, 1 -mvi r2, 1 -divu r3, r1, r2 -check_r3 1 - -test_name DIVU_3 -mvi r1, 0 -mvi r2, 0 -divu r3, r1, r2 -check_excp 16 - -test_name DIVU_4 -load r1 0xabcdef12 -load r2 0x12345 -divu r3, r1, r2 -check_r3 0x9700 - -end diff --git a/tests/tcg/lm32/test_eret.S b/tests/tcg/lm32/test_eret.S deleted file mode 100644 index 6830bd1abf..0000000000 --- a/tests/tcg/lm32/test_eret.S +++ /dev/null @@ -1,38 +0,0 @@ -.include "macros.inc" - -start - -test_name ERET_1 -mvi r1, 2 -wcsr IE, r1 -load ea mark -eret -tc_fail -bi 1f - -mark: -tc_pass - -1: -test_name ERET_2 -rcsr r3, IE -check_r3 3 - -test_name ERET_3 -mvi r1, 0 -wcsr IE, r1 -load ea mark2 -eret -tc_fail -bi 1f - -mark2: -tc_pass - -1: -test_name ERET_4 -rcsr r3, IE -check_r3 0 - -end - diff --git a/tests/tcg/lm32/test_lb.S b/tests/tcg/lm32/test_lb.S deleted file mode 100644 index d677eea4c4..0000000000 --- a/tests/tcg/lm32/test_lb.S +++ /dev/null @@ -1,49 +0,0 @@ -.include "macros.inc" - -start - -test_name LB_1 -load r1 data -lb r3, (r1+0) -check_r3 0x7e - -test_name LB_2 -load r1 data -lb r3, (r1+1) -check_r3 0x7f - -test_name LB_3 -load r1 data -lb r3, (r1+-1) -check_r3 0x7d - -test_name LB_4 -load r1 data_msb -lb r3, (r1+0) -check_r3 0xfffffffe - -test_name LB_5 -load r1 data_msb -lb r3, (r1+1) -check_r3 0xffffffff - -test_name LB_6 -load r1 data_msb -lb r3, (r1+-1) -check_r3 0xfffffffd - -test_name LB_7 -load r3 data -lb r3, (r3+0) -check_r3 0x7e - -end - -.data - .align 4 - .byte 0x7a, 0x7b, 0x7c, 0x7d -data: - .byte 0x7e, 0x7f, 0x70, 0x71 - .byte 0xfa, 0xfb, 0xfc, 0xfd -data_msb: - .byte 0xfe, 0xff, 0xf0, 0xf1 diff --git a/tests/tcg/lm32/test_lbu.S b/tests/tcg/lm32/test_lbu.S deleted file mode 100644 index dc5d5f67d3..0000000000 --- a/tests/tcg/lm32/test_lbu.S +++ /dev/null @@ -1,49 +0,0 @@ -.include "macros.inc" - -start - -test_name LBU_1 -load r1 data -lbu r3, (r1+0) -check_r3 0x7e - -test_name LBU_2 -load r1 data -lbu r3, (r1+1) -check_r3 0x7f - -test_name LBU_3 -load r1 data -lbu r3, (r1+-1) -check_r3 0x7d - -test_name LBU_4 -load r1 data_msb -lbu r3, (r1+0) -check_r3 0xfe - -test_name LBU_5 -load r1 data_msb -lbu r3, (r1+1) -check_r3 0xff - -test_name LBU_6 -load r1 data_msb -lbu r3, (r1+-1) -check_r3 0xfd - -test_name LBU_7 -load r3 data -lbu r3, (r3+0) -check_r3 0x7e - -end - -.data - .align 4 - .byte 0x7a, 0x7b, 0x7c, 0x7d -data: - .byte 0x7e, 0x7f, 0x70, 0x71 - .byte 0xfa, 0xfb, 0xfc, 0xfd -data_msb: - .byte 0xfe, 0xff, 0xf0, 0xf1 diff --git a/tests/tcg/lm32/test_lh.S b/tests/tcg/lm32/test_lh.S deleted file mode 100644 index 397996bddd..0000000000 --- a/tests/tcg/lm32/test_lh.S +++ /dev/null @@ -1,49 +0,0 @@ -.include "macros.inc" - -start - -test_name LH_1 -load r1 data -lh r3, (r1+0) -check_r3 0x7e7f - -test_name LH_2 -load r1 data -lh r3, (r1+2) -check_r3 0x7071 - -test_name LH_3 -load r1 data -lh r3, (r1+-2) -check_r3 0x7c7d - -test_name LH_4 -load r1 data_msb -lh r3, (r1+0) -check_r3 0xfffffeff - -test_name LH_5 -load r1 data_msb -lh r3, (r1+2) -check_r3 0xfffff0f1 - -test_name LH_6 -load r1 data_msb -lh r3, (r1+-2) -check_r3 0xfffffcfd - -test_name LH_7 -load r3 data -lh r3, (r3+0) -check_r3 0x7e7f - -end - -.data - .align 4 - .byte 0x7a, 0x7b, 0x7c, 0x7d -data: - .byte 0x7e, 0x7f, 0x70, 0x71 - .byte 0xfa, 0xfb, 0xfc, 0xfd -data_msb: - .byte 0xfe, 0xff, 0xf0, 0xf1 diff --git a/tests/tcg/lm32/test_lhu.S b/tests/tcg/lm32/test_lhu.S deleted file mode 100644 index 8de7c52560..0000000000 --- a/tests/tcg/lm32/test_lhu.S +++ /dev/null @@ -1,49 +0,0 @@ -.include "macros.inc" - -start - -test_name LHU_1 -load r1 data -lhu r3, (r1+0) -check_r3 0x7e7f - -test_name LHU_2 -load r1 data -lhu r3, (r1+2) -check_r3 0x7071 - -test_name LHU_3 -load r1 data -lhu r3, (r1+-2) -check_r3 0x7c7d - -test_name LHU_4 -load r1 data_msb -lhu r3, (r1+0) -check_r3 0xfeff - -test_name LHU_5 -load r1 data_msb -lhu r3, (r1+2) -check_r3 0xf0f1 - -test_name LHU_6 -load r1 data_msb -lhu r3, (r1+-2) -check_r3 0xfcfd - -test_name LHU_7 -load r3 data -lhu r3, (r3+0) -check_r3 0x7e7f - -end - -.data - .align 4 - .byte 0x7a, 0x7b, 0x7c, 0x7d -data: - .byte 0x7e, 0x7f, 0x70, 0x71 - .byte 0xfa, 0xfb, 0xfc, 0xfd -data_msb: - .byte 0xfe, 0xff, 0xf0, 0xf1 diff --git a/tests/tcg/lm32/test_lw.S b/tests/tcg/lm32/test_lw.S deleted file mode 100644 index 996e5f8c88..0000000000 --- a/tests/tcg/lm32/test_lw.S +++ /dev/null @@ -1,32 +0,0 @@ -.include "macros.inc" - -start - -test_name LW_1 -load r1 data -lw r3, (r1+0) -check_r3 0x7e7f7071 - -test_name LW_2 -load r1 data -lw r3, (r1+4) -check_r3 0x72737475 - -test_name LW_3 -load r1 data -lw r3, (r1+-4) -check_r3 0x7a7b7c7d - -test_name LW_4 -load r3 data -lw r3, (r3+0) -check_r3 0x7e7f7071 - -end - -.data - .align 4 - .byte 0x7a, 0x7b, 0x7c, 0x7d -data: - .byte 0x7e, 0x7f, 0x70, 0x71 - .byte 0x72, 0x73, 0x74, 0x75 diff --git a/tests/tcg/lm32/test_modu.S b/tests/tcg/lm32/test_modu.S deleted file mode 100644 index 42486900b4..0000000000 --- a/tests/tcg/lm32/test_modu.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name MODU_1 -mvi r1, 0 -mvi r2, 1 -modu r3, r1, r2 -check_r3 0 - -test_name MODU_2 -mvi r1, 1 -mvi r2, 1 -modu r3, r1, r2 -check_r3 0 - -test_name MODU_3 -mvi r1, 3 -mvi r2, 2 -modu r3, r1, r2 -check_r3 1 - -test_name MODU_4 -mvi r1, 0 -mvi r2, 0 -modu r3, r1, r2 -check_excp 16 - -test_name MODU_5 -load r1 0xabcdef12 -load r2 0x12345 -modu r3, r1, r2 -check_r3 0x3c12 - -end diff --git a/tests/tcg/lm32/test_mul.S b/tests/tcg/lm32/test_mul.S deleted file mode 100644 index e9b937e648..0000000000 --- a/tests/tcg/lm32/test_mul.S +++ /dev/null @@ -1,70 +0,0 @@ -.include "macros.inc" - -start - -test_name MUL_1 -mvi r1, 0 -mvi r2, 0 -mul r3, r1, r2 -check_r3 0 - -test_name MUL_2 -mvi r1, 1 -mvi r2, 0 -mul r3, r1, r2 -check_r3 0 - -test_name MUL_3 -mvi r1, 0 -mvi r2, 1 -mul r3, r1, r2 -check_r3 0 - -test_name MUL_4 -mvi r1, 1 -mvi r2, 1 -mul r3, r1, r2 -check_r3 1 - -test_name MUL_5 -mvi r1, 2 -mvi r2, -1 -mul r3, r1, r2 -check_r3 -2 - -test_name MUL_6 -mvi r1, -2 -mvi r2, -1 -mul r3, r1, r2 -check_r3 2 - -test_name MUL_7 -mvi r1, 0x1234 -mvi r2, 0x789 -mul r3, r1, r2 -check_r3 0x8929d4 - -test_name MUL_8 -mvi r3, 4 -mul r3, r3, r3 -check_r3 16 - -test_name MUL_9 -mvi r2, 2 -mvi r3, 4 -mul r3, r3, r2 -check_r3 8 - -test_name MUL_10 -load r1 0x12345678 -load r2 0x7bcdef12 -mul r3, r1, r2 -check_r3 0xa801c70 - -test_name MUL_11 -load r1 0x12345678 -load r2 0xabcdef12 -mul r3, r1, r2 -check_r3 0x8a801c70 - -end diff --git a/tests/tcg/lm32/test_muli.S b/tests/tcg/lm32/test_muli.S deleted file mode 100644 index d6dd4a0f7e..0000000000 --- a/tests/tcg/lm32/test_muli.S +++ /dev/null @@ -1,45 +0,0 @@ -.include "macros.inc" - -start - -test_name MULI_1 -mvi r1, 0 -muli r3, r1, 0 -check_r3 0 - -test_name MULI_2 -mvi r1, 1 -muli r3, r1, 0 -check_r3 0 - -test_name MULI_3 -mvi r1, 0 -muli r3, r1, 1 -check_r3 0 - -test_name MULI_4 -mvi r1, 1 -muli r3, r1, 1 -check_r3 1 - -test_name MULI_5 -mvi r1, 2 -muli r3, r1, -1 -check_r3 -2 - -test_name MULI_6 -mvi r1, -2 -muli r3, r1, -1 -check_r3 2 - -test_name MULI_7 -mvi r1, 0x1234 -muli r3, r1, 0x789 -check_r3 0x8929d4 - -test_name MULI_8 -mvi r3, 4 -muli r3, r3, 4 -check_r3 16 - -end diff --git a/tests/tcg/lm32/test_nor.S b/tests/tcg/lm32/test_nor.S deleted file mode 100644 index 74d7592565..0000000000 --- a/tests/tcg/lm32/test_nor.S +++ /dev/null @@ -1,51 +0,0 @@ -.include "macros.inc" - -start - -test_name NOR_1 -mvi r1, 0 -mvi r2, 0 -nor r3, r1, r2 -check_r3 0xffffffff - -test_name NOR_2 -mvi r1, 0 -mvi r2, 1 -nor r3, r1, r2 -check_r3 0xfffffffe - -test_name NOR_3 -mvi r1, 1 -mvi r2, 1 -nor r3, r1, r2 -check_r3 0xfffffffe - -test_name NOR_4 -mvi r1, 1 -mvi r2, 0 -nor r3, r1, r2 -check_r3 0xfffffffe - -test_name NOR_5 -load r1 0xaa55aa55 -load r2 0x55aa55aa -nor r3, r1, r2 -check_r3 0 - -test_name NOR_6 -load r1 0xaa550000 -load r2 0x0000aa55 -nor r3, r1, r2 -check_r3 0x55aa55aa - -test_name NOR_7 -load r1 0xaa55aa55 -nor r3, r1, r1 -check_r3 0x55aa55aa - -test_name NOR_8 -load r3 0xaa55aa55 -nor r3, r3, r3 -check_r3 0x55aa55aa - -end diff --git a/tests/tcg/lm32/test_nori.S b/tests/tcg/lm32/test_nori.S deleted file mode 100644 index d00309c73e..0000000000 --- a/tests/tcg/lm32/test_nori.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name NORI_1 -mvi r1, 0 -nori r3, r1, 0 -check_r3 0xffffffff - -test_name NORI_2 -mvi r1, 0 -nori r3, r1, 1 -check_r3 0xfffffffe - -test_name NORI_3 -mvi r1, 1 -nori r3, r1, 1 -check_r3 0xfffffffe - -test_name NORI_4 -mvi r1, 1 -nori r3, r1, 0 -check_r3 0xfffffffe - -test_name NORI_5 -load r1 0xaa55aa55 -nori r3, r1, 0x55aa -check_r3 0x55aa0000 - -test_name NORI_6 -load r3 0xaa55aa55 -nori r3, r3, 0x55aa -check_r3 0x55aa0000 - -end diff --git a/tests/tcg/lm32/test_or.S b/tests/tcg/lm32/test_or.S deleted file mode 100644 index 4ed292330e..0000000000 --- a/tests/tcg/lm32/test_or.S +++ /dev/null @@ -1,51 +0,0 @@ -.include "macros.inc" - -start - -test_name OR_1 -mvi r1, 0 -mvi r2, 0 -or r3, r1, r2 -check_r3 0 - -test_name OR_2 -mvi r1, 0 -mvi r2, 1 -or r3, r1, r2 -check_r3 1 - -test_name OR_3 -mvi r1, 1 -mvi r2, 1 -or r3, r1, r2 -check_r3 1 - -test_name OR_4 -mvi r1, 1 -mvi r2, 0 -or r3, r1, r2 -check_r3 1 - -test_name OR_5 -load r1 0xaa55aa55 -load r2 0x55aa55aa -or r3, r1, r2 -check_r3 0xffffffff - -test_name OR_6 -load r1 0xaa550000 -load r2 0x0000aa55 -or r3, r1, r2 -check_r3 0xaa55aa55 - -test_name OR_7 -load r1 0xaa55aa55 -or r3, r1, r1 -check_r3 0xaa55aa55 - -test_name OR_8 -load r3 0xaa55aa55 -or r3, r3, r3 -check_r3 0xaa55aa55 - -end diff --git a/tests/tcg/lm32/test_orhi.S b/tests/tcg/lm32/test_orhi.S deleted file mode 100644 index 78b7600e03..0000000000 --- a/tests/tcg/lm32/test_orhi.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name ORHI_1 -mvi r1, 0 -orhi r3, r1, 0 -check_r3 0 - -test_name ORHI_2 -mvi r1, 0 -orhi r3, r1, 1 -check_r3 0x00010000 - -test_name ORHI_3 -load r1 0x00010000 -orhi r3, r1, 1 -check_r3 0x00010000 - -test_name ORHI_4 -mvi r1, 1 -orhi r3, r1, 0 -check_r3 1 - -test_name ORHI_5 -load r1 0xaa55aa55 -orhi r3, r1, 0x55aa -check_r3 0xffffaa55 - -test_name ORHI_6 -load r3 0xaa55aa55 -orhi r3, r3, 0x55aa -check_r3 0xffffaa55 - -end diff --git a/tests/tcg/lm32/test_ori.S b/tests/tcg/lm32/test_ori.S deleted file mode 100644 index 3d576cdb8b..0000000000 --- a/tests/tcg/lm32/test_ori.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name ORI_1 -mvi r1, 0 -ori r3, r1, 0 -check_r3 0 - -test_name ORI_2 -mvi r1, 0 -ori r3, r1, 1 -check_r3 1 - -test_name ORI_3 -mvi r1, 1 -ori r3, r1, 1 -check_r3 1 - -test_name ORI_4 -mvi r1, 1 -ori r3, r1, 0 -check_r3 1 - -test_name ORI_5 -load r1 0xaa55aa55 -ori r3, r1, 0x55aa -check_r3 0xaa55ffff - -test_name ORI_6 -load r3 0xaa55aa55 -ori r3, r3, 0x55aa -check_r3 0xaa55ffff - -end diff --git a/tests/tcg/lm32/test_ret.S b/tests/tcg/lm32/test_ret.S deleted file mode 100644 index 320264f148..0000000000 --- a/tests/tcg/lm32/test_ret.S +++ /dev/null @@ -1,14 +0,0 @@ -.include "macros.inc" - -start - -test_name RET_1 -load ra mark -ret - -tc_fail -end - -mark: -tc_pass -end diff --git a/tests/tcg/lm32/test_sb.S b/tests/tcg/lm32/test_sb.S deleted file mode 100644 index b15a89d342..0000000000 --- a/tests/tcg/lm32/test_sb.S +++ /dev/null @@ -1,32 +0,0 @@ -.include "macros.inc" - -start - -test_name SB_1 -load r1 data -load r2 0xf0f1f2aa -sb (r1+0), r2 -check_mem data 0xaa000000 - -test_name SB_2 -load r1 data -load r2 0xf0f1f2bb -sb (r1+1), r2 -check_mem data 0xaabb0000 - -test_name SB_3 -load r1 data -load r2 0xf0f1f2cc -sb (r1+-1), r2 -check_mem data0 0x000000cc - -end - -.data - .align 4 -data0: - .byte 0, 0, 0, 0 -data: - .byte 0, 0, 0, 0 -data1: - .byte 0, 0, 0, 0 diff --git a/tests/tcg/lm32/test_scall.S b/tests/tcg/lm32/test_scall.S deleted file mode 100644 index 46032f841d..0000000000 --- a/tests/tcg/lm32/test_scall.S +++ /dev/null @@ -1,24 +0,0 @@ -.include "macros.inc" - -start - -test_name SCALL_1 -mvi r1, 1 -wcsr IE, r1 -# we are running in a semi hosted environment -# therefore we have to set r8 to some unused system -# call -mvi r8, 0 -insn: -scall -check_excp 64 - -test_name SCALL_2 -mv r3, ea -check_r3 insn - -test_name SCALL_3 -rcsr r3, IE -check_r3 2 - -end diff --git a/tests/tcg/lm32/test_sextb.S b/tests/tcg/lm32/test_sextb.S deleted file mode 100644 index 58db8ee8b9..0000000000 --- a/tests/tcg/lm32/test_sextb.S +++ /dev/null @@ -1,20 +0,0 @@ -.include "macros.inc" - -start - -test_name SEXTB_1 -mvi r1, 0 -sextb r3, r1 -check_r3 0 - -test_name SEXTB_2 -mvi r1, 0x7f -sextb r3, r1 -check_r3 0x0000007f - -test_name SEXTB_3 -mvi r1, 0x80 -sextb r3, r1 -check_r3 0xffffff80 - -end diff --git a/tests/tcg/lm32/test_sexth.S b/tests/tcg/lm32/test_sexth.S deleted file mode 100644 index a059ec3ee6..0000000000 --- a/tests/tcg/lm32/test_sexth.S +++ /dev/null @@ -1,20 +0,0 @@ -.include "macros.inc" - -start - -test_name SEXTH_1 -mvi r1, 0 -sexth r3, r1 -check_r3 0 - -test_name SEXTH_2 -load r1 0x7fff -sexth r3, r1 -check_r3 0x00007fff - -test_name SEXTH_3 -load r1 0x8000 -sexth r3, r1 -check_r3 0xffff8000 - -end diff --git a/tests/tcg/lm32/test_sh.S b/tests/tcg/lm32/test_sh.S deleted file mode 100644 index bba10224f6..0000000000 --- a/tests/tcg/lm32/test_sh.S +++ /dev/null @@ -1,32 +0,0 @@ -.include "macros.inc" - -start - -test_name SH_1 -load r1 data -load r2 0xf0f1aaaa -sh (r1+0), r2 -check_mem data 0xaaaa0000 - -test_name SH_2 -load r1 data -load r2 0xf0f1bbbb -sh (r1+2), r2 -check_mem data 0xaaaabbbb - -test_name SH_3 -load r1 data -load r2 0xf0f1cccc -sh (r1+-2), r2 -check_mem data0 0x0000cccc - -end - -.data - .align 4 -data0: - .byte 0, 0, 0, 0 -data: - .byte 0, 0, 0, 0 -data1: - .byte 0, 0, 0, 0 diff --git a/tests/tcg/lm32/test_sl.S b/tests/tcg/lm32/test_sl.S deleted file mode 100644 index 0aee17fdb8..0000000000 --- a/tests/tcg/lm32/test_sl.S +++ /dev/null @@ -1,45 +0,0 @@ -.include "macros.inc" - -start - -test_name SL_1 -mvi r1, 1 -mvi r2, 0 -sl r3, r1, r2 -check_r3 1 - -test_name SL_2 -mvi r1, 0 -mvi r2, 1 -sl r3, r1, r2 -check_r3 0 - -test_name SL_3 -mvi r1, 1 -mvi r2, 31 -sl r3, r1, r2 -check_r3 0x80000000 - -test_name SL_4 -mvi r1, 16 -mvi r2, 31 -sl r3, r1, r2 -check_r3 0 - -test_name SL_5 -mvi r1, 1 -mvi r2, 34 -sl r3, r1, r2 -check_r3 4 - -test_name SL_6 -mvi r1, 2 -sl r3, r1, r1 -check_r3 8 - -test_name SL_7 -mvi r3, 2 -sl r3, r3, r3 -check_r3 8 - -end diff --git a/tests/tcg/lm32/test_sli.S b/tests/tcg/lm32/test_sli.S deleted file mode 100644 index a421de9014..0000000000 --- a/tests/tcg/lm32/test_sli.S +++ /dev/null @@ -1,30 +0,0 @@ -.include "macros.inc" - -start - -test_name SLI_1 -mvi r1, 1 -sli r3, r1, 0 -check_r3 1 - -test_name SLI_2 -mvi r1, 0 -sli r3, r1, 1 -check_r3 0 - -test_name SLI_3 -mvi r1, 1 -sli r3, r1, 31 -check_r3 0x80000000 - -test_name SLI_4 -mvi r1, 16 -sli r3, r1, 31 -check_r3 0 - -test_name SLI_7 -mvi r3, 2 -sli r3, r3, 2 -check_r3 8 - -end diff --git a/tests/tcg/lm32/test_sr.S b/tests/tcg/lm32/test_sr.S deleted file mode 100644 index 62431a9864..0000000000 --- a/tests/tcg/lm32/test_sr.S +++ /dev/null @@ -1,57 +0,0 @@ -.include "macros.inc" - -start - -test_name SR_1 -mvi r1, 1 -mvi r2, 0 -sr r3, r1, r2 -check_r3 1 - -test_name SR_2 -mvi r1, 0 -mvi r2, 1 -sr r3, r1, r2 -check_r3 0 - -test_name SR_3 -load r1 0x40000000 -mvi r2, 30 -sr r3, r1, r2 -check_r3 1 - -test_name SR_4 -load r1 0x40000000 -mvi r2, 31 -sr r3, r1, r2 -check_r3 0 - -test_name SR_5 -mvi r1, 16 -mvi r2, 34 -sr r3, r1, r2 -check_r3 4 - -test_name SR_6 -mvi r1, 2 -sr r3, r1, r1 -check_r3 0 - -test_name SR_7 -mvi r3, 2 -sr r3, r3, r3 -check_r3 0 - -test_name SR_8 -mvi r1, 0xfffffff0 -mvi r2, 2 -sr r3, r1, r2 -check_r3 0xfffffffc - -test_name SR_9 -mvi r1, 0xfffffff0 -mvi r2, 4 -sr r3, r1, r2 -check_r3 0xffffffff - -end diff --git a/tests/tcg/lm32/test_sri.S b/tests/tcg/lm32/test_sri.S deleted file mode 100644 index c1be907b5b..0000000000 --- a/tests/tcg/lm32/test_sri.S +++ /dev/null @@ -1,40 +0,0 @@ -.include "macros.inc" - -start - -test_name SRI_1 -mvi r1, 1 -sri r3, r1, 0 -check_r3 1 - -test_name SRI_2 -mvi r1, 0 -sri r3, r1, 1 -check_r3 0 - -test_name SRI_3 -load r1 0x40000000 -sri r3, r1, 30 -check_r3 1 - -test_name SRI_4 -load r1 0x40000000 -sri r3, r1, 31 -check_r3 0 - -test_name SRI_5 -mvi r3, 2 -sri r3, r3, 2 -check_r3 0 - -test_name SRI_6 -mvi r1, 0xfffffff0 -sri r3, r1, 2 -check_r3 0xfffffffc - -test_name SRI_7 -mvi r1, 0xfffffff0 -sri r3, r1, 4 -check_r3 0xffffffff - -end diff --git a/tests/tcg/lm32/test_sru.S b/tests/tcg/lm32/test_sru.S deleted file mode 100644 index 2ab0b54c77..0000000000 --- a/tests/tcg/lm32/test_sru.S +++ /dev/null @@ -1,57 +0,0 @@ -.include "macros.inc" - -start - -test_name SRU_1 -mvi r1, 1 -mvi r2, 0 -sru r3, r1, r2 -check_r3 1 - -test_name SRU_2 -mvi r1, 0 -mvi r2, 1 -sru r3, r1, r2 -check_r3 0 - -test_name SRU_3 -load r1 0x40000000 -mvi r2, 30 -sru r3, r1, r2 -check_r3 1 - -test_name SRU_4 -load r1 0x40000000 -mvi r2, 31 -sru r3, r1, r2 -check_r3 0 - -test_name SRU_5 -mvi r1, 16 -mvi r2, 34 -sru r3, r1, r2 -check_r3 4 - -test_name SRU_6 -mvi r1, 2 -sru r3, r1, r1 -check_r3 0 - -test_name SRU_7 -mvi r3, 2 -sru r3, r3, r3 -check_r3 0 - -test_name SRU_8 -mvi r1, 0xfffffff0 -mvi r2, 2 -sru r3, r1, r2 -check_r3 0x3ffffffc - -test_name SRU_9 -mvi r1, 0xfffffff0 -mvi r2, 4 -sru r3, r1, r2 -check_r3 0x0fffffff - -end diff --git a/tests/tcg/lm32/test_srui.S b/tests/tcg/lm32/test_srui.S deleted file mode 100644 index 872c374121..0000000000 --- a/tests/tcg/lm32/test_srui.S +++ /dev/null @@ -1,40 +0,0 @@ -.include "macros.inc" - -start - -test_name SRUI_1 -mvi r1, 1 -srui r3, r1, 0 -check_r3 1 - -test_name SRUI_2 -mvi r1, 0 -srui r3, r1, 1 -check_r3 0 - -test_name SRUI_3 -load r1 0x40000000 -srui r3, r1, 30 -check_r3 1 - -test_name SRUI_4 -load r1 0x40000000 -srui r3, r1, 31 -check_r3 0 - -test_name SRUI_5 -mvi r3, 2 -srui r3, r3, 2 -check_r3 0 - -test_name SRUI_6 -mvi r1, 0xfffffff0 -srui r3, r1, 2 -check_r3 0x3ffffffc - -test_name SRUI_7 -mvi r1, 0xfffffff0 -srui r3, r1, 4 -check_r3 0x0fffffff - -end diff --git a/tests/tcg/lm32/test_sub.S b/tests/tcg/lm32/test_sub.S deleted file mode 100644 index 44b74a9e10..0000000000 --- a/tests/tcg/lm32/test_sub.S +++ /dev/null @@ -1,75 +0,0 @@ -.include "macros.inc" - -start - -test_name SUB_1 -mvi r1, 0 -mvi r2, 0 -sub r3, r1, r2 -check_r3 0 - -test_name SUB_2 -mvi r1, 0 -mvi r2, 1 -sub r3, r1, r2 -check_r3 -1 - -test_name SUB_3 -mvi r1, 1 -mvi r2, 0 -sub r3, r1, r2 -check_r3 1 - -test_name SUB_4 -mvi r1, 1 -mvi r2, -1 -sub r3, r1, r2 -check_r3 2 - -test_name SUB_5 -mvi r1, -1 -mvi r2, 1 -sub r3, r1, r2 -check_r3 -2 - -test_name SUB_6 -mvi r1, -1 -mvi r2, 0 -sub r3, r1, r2 -check_r3 -1 - -test_name SUB_7 -mvi r1, 0 -mvi r2, -1 -sub r3, r1, r2 -check_r3 1 - -test_name SUB_8 -mvi r3, 2 -sub r3, r3, r3 -check_r3 0 - -test_name SUB_9 -mvi r1, 4 -mvi r3, 2 -sub r3, r1, r3 -check_r3 2 - -test_name SUB_10 -mvi r1, 4 -mvi r3, 2 -sub r3, r3, r1 -check_r3 -2 - -test_name SUB_11 -mvi r1, 4 -sub r3, r1, r1 -check_r3 0 - -test_name SUB_12 -load r1 0x12345678 -load r2 0xabcdef97 -sub r3, r1, r2 -check_r3 0x666666e1 - -end diff --git a/tests/tcg/lm32/test_sw.S b/tests/tcg/lm32/test_sw.S deleted file mode 100644 index 2b1c017e7b..0000000000 --- a/tests/tcg/lm32/test_sw.S +++ /dev/null @@ -1,38 +0,0 @@ -.include "macros.inc" - -start - -test_name SW_1 -load r1 data -load r2 0xaabbccdd -sw (r1+0), r2 -check_mem data 0xaabbccdd - -test_name SW_2 -load r1 data -load r2 0x00112233 -sw (r1+4), r2 -check_mem data1 0x00112233 - -test_name SW_3 -load r1 data -load r2 0x44556677 -sw (r1+-4), r2 -check_mem data0 0x44556677 - -test_name SW_4 -load r1 data -sw (r1+0), r1 -lw r3, (r1+0) -check_r3 data - -end - -.data - .align 4 -data0: - .byte 0, 0, 0, 0 -data: - .byte 0, 0, 0, 0 -data1: - .byte 0, 0, 0, 0 diff --git a/tests/tcg/lm32/test_xnor.S b/tests/tcg/lm32/test_xnor.S deleted file mode 100644 index 14a62075f6..0000000000 --- a/tests/tcg/lm32/test_xnor.S +++ /dev/null @@ -1,51 +0,0 @@ -.include "macros.inc" - -start - -test_name XNOR_1 -mvi r1, 0 -mvi r2, 0 -xnor r3, r1, r2 -check_r3 0xffffffff - -test_name XNOR_2 -mvi r1, 0 -mvi r2, 1 -xnor r3, r1, r2 -check_r3 0xfffffffe - -test_name XNOR_3 -mvi r1, 1 -mvi r2, 1 -xnor r3, r1, r2 -check_r3 0xffffffff - -test_name XNOR_4 -mvi r1, 1 -mvi r2, 0 -xnor r3, r1, r2 -check_r3 0xfffffffe - -test_name XNOR_5 -load r1 0xaa55aa55 -load r2 0x55aa55aa -xnor r3, r1, r2 -check_r3 0 - -test_name XNOR_6 -load r1 0xaa550000 -load r2 0x0000aa55 -xnor r3, r1, r2 -check_r3 0x55aa55aa - -test_name XNOR_7 -load r1 0xaa55aa55 -xnor r3, r1, r1 -check_r3 0xffffffff - -test_name XNOR_8 -load r3 0xaa55aa55 -xnor r3, r3, r3 -check_r3 0xffffffff - -end diff --git a/tests/tcg/lm32/test_xnori.S b/tests/tcg/lm32/test_xnori.S deleted file mode 100644 index 9d9c3c6780..0000000000 --- a/tests/tcg/lm32/test_xnori.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name XNORI_1 -mvi r1, 0 -xnori r3, r1, 0 -check_r3 0xffffffff - -test_name XNORI_2 -mvi r1, 0 -xnori r3, r1, 1 -check_r3 0xfffffffe - -test_name XNORI_3 -mvi r1, 1 -xnori r3, r1, 1 -check_r3 0xffffffff - -test_name XNORI_4 -mvi r1, 1 -xnori r3, r1, 0 -check_r3 0xfffffffe - -test_name XNORI_5 -load r1 0xaa55aa55 -xnori r3, r1, 0x5555 -check_r3 0x55aa00ff - -test_name XNORI_6 -load r3 0xaa55aa55 -xnori r3, r3, 0x5555 -check_r3 0x55aa00ff - -end diff --git a/tests/tcg/lm32/test_xor.S b/tests/tcg/lm32/test_xor.S deleted file mode 100644 index 6c6e712bae..0000000000 --- a/tests/tcg/lm32/test_xor.S +++ /dev/null @@ -1,51 +0,0 @@ -.include "macros.inc" - -start - -test_name XOR_1 -mvi r1, 0 -mvi r2, 0 -xor r3, r1, r2 -check_r3 0 - -test_name XOR_2 -mvi r1, 0 -mvi r2, 1 -xor r3, r1, r2 -check_r3 1 - -test_name XOR_3 -mvi r1, 1 -mvi r2, 1 -xor r3, r1, r2 -check_r3 0 - -test_name XOR_4 -mvi r1, 1 -mvi r2, 0 -xor r3, r1, r2 -check_r3 1 - -test_name XOR_5 -load r1 0xaa55aa55 -load r2 0x55aa55aa -xor r3, r1, r2 -check_r3 0xffffffff - -test_name XOR_6 -load r1 0xaa550000 -load r2 0x0000aa55 -xor r3, r1, r2 -check_r3 0xaa55aa55 - -test_name XOR_7 -load r1 0xaa55aa55 -xor r3, r1, r1 -check_r3 0 - -test_name XOR_8 -load r3 0xaa55aa55 -xor r3, r3, r3 -check_r3 0 - -end diff --git a/tests/tcg/lm32/test_xori.S b/tests/tcg/lm32/test_xori.S deleted file mode 100644 index 2051699f12..0000000000 --- a/tests/tcg/lm32/test_xori.S +++ /dev/null @@ -1,35 +0,0 @@ -.include "macros.inc" - -start - -test_name XORI_1 -mvi r1, 0 -xori r3, r1, 0 -check_r3 0 - -test_name XORI_2 -mvi r1, 0 -xori r3, r1, 1 -check_r3 1 - -test_name XORI_3 -mvi r1, 1 -xori r3, r1, 1 -check_r3 0 - -test_name XORI_4 -mvi r1, 1 -xori r3, r1, 0 -check_r3 1 - -test_name XORI_5 -load r1 0xaa55aa55 -xori r3, r1, 0x5555 -check_r3 0xaa55ff00 - -test_name XORI_6 -load r3 0xaa55aa55 -xori r3, r3, 0x5555 -check_r3 0xaa55ff00 - -end diff --git a/tests/unit/test-write-threshold.c b/tests/unit/test-write-threshold.c index fc1c45a2eb..0158e4637a 100644 --- a/tests/unit/test-write-threshold.c +++ b/tests/unit/test-write-threshold.c @@ -7,117 +7,41 @@ */ #include "qemu/osdep.h" -#include "qapi/error.h" #include "block/block_int.h" #include "block/write-threshold.h" -static void test_threshold_not_set_on_init(void) -{ - uint64_t res; - BlockDriverState bs; - memset(&bs, 0, sizeof(bs)); - - g_assert(!bdrv_write_threshold_is_set(&bs)); - - res = bdrv_write_threshold_get(&bs); - g_assert_cmpint(res, ==, 0); -} - -static void test_threshold_set_get(void) -{ - uint64_t threshold = 4 * 1024 * 1024; - uint64_t res; - BlockDriverState bs; - memset(&bs, 0, sizeof(bs)); - - bdrv_write_threshold_set(&bs, threshold); - - g_assert(bdrv_write_threshold_is_set(&bs)); - - res = bdrv_write_threshold_get(&bs); - g_assert_cmpint(res, ==, threshold); -} - -static void test_threshold_multi_set_get(void) -{ - uint64_t threshold1 = 4 * 1024 * 1024; - uint64_t threshold2 = 15 * 1024 * 1024; - uint64_t res; - BlockDriverState bs; - memset(&bs, 0, sizeof(bs)); - - bdrv_write_threshold_set(&bs, threshold1); - bdrv_write_threshold_set(&bs, threshold2); - res = bdrv_write_threshold_get(&bs); - g_assert_cmpint(res, ==, threshold2); -} - static void test_threshold_not_trigger(void) { - uint64_t amount = 0; uint64_t threshold = 4 * 1024 * 1024; BlockDriverState bs; - BdrvTrackedRequest req; memset(&bs, 0, sizeof(bs)); - memset(&req, 0, sizeof(req)); - req.offset = 1024; - req.bytes = 1024; - - bdrv_check_request(req.offset, req.bytes, &error_abort); bdrv_write_threshold_set(&bs, threshold); - amount = bdrv_write_threshold_exceeded(&bs, &req); - g_assert_cmpuint(amount, ==, 0); + bdrv_write_threshold_check_write(&bs, 1024, 1024); + g_assert_cmpuint(bdrv_write_threshold_get(&bs), ==, threshold); } static void test_threshold_trigger(void) { - uint64_t amount = 0; uint64_t threshold = 4 * 1024 * 1024; BlockDriverState bs; - BdrvTrackedRequest req; memset(&bs, 0, sizeof(bs)); - memset(&req, 0, sizeof(req)); - req.offset = (4 * 1024 * 1024) - 1024; - req.bytes = 2 * 1024; - - bdrv_check_request(req.offset, req.bytes, &error_abort); bdrv_write_threshold_set(&bs, threshold); - amount = bdrv_write_threshold_exceeded(&bs, &req); - g_assert_cmpuint(amount, >=, 1024); + bdrv_write_threshold_check_write(&bs, threshold - 1024, 2 * 1024); + g_assert_cmpuint(bdrv_write_threshold_get(&bs), ==, 0); } -typedef struct TestStruct { - const char *name; - void (*func)(void); -} TestStruct; - int main(int argc, char **argv) { - size_t i; - TestStruct tests[] = { - { "/write-threshold/not-set-on-init", - test_threshold_not_set_on_init }, - { "/write-threshold/set-get", - test_threshold_set_get }, - { "/write-threshold/multi-set-get", - test_threshold_multi_set_get }, - { "/write-threshold/not-trigger", - test_threshold_not_trigger }, - { "/write-threshold/trigger", - test_threshold_trigger }, - { NULL, NULL } - }; - g_test_init(&argc, &argv, NULL); - for (i = 0; tests[i].name != NULL; i++) { - g_test_add_func(tests[i].name, tests[i].func); - } + g_test_add_func("/write-threshold/not-trigger", test_threshold_not_trigger); + g_test_add_func("/write-threshold/trigger", test_threshold_trigger); + return g_test_run(); } diff --git a/util/compatfd.c b/util/compatfd.c index 174f394533..a8ec525c6c 100644 --- a/util/compatfd.c +++ b/util/compatfd.c @@ -72,14 +72,10 @@ static int qemu_signalfd_compat(const sigset_t *mask) QemuThread thread; int fds[2]; - info = malloc(sizeof(*info)); - if (info == NULL) { - errno = ENOMEM; - return -1; - } + info = g_malloc(sizeof(*info)); if (pipe(fds) == -1) { - free(info); + g_free(info); return -1; } diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c index 97dfa3fd57..911115b86e 100644 --- a/util/vfio-helpers.c +++ b/util/vfio-helpers.c @@ -459,51 +459,38 @@ fail_container: return ret; } -static void qemu_vfio_ram_block_added(RAMBlockNotifier *n, - void *host, size_t size) +static void qemu_vfio_ram_block_added(RAMBlockNotifier *n, void *host, + size_t size, size_t max_size) { QEMUVFIOState *s = container_of(n, QEMUVFIOState, ram_notifier); - trace_qemu_vfio_ram_block_added(s, host, size); - qemu_vfio_dma_map(s, host, size, false, NULL); + int ret; + + trace_qemu_vfio_ram_block_added(s, host, max_size); + ret = qemu_vfio_dma_map(s, host, max_size, false, NULL); + if (ret) { + error_report("qemu_vfio_dma_map(%p, %zu) failed: %s", host, max_size, + strerror(-ret)); + } } -static void qemu_vfio_ram_block_removed(RAMBlockNotifier *n, - void *host, size_t size) +static void qemu_vfio_ram_block_removed(RAMBlockNotifier *n, void *host, + size_t size, size_t max_size) { QEMUVFIOState *s = container_of(n, QEMUVFIOState, ram_notifier); if (host) { - trace_qemu_vfio_ram_block_removed(s, host, size); + trace_qemu_vfio_ram_block_removed(s, host, max_size); qemu_vfio_dma_unmap(s, host); } } -static int qemu_vfio_init_ramblock(RAMBlock *rb, void *opaque) -{ - void *host_addr = qemu_ram_get_host_addr(rb); - ram_addr_t length = qemu_ram_get_used_length(rb); - int ret; - QEMUVFIOState *s = opaque; - - if (!host_addr) { - return 0; - } - ret = qemu_vfio_dma_map(s, host_addr, length, false, NULL); - if (ret) { - fprintf(stderr, "qemu_vfio_init_ramblock: failed %p %" PRId64 "\n", - host_addr, (uint64_t)length); - } - return 0; -} - static void qemu_vfio_open_common(QEMUVFIOState *s) { qemu_mutex_init(&s->lock); s->ram_notifier.ram_block_added = qemu_vfio_ram_block_added; s->ram_notifier.ram_block_removed = qemu_vfio_ram_block_removed; - ram_block_notifier_add(&s->ram_notifier); s->low_water_mark = QEMU_VFIO_IOVA_MIN; s->high_water_mark = QEMU_VFIO_IOVA_MAX; - qemu_ram_foreach_block(qemu_vfio_init_ramblock, s); + ram_block_notifier_add(&s->ram_notifier); } /** |