diff options
38 files changed, 1380 insertions, 825 deletions
diff --git a/.gitlab-ci.d/edk2.yml b/.gitlab-ci.d/edk2.yml index ba7280605c..aae2f7ad88 100644 --- a/.gitlab-ci.d/edk2.yml +++ b/.gitlab-ci.d/edk2.yml @@ -1,10 +1,22 @@ -docker-edk2: - stage: containers - rules: # Only run this job when the Dockerfile is modified +# All jobs needing docker-edk2 must use the same rules it uses. +.edk2_job_rules: + rules: # Only run this job when ... - changes: + # this file is modified - .gitlab-ci.d/edk2.yml + # or the Dockerfile is modified - .gitlab-ci.d/edk2/Dockerfile + # or roms/edk2/ is modified (submodule updated) + - roms/edk2/* when: always + - if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2' + when: always + - if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2' + when: always + +docker-edk2: + extends: .edk2_job_rules + stage: containers image: docker:19.03.1 services: - docker:19.03.1-dind @@ -24,16 +36,9 @@ docker-edk2: - docker push $IMAGE_TAG build-edk2: + extends: .edk2_job_rules stage: build needs: ['docker-edk2'] - rules: # Only run this job when ... - - changes: # ... roms/edk2/ is modified (submodule updated) - - roms/edk2/* - when: always - - if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2' - when: always - - if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2' - when: always artifacts: paths: # 'artifacts.zip' will contains the following files: - pc-bios/edk2*bz2 diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml index b01f6ec231..96dbd9e310 100644 --- a/.gitlab-ci.d/static_checks.yml +++ b/.gitlab-ci.d/static_checks.yml @@ -43,6 +43,7 @@ check-python-tox: - make -C python check-tox variables: GIT_DEPTH: 1 + QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false needs: job: python-container allow_failure: true diff --git a/MAINTAINERS b/MAINTAINERS index c4439a9488..9100f9a043 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -171,6 +171,7 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/arm/smmu* F: include/hw/arm/smmu* +F: tests/acceptance/smmu.py AVR TCG CPUs M: Michael Rolnik <mrolnik@gmail.com> @@ -2201,7 +2202,6 @@ F: include/hw/southbridge/piix.h Firmware configuration (fw_cfg) M: Philippe Mathieu-Daudé <philmd@redhat.com> -R: Laszlo Ersek <lersek@redhat.com> R: Gerd Hoffmann <kraxel@redhat.com> S: Supported F: docs/specs/fw_cfg.txt @@ -2933,7 +2933,6 @@ F: include/hw/i2c/smbus_slave.h F: include/hw/i2c/smbus_eeprom.h Firmware schema specifications -M: Laszlo Ersek <lersek@redhat.com> M: Philippe Mathieu-Daudé <philmd@redhat.com> R: Daniel P. Berrange <berrange@redhat.com> R: Kashyap Chamarthy <kchamart@redhat.com> @@ -2941,9 +2940,9 @@ S: Maintained F: docs/interop/firmware.json EDK2 Firmware -M: Laszlo Ersek <lersek@redhat.com> M: Philippe Mathieu-Daudé <philmd@redhat.com> S: Supported +F: hw/i386/*ovmf* F: pc-bios/descriptors/??-edk2-*.json F: pc-bios/edk2-* F: roms/Makefile.edk2 diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 4e42392810..8f572255d3 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -904,6 +904,17 @@ name. If one is not given explicitly, it will either be set to ``None``, or, if the test is tagged with one (and only one) ``:avocado: tags=arch:VALUE`` tag, it will be set to ``VALUE``. +cpu +~~~ + +The cpu model that will be set to all QEMUMachine instances created +by the test. + +The ``cpu`` attribute will be set to the test parameter of the same +name. If one is not given explicitly, it will either be set to +``None ``, or, if the test is tagged with one (and only one) +``:avocado: tags=cpu:VALUE`` tag, it will be set to ``VALUE``. + machine ~~~~~~~ @@ -922,6 +933,39 @@ The preserved value of the ``qemu_bin`` parameter or the result of the dynamic probe for a QEMU binary in the current working directory or source tree. +LinuxTest +~~~~~~~~~ + +Besides the attributes present on the ``avocado_qemu.Test`` base +class, the ``avocado_qemu.LinuxTest`` adds the following attributes: + +distro +...... + +The name of the Linux distribution used as the guest image for the +test. The name should match the **Provider** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_version +.............. + +The version of the Linux distribution as the guest image for the +test. The name should match the **Version** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_checksum +............... + +The sha256 hash of the guest image file used for the test. + +If this value is not set in the code or by a test parameter (with the +same name), no validation on the integrity of the image will be +performed. + Parameter reference ------------------- @@ -950,6 +994,12 @@ architecture of a kernel or disk image to boot a VM with. This parameter has a direct relation with the ``arch`` attribute. If not given, it will default to None. +cpu +~~~ + +The cpu model that will be set to all QEMUMachine instances created +by the test. + machine ~~~~~~~ @@ -962,6 +1012,38 @@ qemu_bin The exact QEMU binary to be used on QEMUMachine. +LinuxTest +~~~~~~~~~ + +Besides the parameters present on the ``avocado_qemu.Test`` base +class, the ``avocado_qemu.LinuxTest`` adds the following parameters: + +distro +...... + +The name of the Linux distribution used as the guest image for the +test. The name should match the **Provider** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_version +.............. + +The version of the Linux distribution as the guest image for the +test. The name should match the **Version** column on the list +of images supported by the avocado.utils.vmimage library: + +https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images + +distro_checksum +............... + +The sha256 hash of the guest image file used for the test. + +If this value is not set in the code or by this parameter no +validation on the integrity of the image will be performed. + Skipping tests -------------- The Avocado framework provides Python decorators which allow for easily skip diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index aacb6f6d96..bad6cf5b4e 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -1,5 +1,9 @@ +config X86_FW_OVMF + bool + config SEV bool + select X86_FW_OVMF depends on KVM config PC diff --git a/hw/i386/meson.build b/hw/i386/meson.build index e5d109f5c6..80dad29f2b 100644 --- a/hw/i386/meson.build +++ b/hw/i386/meson.build @@ -24,6 +24,8 @@ i386_ss.add(when: 'CONFIG_PC', if_true: files( 'pc_sysfw.c', 'acpi-build.c', 'port92.c')) +i386_ss.add(when: 'CONFIG_X86_FW_OVMF', if_true: files('pc_sysfw_ovmf.c'), + if_false: files('pc_sysfw_ovmf-stubs.c')) subdir('kvm') subdir('xen') diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 6ce37a2b05..68d6b1f783 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -124,113 +124,6 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms) } } -#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" - -static uint8_t *ovmf_table; -static int ovmf_table_len; - -static void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) -{ - uint8_t *ptr; - QemuUUID guid; - int tot_len; - - /* should only be called once */ - if (ovmf_table) { - return; - } - - if (flash_size < TARGET_PAGE_SIZE) { - return; - } - - /* - * if this is OVMF there will be a table footer - * guid 48 bytes before the end of the flash file. If it's - * not found, silently abort the flash parsing. - */ - qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid); - guid = qemu_uuid_bswap(guid); /* guids are LE */ - ptr = flash_ptr + flash_size - 48; - if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) { - return; - } - - /* if found, just before is two byte table length */ - ptr -= sizeof(uint16_t); - tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t); - - if (tot_len <= 0) { - return; - } - - ovmf_table = g_malloc(tot_len); - ovmf_table_len = tot_len; - - /* - * ptr is the foot of the table, so copy it all to the newly - * allocated ovmf_table and then set the ovmf_table pointer - * to the table foot - */ - memcpy(ovmf_table, ptr - tot_len, tot_len); - ovmf_table += tot_len; -} - -bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, - int *data_len) -{ - uint8_t *ptr = ovmf_table; - int tot_len = ovmf_table_len; - QemuUUID entry_guid; - - if (qemu_uuid_parse(entry, &entry_guid) < 0) { - return false; - } - - if (!ptr) { - return false; - } - - entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */ - while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) { - int len; - QemuUUID *guid; - - /* - * The data structure is - * arbitrary length data - * 2 byte length of entire entry - * 16 byte guid - */ - guid = (QemuUUID *)(ptr - sizeof(QemuUUID)); - len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) - - sizeof(uint16_t))); - - /* - * just in case the table is corrupt, wouldn't want to spin in - * the zero case - */ - if (len < sizeof(QemuUUID) + sizeof(uint16_t)) { - return false; - } else if (len > tot_len) { - return false; - } - - ptr -= len; - tot_len -= len; - if (qemu_uuid_is_equal(guid, &entry_guid)) { - if (data) { - *data = ptr; - } - if (data_len) { - *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t); - } - return true; - } - } - return false; -} - /* * Map the pcms->flash[] from 4GiB downward, and realize. * Map them in descending order, i.e. pcms->flash[0] at the top, diff --git a/hw/i386/pc_sysfw_ovmf-stubs.c b/hw/i386/pc_sysfw_ovmf-stubs.c new file mode 100644 index 0000000000..aabe78b271 --- /dev/null +++ b/hw/i386/pc_sysfw_ovmf-stubs.c @@ -0,0 +1,26 @@ +/* + * QEMU PC System Firmware (OVMF stubs) + * + * Copyright (c) 2021 Red Hat, Inc. + * + * Author: + * Philippe Mathieu-Daudé <philmd@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/i386/pc.h" + +bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len) +{ + g_assert_not_reached(); +} + +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) +{ + g_assert_not_reached(); +} diff --git a/hw/i386/pc_sysfw_ovmf.c b/hw/i386/pc_sysfw_ovmf.c new file mode 100644 index 0000000000..f4dd92c588 --- /dev/null +++ b/hw/i386/pc_sysfw_ovmf.c @@ -0,0 +1,151 @@ +/* + * QEMU PC System Firmware (OVMF specific) + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2011-2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/i386/pc.h" +#include "cpu.h" + +#define OVMF_TABLE_FOOTER_GUID "96b582de-1fb2-45f7-baea-a366c55a082d" + +static bool ovmf_flash_parsed; +static uint8_t *ovmf_table; +static int ovmf_table_len; + +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size) +{ + uint8_t *ptr; + QemuUUID guid; + int tot_len; + + /* should only be called once */ + if (ovmf_flash_parsed) { + return; + } + + ovmf_flash_parsed = true; + + if (flash_size < TARGET_PAGE_SIZE) { + return; + } + + /* + * if this is OVMF there will be a table footer + * guid 48 bytes before the end of the flash file. If it's + * not found, silently abort the flash parsing. + */ + qemu_uuid_parse(OVMF_TABLE_FOOTER_GUID, &guid); + guid = qemu_uuid_bswap(guid); /* guids are LE */ + ptr = flash_ptr + flash_size - 48; + if (!qemu_uuid_is_equal((QemuUUID *)ptr, &guid)) { + return; + } + + /* if found, just before is two byte table length */ + ptr -= sizeof(uint16_t); + tot_len = le16_to_cpu(*(uint16_t *)ptr) - sizeof(guid) - sizeof(uint16_t); + + if (tot_len <= 0) { + return; + } + + ovmf_table = g_malloc(tot_len); + ovmf_table_len = tot_len; + + /* + * ptr is the foot of the table, so copy it all to the newly + * allocated ovmf_table and then set the ovmf_table pointer + * to the table foot + */ + memcpy(ovmf_table, ptr - tot_len, tot_len); + ovmf_table += tot_len; +} + +/** + * pc_system_ovmf_table_find - Find the data associated with an entry in OVMF's + * reset vector GUIDed table. + * + * @entry: GUID string of the entry to lookup + * @data: Filled with a pointer to the entry's value (if not NULL) + * @data_len: Filled with the length of the entry's value (if not NULL). Pass + * NULL here if the length of data is known. + * + * Return: true if the entry was found in the OVMF table; false otherwise. + */ +bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, + int *data_len) +{ + uint8_t *ptr = ovmf_table; + int tot_len = ovmf_table_len; + QemuUUID entry_guid; + + assert(ovmf_flash_parsed); + + if (qemu_uuid_parse(entry, &entry_guid) < 0) { + return false; + } + + if (!ptr) { + return false; + } + + entry_guid = qemu_uuid_bswap(entry_guid); /* guids are LE */ + while (tot_len >= sizeof(QemuUUID) + sizeof(uint16_t)) { + int len; + QemuUUID *guid; + + /* + * The data structure is + * arbitrary length data + * 2 byte length of entire entry + * 16 byte guid + */ + guid = (QemuUUID *)(ptr - sizeof(QemuUUID)); + len = le16_to_cpu(*(uint16_t *)(ptr - sizeof(QemuUUID) - + sizeof(uint16_t))); + + /* + * just in case the table is corrupt, wouldn't want to spin in + * the zero case + */ + if (len < sizeof(QemuUUID) + sizeof(uint16_t)) { + return false; + } else if (len > tot_len) { + return false; + } + + ptr -= len; + tot_len -= len; + if (qemu_uuid_is_equal(guid, &entry_guid)) { + if (data) { + *data = ptr; + } + if (data_len) { + *data_len = len - sizeof(QemuUUID) - sizeof(uint16_t); + } + return true; + } + } + return false; +} diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 87294f2632..0775f945d7 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -188,6 +188,7 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms); void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory); bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len); +void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size); /* acpi-build.c */ diff --git a/python/Makefile b/python/Makefile index ac46ae33e7..fe27a3e12e 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,4 +1,5 @@ QEMU_VENV_DIR=.dev-venv +QEMU_TOX_EXTRA_ARGS ?= .PHONY: help help: @@ -15,6 +16,8 @@ help: @echo " These tests use the newest dependencies." @echo " Requires: Python 3.6 - 3.10, and tox." @echo " Hint (Fedora): 'sudo dnf install python3-tox python3.10'" + @echo " The variable QEMU_TOX_EXTRA_ARGS can be use to pass extra" + @echo " arguments to tox". @echo "" @echo "make check-dev:" @echo " Run tests in a venv against your default python3 version." @@ -87,7 +90,7 @@ check: .PHONY: check-tox check-tox: - @tox + @tox $(QEMU_TOX_EXTRA_ARGS) .PHONY: clean clean: diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index d47ab3d896..971ed7e8c6 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -96,7 +96,8 @@ class QEMUMachine: socket_scm_helper: Optional[str] = None, sock_dir: Optional[str] = None, drain_console: bool = False, - console_log: Optional[str] = None): + console_log: Optional[str] = None, + log_dir: Optional[str] = None): ''' Initialize a QEMUMachine @@ -110,6 +111,7 @@ class QEMUMachine: @param sock_dir: where to create socket (defaults to base_temp_dir) @param drain_console: (optional) True to drain console socket to buffer @param console_log: (optional) path to console log file + @param log_dir: where to create and keep log files @note: Qemu process is not started until launch() is used. ''' # pylint: disable=too-many-arguments @@ -123,6 +125,7 @@ class QEMUMachine: self._name = name or "qemu-%d" % os.getpid() self._base_temp_dir = base_temp_dir self._sock_dir = sock_dir or self._base_temp_dir + self._log_dir = log_dir self._socket_scm_helper = socket_scm_helper if monitor_address is not None: @@ -313,9 +316,12 @@ class QEMUMachine: args.extend(['-device', device]) return args - def _pre_launch(self) -> None: - self._qemu_log_path = os.path.join(self.temp_dir, self._name + ".log") + @property + def args(self) -> List[str]: + """Returns the list of arguments given to the QEMU binary.""" + return self._args + def _pre_launch(self) -> None: if self._console_set: self._remove_files.append(self._console_address) @@ -332,6 +338,7 @@ class QEMUMachine: # NOTE: Make sure any opened resources are *definitely* freed in # _post_shutdown()! # pylint: disable=consider-using-with + self._qemu_log_path = os.path.join(self.log_dir, self._name + ".log") self._qemu_log_file = open(self._qemu_log_path, 'wb') def _post_launch(self) -> None: @@ -770,3 +777,12 @@ class QEMUMachine: self._temp_dir = tempfile.mkdtemp(prefix="qemu-machine-", dir=self._base_temp_dir) return self._temp_dir + + @property + def log_dir(self) -> str: + """ + Returns a directory to be used for writing logs + """ + if self._log_dir is None: + return self.temp_dir + return self._log_dir diff --git a/python/setup.cfg b/python/setup.cfg index 11f71d5312..14bab90288 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -121,6 +121,7 @@ multi_line_output=3 [tox:tox] envlist = py36, py37, py38, py39, py310 +skip_missing_interpreters = true [testenv] allowlist_externals = make diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 27baf17d6c..a099acb34d 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2166,9 +2166,10 @@ typedef struct _ga_win_10_0_server_t { char const *version_id; } ga_win_10_0_server_t; -static ga_win_10_0_server_t const WIN_10_0_SERVER_VERSION_MATRIX[3] = { +static ga_win_10_0_server_t const WIN_10_0_SERVER_VERSION_MATRIX[4] = { {14393, "Microsoft Windows Server 2016", "2016"}, {17763, "Microsoft Windows Server 2019", "2019"}, + {20344, "Microsoft Windows Server 2022", "2022"}, {0, 0} }; diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 833d3baa7b..103c6326a2 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -66,8 +66,6 @@ struct DisasContext { /* Temporaries for $31 and $f31 as source and destination. */ TCGv zero; TCGv sink; - /* Temporary for immediate constants. */ - TCGv lit; }; /* Target-specific return values from translate_one, indicating the @@ -157,7 +155,7 @@ void alpha_translate_init(void) static TCGv load_zero(DisasContext *ctx) { if (!ctx->zero) { - ctx->zero = tcg_const_i64(0); + ctx->zero = tcg_constant_i64(0); } return ctx->zero; } @@ -177,14 +175,6 @@ static void free_context_temps(DisasContext *ctx) tcg_temp_free(ctx->sink); ctx->sink = NULL; } - if (ctx->zero) { - tcg_temp_free(ctx->zero); - ctx->zero = NULL; - } - if (ctx->lit) { - tcg_temp_free(ctx->lit); - ctx->lit = NULL; - } } static TCGv load_gpr(DisasContext *ctx, unsigned reg) @@ -200,8 +190,7 @@ static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg, uint8_t lit, bool islit) { if (islit) { - ctx->lit = tcg_const_i64(lit); - return ctx->lit; + return tcg_constant_i64(lit); } else if (likely(reg < 31)) { return ctx->ir[reg]; } else { @@ -261,11 +250,9 @@ static void gen_excp_1(int exception, int error_code) { TCGv_i32 tmp1, tmp2; - tmp1 = tcg_const_i32(exception); - tmp2 = tcg_const_i32(error_code); + tmp1 = tcg_constant_i32(exception); + tmp2 = tcg_constant_i32(error_code); gen_helper_excp(cpu_env, tmp1, tmp2); - tcg_temp_free_i32(tmp2); - tcg_temp_free_i32(tmp1); } static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code) @@ -485,15 +472,11 @@ static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond, return DISAS_NORETURN; } else { - TCGv_i64 z = tcg_const_i64(0); - TCGv_i64 d = tcg_const_i64(dest); - TCGv_i64 p = tcg_const_i64(ctx->base.pc_next); + TCGv_i64 z = load_zero(ctx); + TCGv_i64 d = tcg_constant_i64(dest); + TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next); tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p); - - tcg_temp_free_i64(z); - tcg_temp_free_i64(d); - tcg_temp_free_i64(p); return DISAS_PC_UPDATED; } } @@ -695,22 +678,19 @@ static void gen_fp_exc_raise(int rc, int fn11) if (!(fn11 & QUAL_I)) { ignore |= FPCR_INE; } - ign = tcg_const_i32(ignore); + ign = tcg_constant_i32(ignore); /* ??? Pass in the regno of the destination so that the helper can set EXC_MASK, which contains a bitmask of destination registers that have caused arithmetic traps. A simple userspace emulation does not require this. We do need it for a guest kernel's entArith, or if we were to do something clever with imprecise exceptions. */ - reg = tcg_const_i32(rc + 32); + reg = tcg_constant_i32(rc + 32); if (fn11 & QUAL_S) { gen_helper_fp_exc_raise_s(cpu_env, ign, reg); } else { gen_helper_fp_exc_raise(cpu_env, ign, reg); } - - tcg_temp_free_i32(reg); - tcg_temp_free_i32(ign); } static void gen_cvtlq(TCGv vc, TCGv vb) @@ -803,7 +783,7 @@ IEEE_INTCVT(cvtqt) static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask) { - TCGv vmask = tcg_const_i64(mask); + TCGv vmask = tcg_constant_i64(mask); TCGv tmp = tcg_temp_new_i64(); if (inv_a) { @@ -815,7 +795,6 @@ static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask) tcg_gen_andc_i64(vc, vb, vmask); tcg_gen_or_i64(vc, vc, tmp); - tcg_temp_free(vmask); tcg_temp_free(tmp); } @@ -1084,15 +1063,11 @@ static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit, static void gen_rx(DisasContext *ctx, int ra, int set) { - TCGv tmp; - if (ra != 31) { ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT); } - tmp = tcg_const_i64(set); - st_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT); - tcg_temp_free(tmp); + st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT); } static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode) @@ -1193,12 +1168,9 @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode) case 0x3E: /* WTINT */ - { - TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) + - offsetof(CPUState, halted)); - tcg_temp_free_i32(tmp); - } + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + -offsetof(AlphaCPU, env) + + offsetof(CPUState, halted)); tcg_gen_movi_i64(ctx->ir[IR_V0], 0); return gen_excp(ctx, EXCP_HALTED, 0); @@ -1349,12 +1321,8 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno) case 253: /* WAIT */ - { - TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) + - offsetof(CPUState, halted)); - tcg_temp_free_i32(tmp); - } + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + -offsetof(AlphaCPU, env) + offsetof(CPUState, halted)); return gen_excp(ctx, EXCP_HALTED, 0); case 252: @@ -2721,15 +2689,14 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return address from EXC_ADDR. This turns out to be useful for our emulation PALcode, so continue to accept it. */ - ctx->lit = vb = tcg_temp_new(); + vb = dest_sink(ctx); tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr)); } else { vb = load_gpr(ctx, rb); } tcg_gen_movi_i64(cpu_lock_addr, -1); + st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT); tmp = tcg_temp_new(); - tcg_gen_movi_i64(tmp, 0); - st_flag_byte(tmp, ENV_FLAG_RX_SHIFT); tcg_gen_andi_i64(tmp, vb, 1); st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT); tcg_temp_free(tmp); @@ -2996,7 +2963,6 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) ctx->zero = NULL; ctx->sink = NULL; - ctx->lit = NULL; /* Bound the number of insns to execute to those left on the page. */ bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 835120c038..2552747138 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -144,6 +144,7 @@ #define tcg_gen_sextract_reg tcg_gen_sextract_i64 #define tcg_const_reg tcg_const_i64 #define tcg_const_local_reg tcg_const_local_i64 +#define tcg_constant_reg tcg_constant_i64 #define tcg_gen_movcond_reg tcg_gen_movcond_i64 #define tcg_gen_add2_reg tcg_gen_add2_i64 #define tcg_gen_sub2_reg tcg_gen_sub2_i64 @@ -238,6 +239,7 @@ #define tcg_gen_sextract_reg tcg_gen_sextract_i32 #define tcg_const_reg tcg_const_i32 #define tcg_const_local_reg tcg_const_local_i32 +#define tcg_constant_reg tcg_constant_i32 #define tcg_gen_movcond_reg tcg_gen_movcond_i32 #define tcg_gen_add2_reg tcg_gen_add2_i32 #define tcg_gen_sub2_reg tcg_gen_sub2_i32 @@ -250,8 +252,6 @@ typedef struct DisasCond { TCGCond c; TCGv_reg a0, a1; - bool a0_is_n; - bool a1_is_0; } DisasCond; typedef struct DisasContext { @@ -446,9 +446,7 @@ static DisasCond cond_make_n(void) return (DisasCond){ .c = TCG_COND_NE, .a0 = cpu_psw_n, - .a0_is_n = true, - .a1 = NULL, - .a1_is_0 = true + .a1 = tcg_constant_reg(0) }; } @@ -456,7 +454,7 @@ static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0) { assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); return (DisasCond){ - .c = c, .a0 = a0, .a1_is_0 = true + .c = c, .a0 = a0, .a1 = tcg_constant_reg(0) }; } @@ -480,26 +478,14 @@ static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1) return r; } -static void cond_prep(DisasCond *cond) -{ - if (cond->a1_is_0) { - cond->a1_is_0 = false; - cond->a1 = tcg_const_reg(0); - } -} - static void cond_free(DisasCond *cond) { switch (cond->c) { default: - if (!cond->a0_is_n) { + if (cond->a0 != cpu_psw_n) { tcg_temp_free(cond->a0); } - if (!cond->a1_is_0) { - tcg_temp_free(cond->a1); - } - cond->a0_is_n = false; - cond->a1_is_0 = false; + tcg_temp_free(cond->a1); cond->a0 = NULL; cond->a1 = NULL; /* fallthru */ @@ -557,9 +543,8 @@ static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg) static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t) { if (ctx->null_cond.c != TCG_COND_NEVER) { - cond_prep(&ctx->null_cond); tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0, - ctx->null_cond.a1, dest, t); + ctx->null_cond.a1, dest, t); } else { tcg_gen_mov_reg(dest, t); } @@ -666,11 +651,9 @@ static void nullify_over(DisasContext *ctx) assert(ctx->null_cond.c != TCG_COND_ALWAYS); ctx->null_lab = gen_new_label(); - cond_prep(&ctx->null_cond); /* If we're using PSW[N], copy it to a temp because... */ - if (ctx->null_cond.a0_is_n) { - ctx->null_cond.a0_is_n = false; + if (ctx->null_cond.a0 == cpu_psw_n) { ctx->null_cond.a0 = tcg_temp_new(); tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n); } @@ -683,7 +666,7 @@ static void nullify_over(DisasContext *ctx) } tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0, - ctx->null_cond.a1, ctx->null_lab); + ctx->null_cond.a1, ctx->null_lab); cond_free(&ctx->null_cond); } } @@ -697,10 +680,9 @@ static void nullify_save(DisasContext *ctx) } return; } - if (!ctx->null_cond.a0_is_n) { - cond_prep(&ctx->null_cond); + if (ctx->null_cond.a0 != cpu_psw_n) { tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n, - ctx->null_cond.a0, ctx->null_cond.a1); + ctx->null_cond.a0, ctx->null_cond.a1); ctx->psw_n_nonzero = true; } cond_free(&ctx->null_cond); @@ -771,9 +753,7 @@ static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp) static void gen_excp_1(int exception) { - TCGv_i32 t = tcg_const_i32(exception); - gen_helper_excp(cpu_env, t); - tcg_temp_free_i32(t); + gen_helper_excp(cpu_env, tcg_constant_i32(exception)); } static void gen_excp(DisasContext *ctx, int exception) @@ -787,12 +767,9 @@ static void gen_excp(DisasContext *ctx, int exception) static bool gen_excp_iir(DisasContext *ctx, int exc) { - TCGv_reg tmp; - nullify_over(ctx); - tmp = tcg_const_reg(ctx->insn); - tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR])); - tcg_temp_free(tmp); + tcg_gen_st_reg(tcg_constant_reg(ctx->insn), + cpu_env, offsetof(CPUHPPAState, cr[CR_IIR])); gen_excp(ctx, exc); return nullify_end(ctx); } @@ -1150,13 +1127,12 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1, } if (!is_l || cond_need_cb(c)) { - TCGv_reg zero = tcg_const_reg(0); + TCGv_reg zero = tcg_constant_reg(0); cb_msb = get_temp(ctx); tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero); if (is_c) { tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero); } - tcg_temp_free(zero); if (!is_l) { cb = get_temp(ctx); tcg_gen_xor_reg(cb, in1, in2); @@ -1182,7 +1158,6 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1, /* Emit any conditional trap before any writeback. */ cond = do_cond(cf, dest, cb_msb, sv); if (is_tc) { - cond_prep(&cond); tmp = tcg_temp_new(); tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); @@ -1242,7 +1217,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, cb = tcg_temp_new(); cb_msb = tcg_temp_new(); - zero = tcg_const_reg(0); + zero = tcg_constant_reg(0); if (is_b) { /* DEST,C = IN1 + ~IN2 + C. */ tcg_gen_not_reg(cb, in2); @@ -1258,7 +1233,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, tcg_gen_eqv_reg(cb, in1, in2); tcg_gen_xor_reg(cb, cb, dest); } - tcg_temp_free(zero); /* Compute signed overflow if required. */ sv = NULL; @@ -1278,7 +1252,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, /* Emit any conditional trap before any writeback. */ if (is_tc) { - cond_prep(&cond); tmp = tcg_temp_new(); tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); @@ -1404,7 +1377,6 @@ static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, if (is_tc) { TCGv_reg tmp = tcg_temp_new(); - cond_prep(&cond); tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); tcg_temp_free(tmp); @@ -1860,7 +1832,6 @@ static bool do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n, } taken = gen_new_label(); - cond_prep(cond); tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken); cond_free(cond); @@ -1957,7 +1928,6 @@ static bool do_ibranch(DisasContext *ctx, TCGv_reg dest, tcg_gen_lookup_and_goto_ptr(); return nullify_end(ctx); } else { - cond_prep(&ctx->null_cond); c = ctx->null_cond.c; a0 = ctx->null_cond.a0; a1 = ctx->null_cond.a1; @@ -2449,17 +2419,16 @@ static bool trans_probe(DisasContext *ctx, arg_probe *a) form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false); if (a->imm) { - level = tcg_const_i32(a->ri); + level = tcg_constant_i32(a->ri); } else { level = tcg_temp_new_i32(); tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri)); tcg_gen_andi_i32(level, level, 3); } - want = tcg_const_i32(a->write ? PAGE_WRITE : PAGE_READ); + want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ); gen_helper_probe(dest, cpu_env, addr, level, want); - tcg_temp_free_i32(want); tcg_temp_free_i32(level); save_gpr(ctx, a->t, dest); @@ -2599,17 +2568,13 @@ static bool trans_lpa(DisasContext *ctx, arg_ldst *a) static bool trans_lci(DisasContext *ctx, arg_lci *a) { - TCGv_reg ci; - CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); /* The Coherence Index is an implementation-defined function of the physical address. Two addresses with the same CI have a coherent view of the cache. Our implementation is to return 0 for all, since the entire address space is coherent. */ - ci = tcg_const_reg(0); - save_gpr(ctx, a->t, ci); - tcg_temp_free(ci); + save_gpr(ctx, a->t, tcg_constant_reg(0)); cond_free(&ctx->null_cond); return true; @@ -2710,8 +2675,6 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a) * currently implemented as idle. */ if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */ - TCGv_i32 tmp; - /* No need to check for supervisor, as userland can only pause until the next timer interrupt. */ nullify_over(ctx); @@ -2722,10 +2685,8 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a) nullify_set(ctx, 0); /* Tell the qemu main loop to halt until this cpu has work. */ - tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) + - offsetof(CPUState, halted)); - tcg_temp_free_i32(tmp); + tcg_gen_st_i32(tcg_constant_i32(1), cpu_env, + offsetof(CPUState, halted) - offsetof(HPPACPU, env)); gen_excp_1(EXCP_HALTED); ctx->base.is_jmp = DISAS_NORETURN; @@ -2833,7 +2794,7 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a) add2 = tcg_temp_new(); addc = tcg_temp_new(); dest = tcg_temp_new(); - zero = tcg_const_reg(0); + zero = tcg_constant_reg(0); /* Form R1 << 1 | PSW[CB]{8}. */ tcg_gen_add_reg(add1, in1, in1); @@ -2851,7 +2812,6 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a) tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero); tcg_temp_free(addc); - tcg_temp_free(zero); /* Write back the result register. */ save_gpr(ctx, a->t, dest); @@ -2967,9 +2927,8 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a) */ gen_helper_ldc_check(addr); - zero = tcg_const_reg(0); + zero = tcg_constant_reg(0); tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop); - tcg_temp_free(zero); if (a->m) { save_gpr(ctx, a->b, ofs); @@ -3882,15 +3841,13 @@ static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a) ta = load_frw0_i32(a->r1); tb = load_frw0_i32(a->r2); - ty = tcg_const_i32(a->y); - tc = tcg_const_i32(a->c); + ty = tcg_constant_i32(a->y); + tc = tcg_constant_i32(a->c); gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc); tcg_temp_free_i32(ta); tcg_temp_free_i32(tb); - tcg_temp_free_i32(ty); - tcg_temp_free_i32(tc); return nullify_end(ctx); } @@ -3904,15 +3861,13 @@ static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a) ta = load_frd0(a->r1); tb = load_frd0(a->r2); - ty = tcg_const_i32(a->y); - tc = tcg_const_i32(a->c); + ty = tcg_constant_i32(a->y); + tc = tcg_constant_i32(a->c); gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc); tcg_temp_free_i64(ta); tcg_temp_free_i64(tb); - tcg_temp_free_i32(ty); - tcg_temp_free_i32(tc); return nullify_end(ctx); } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 950a991a71..5d98a4e7c0 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1437,6 +1437,8 @@ typedef struct CPUX86State { FPReg fpregs[8]; /* KVM-only so far */ uint16_t fpop; + uint16_t fpcs; + uint16_t fpds; uint64_t fpip; uint64_t fpdp; diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index 74bbe94b80..cdd8e9f947 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -727,10 +727,14 @@ void helper_fwait(CPUX86State *env) } } -void helper_fninit(CPUX86State *env) +static void do_fninit(CPUX86State *env) { env->fpus = 0; env->fpstt = 0; + env->fpcs = 0; + env->fpds = 0; + env->fpip = 0; + env->fpdp = 0; cpu_set_fpuc(env, 0x37f); env->fptags[0] = 1; env->fptags[1] = 1; @@ -742,6 +746,11 @@ void helper_fninit(CPUX86State *env) env->fptags[7] = 1; } +void helper_fninit(CPUX86State *env) +{ + do_fninit(env); +} + /* BCD ops */ void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) @@ -2373,19 +2382,19 @@ static void do_fstenv(CPUX86State *env, target_ulong ptr, int data32, cpu_stl_data_ra(env, ptr, env->fpuc, retaddr); cpu_stl_data_ra(env, ptr + 4, fpus, retaddr); cpu_stl_data_ra(env, ptr + 8, fptag, retaddr); - cpu_stl_data_ra(env, ptr + 12, 0, retaddr); /* fpip */ - cpu_stl_data_ra(env, ptr + 16, 0, retaddr); /* fpcs */ - cpu_stl_data_ra(env, ptr + 20, 0, retaddr); /* fpoo */ - cpu_stl_data_ra(env, ptr + 24, 0, retaddr); /* fpos */ + cpu_stl_data_ra(env, ptr + 12, env->fpip, retaddr); /* fpip */ + cpu_stl_data_ra(env, ptr + 16, env->fpcs, retaddr); /* fpcs */ + cpu_stl_data_ra(env, ptr + 20, env->fpdp, retaddr); /* fpoo */ + cpu_stl_data_ra(env, ptr + 24, env->fpds, retaddr); /* fpos */ } else { /* 16 bit */ cpu_stw_data_ra(env, ptr, env->fpuc, retaddr); cpu_stw_data_ra(env, ptr + 2, fpus, retaddr); cpu_stw_data_ra(env, ptr + 4, fptag, retaddr); - cpu_stw_data_ra(env, ptr + 6, 0, retaddr); - cpu_stw_data_ra(env, ptr + 8, 0, retaddr); - cpu_stw_data_ra(env, ptr + 10, 0, retaddr); - cpu_stw_data_ra(env, ptr + 12, 0, retaddr); + cpu_stw_data_ra(env, ptr + 6, env->fpip, retaddr); + cpu_stw_data_ra(env, ptr + 8, env->fpcs, retaddr); + cpu_stw_data_ra(env, ptr + 10, env->fpdp, retaddr); + cpu_stw_data_ra(env, ptr + 12, env->fpds, retaddr); } } @@ -2451,18 +2460,7 @@ static void do_fsave(CPUX86State *env, target_ulong ptr, int data32, ptr += 10; } - /* fninit */ - env->fpus = 0; - env->fpstt = 0; - cpu_set_fpuc(env, 0x37f); - env->fptags[0] = 1; - env->fptags[1] = 1; - env->fptags[2] = 1; - env->fptags[3] = 1; - env->fptags[4] = 1; - env->fptags[5] = 1; - env->fptags[6] = 1; - env->fptags[7] = 1; + do_fninit(env); } void helper_fsave(CPUX86State *env, target_ulong ptr, int data32) @@ -2834,7 +2832,7 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm) if (xstate_bv & XSTATE_FP_MASK) { do_xrstor_fpu(env, ptr, ra); } else { - helper_fninit(env); + do_fninit(env); memset(env->fpregs, 0, sizeof(env->fpregs)); } } diff --git a/target/i386/tcg/sysemu/bpt_helper.c b/target/i386/tcg/sysemu/bpt_helper.c index 624f90b789..4d96a48a3c 100644 --- a/target/i386/tcg/sysemu/bpt_helper.c +++ b/target/i386/tcg/sysemu/bpt_helper.c @@ -109,9 +109,9 @@ static void hw_breakpoint_remove(CPUX86State *env, int index) case DR7_TYPE_DATA_WR: case DR7_TYPE_DATA_RW: - if (env->cpu_breakpoint[index]) { + if (env->cpu_watchpoint[index]) { cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]); - env->cpu_breakpoint[index] = NULL; + env->cpu_watchpoint[index] = NULL; } break; diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 3814ce2a3e..8520d5a1e2 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -5919,503 +5919,555 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /************************/ /* floats */ case 0xd8 ... 0xdf: - if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { - /* if CR0.EM or CR0.TS are set, generate an FPU exception */ - /* XXX: what to do if illegal op ? */ - gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); - break; - } - modrm = x86_ldub_code(env, s); - mod = (modrm >> 6) & 3; - rm = modrm & 7; - op = ((b & 7) << 3) | ((modrm >> 3) & 7); - if (mod != 3) { - /* memory op */ - gen_lea_modrm(env, s, modrm); - switch(op) { - case 0x00 ... 0x07: /* fxxxs */ - case 0x10 ... 0x17: /* fixxxl */ - case 0x20 ... 0x27: /* fxxxl */ - case 0x30 ... 0x37: /* fixxx */ - { - int op1; - op1 = op & 7; + { + bool update_fip = true; + + if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { + /* if CR0.EM or CR0.TS are set, generate an FPU exception */ + /* XXX: what to do if illegal op ? */ + gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); + break; + } + modrm = x86_ldub_code(env, s); + mod = (modrm >> 6) & 3; + rm = modrm & 7; + op = ((b & 7) << 3) | ((modrm >> 3) & 7); + if (mod != 3) { + /* memory op */ + AddressParts a = gen_lea_modrm_0(env, s, modrm); + TCGv ea = gen_lea_modrm_1(s, a); + TCGv last_addr = tcg_temp_new(); + bool update_fdp = true; + + tcg_gen_mov_tl(last_addr, ea); + gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override); + + switch (op) { + case 0x00 ... 0x07: /* fxxxs */ + case 0x10 ... 0x17: /* fixxxl */ + case 0x20 ... 0x27: /* fxxxl */ + case 0x30 ... 0x37: /* fixxx */ + { + int op1; + op1 = op & 7; + + switch (op >> 4) { + case 0: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_flds_FT0(cpu_env, s->tmp2_i32); + break; + case 1: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); + break; + case 2: + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fldl_FT0(cpu_env, s->tmp1_i64); + break; + case 3: + default: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LESW); + gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); + break; + } - switch(op >> 4) { + gen_helper_fp_arith_ST0_FT0(op1); + if (op1 == 3) { + /* fcomp needs pop */ + gen_helper_fpop(cpu_env); + } + } + break; + case 0x08: /* flds */ + case 0x0a: /* fsts */ + case 0x0b: /* fstps */ + case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ + case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ + case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ + switch (op & 7) { case 0: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_flds_FT0(cpu_env, s->tmp2_i32); + switch (op >> 4) { + case 0: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_flds_ST0(cpu_env, s->tmp2_i32); + break; + case 1: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + break; + case 2: + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fldl_ST0(cpu_env, s->tmp1_i64); + break; + case 3: + default: + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LESW); + gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + break; + } break; case 1: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); - break; - case 2: - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); - gen_helper_fldl_FT0(cpu_env, s->tmp1_i64); + /* XXX: the corresponding CPUID bit must be tested ! */ + switch (op >> 4) { + case 1: + gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 2: + gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + break; + case 3: + default: + gen_helper_fistt_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + break; + } + gen_helper_fpop(cpu_env); break; - case 3: default: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LESW); - gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); + switch (op >> 4) { + case 0: + gen_helper_fsts_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 1: + gen_helper_fistl_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUL); + break; + case 2: + gen_helper_fstl_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + break; + case 3: + default: + gen_helper_fist_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + break; + } + if ((op & 7) == 3) { + gen_helper_fpop(cpu_env); + } break; } + break; + case 0x0c: /* fldenv mem */ + gen_helper_fldenv(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x0d: /* fldcw mem */ + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + gen_helper_fldcw(cpu_env, s->tmp2_i32); + update_fip = update_fdp = false; + break; + case 0x0e: /* fnstenv mem */ + gen_helper_fstenv(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x0f: /* fnstcw mem */ + gen_helper_fnstcw(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + update_fip = update_fdp = false; + break; + case 0x1d: /* fldt mem */ + gen_helper_fldt_ST0(cpu_env, s->A0); + break; + case 0x1f: /* fstpt mem */ + gen_helper_fstt_ST0(cpu_env, s->A0); + gen_helper_fpop(cpu_env); + break; + case 0x2c: /* frstor mem */ + gen_helper_frstor(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x2e: /* fnsave mem */ + gen_helper_fsave(cpu_env, s->A0, + tcg_const_i32(dflag - 1)); + update_fip = update_fdp = false; + break; + case 0x2f: /* fnstsw mem */ + gen_helper_fnstsw(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, + s->mem_index, MO_LEUW); + update_fip = update_fdp = false; + break; + case 0x3c: /* fbld */ + gen_helper_fbld_ST0(cpu_env, s->A0); + break; + case 0x3e: /* fbstp */ + gen_helper_fbst_ST0(cpu_env, s->A0); + gen_helper_fpop(cpu_env); + break; + case 0x3d: /* fildll */ + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fildll_ST0(cpu_env, s->tmp1_i64); + break; + case 0x3f: /* fistpll */ + gen_helper_fistll_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, + s->mem_index, MO_LEQ); + gen_helper_fpop(cpu_env); + break; + default: + goto unknown_op; + } - gen_helper_fp_arith_ST0_FT0(op1); - if (op1 == 3) { - /* fcomp needs pop */ - gen_helper_fpop(cpu_env); - } + if (update_fdp) { + int last_seg = s->override >= 0 ? s->override : a.def_seg; + + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, + segs[last_seg].selector)); + tcg_gen_st16_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, fpds)); + tcg_gen_st_tl(last_addr, cpu_env, + offsetof(CPUX86State, fpdp)); } - break; - case 0x08: /* flds */ - case 0x0a: /* fsts */ - case 0x0b: /* fstps */ - case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */ - case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */ - case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */ - switch(op & 7) { - case 0: - switch(op >> 4) { - case 0: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_flds_ST0(cpu_env, s->tmp2_i32); + tcg_temp_free(last_addr); + } else { + /* register float ops */ + opreg = rm; + + switch (op) { + case 0x08: /* fld sti */ + gen_helper_fpush(cpu_env); + gen_helper_fmov_ST0_STN(cpu_env, + tcg_const_i32((opreg + 1) & 7)); + break; + case 0x09: /* fxchg sti */ + case 0x29: /* fxchg4 sti, undocumented op */ + case 0x39: /* fxchg7 sti, undocumented op */ + gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg)); + break; + case 0x0a: /* grp d9/2 */ + switch (rm) { + case 0: /* fnop */ + /* check exceptions (FreeBSD FPU probe) */ + gen_helper_fwait(cpu_env); + update_fip = false; break; - case 1: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); - gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + default: + goto unknown_op; + } + break; + case 0x0c: /* grp d9/4 */ + switch (rm) { + case 0: /* fchs */ + gen_helper_fchs_ST0(cpu_env); break; - case 2: - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); - gen_helper_fldl_ST0(cpu_env, s->tmp1_i64); + case 1: /* fabs */ + gen_helper_fabs_ST0(cpu_env); break; - case 3: - default: - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LESW); - gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); + case 4: /* ftst */ + gen_helper_fldz_FT0(cpu_env); + gen_helper_fcom_ST0_FT0(cpu_env); break; + case 5: /* fxam */ + gen_helper_fxam_ST0(cpu_env); + break; + default: + goto unknown_op; } break; - case 1: - /* XXX: the corresponding CPUID bit must be tested ! */ - switch(op >> 4) { - case 1: - gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); + case 0x0d: /* grp d9/5 */ + { + switch (rm) { + case 0: + gen_helper_fpush(cpu_env); + gen_helper_fld1_ST0(cpu_env); + break; + case 1: + gen_helper_fpush(cpu_env); + gen_helper_fldl2t_ST0(cpu_env); + break; + case 2: + gen_helper_fpush(cpu_env); + gen_helper_fldl2e_ST0(cpu_env); + break; + case 3: + gen_helper_fpush(cpu_env); + gen_helper_fldpi_ST0(cpu_env); + break; + case 4: + gen_helper_fpush(cpu_env); + gen_helper_fldlg2_ST0(cpu_env); + break; + case 5: + gen_helper_fpush(cpu_env); + gen_helper_fldln2_ST0(cpu_env); + break; + case 6: + gen_helper_fpush(cpu_env); + gen_helper_fldz_ST0(cpu_env); + break; + default: + goto unknown_op; + } + } + break; + case 0x0e: /* grp d9/6 */ + switch (rm) { + case 0: /* f2xm1 */ + gen_helper_f2xm1(cpu_env); break; - case 2: - gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + case 1: /* fyl2x */ + gen_helper_fyl2x(cpu_env); + break; + case 2: /* fptan */ + gen_helper_fptan(cpu_env); + break; + case 3: /* fpatan */ + gen_helper_fpatan(cpu_env); + break; + case 4: /* fxtract */ + gen_helper_fxtract(cpu_env); + break; + case 5: /* fprem1 */ + gen_helper_fprem1(cpu_env); + break; + case 6: /* fdecstp */ + gen_helper_fdecstp(cpu_env); break; - case 3: default: - gen_helper_fistt_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); + case 7: /* fincstp */ + gen_helper_fincstp(cpu_env); break; } - gen_helper_fpop(cpu_env); break; - default: - switch(op >> 4) { - case 0: - gen_helper_fsts_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); + case 0x0f: /* grp d9/7 */ + switch (rm) { + case 0: /* fprem */ + gen_helper_fprem(cpu_env); break; - case 1: - gen_helper_fistl_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUL); + case 1: /* fyl2xp1 */ + gen_helper_fyl2xp1(cpu_env); break; - case 2: - gen_helper_fstl_ST0(s->tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + case 2: /* fsqrt */ + gen_helper_fsqrt(cpu_env); + break; + case 3: /* fsincos */ + gen_helper_fsincos(cpu_env); + break; + case 5: /* fscale */ + gen_helper_fscale(cpu_env); + break; + case 4: /* frndint */ + gen_helper_frndint(cpu_env); + break; + case 6: /* fsin */ + gen_helper_fsin(cpu_env); break; - case 3: default: - gen_helper_fist_ST0(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); + case 7: /* fcos */ + gen_helper_fcos(cpu_env); break; } - if ((op & 7) == 3) - gen_helper_fpop(cpu_env); - break; - } - break; - case 0x0c: /* fldenv mem */ - gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x0d: /* fldcw mem */ - tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - gen_helper_fldcw(cpu_env, s->tmp2_i32); - break; - case 0x0e: /* fnstenv mem */ - gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x0f: /* fnstcw mem */ - gen_helper_fnstcw(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - break; - case 0x1d: /* fldt mem */ - gen_helper_fldt_ST0(cpu_env, s->A0); - break; - case 0x1f: /* fstpt mem */ - gen_helper_fstt_ST0(cpu_env, s->A0); - gen_helper_fpop(cpu_env); - break; - case 0x2c: /* frstor mem */ - gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x2e: /* fnsave mem */ - gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1)); - break; - case 0x2f: /* fnstsw mem */ - gen_helper_fnstsw(s->tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, - s->mem_index, MO_LEUW); - break; - case 0x3c: /* fbld */ - gen_helper_fbld_ST0(cpu_env, s->A0); - break; - case 0x3e: /* fbstp */ - gen_helper_fbst_ST0(cpu_env, s->A0); - gen_helper_fpop(cpu_env); - break; - case 0x3d: /* fildll */ - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); - gen_helper_fildll_ST0(cpu_env, s->tmp1_i64); - break; - case 0x3f: /* fistpll */ - gen_helper_fistll_ST0(s->tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); - gen_helper_fpop(cpu_env); - break; - default: - goto unknown_op; - } - } else { - /* register float ops */ - opreg = rm; - - switch(op) { - case 0x08: /* fld sti */ - gen_helper_fpush(cpu_env); - gen_helper_fmov_ST0_STN(cpu_env, - tcg_const_i32((opreg + 1) & 7)); - break; - case 0x09: /* fxchg sti */ - case 0x29: /* fxchg4 sti, undocumented op */ - case 0x39: /* fxchg7 sti, undocumented op */ - gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg)); - break; - case 0x0a: /* grp d9/2 */ - switch(rm) { - case 0: /* fnop */ - /* check exceptions (FreeBSD FPU probe) */ - gen_helper_fwait(cpu_env); - break; - default: - goto unknown_op; - } - break; - case 0x0c: /* grp d9/4 */ - switch(rm) { - case 0: /* fchs */ - gen_helper_fchs_ST0(cpu_env); break; - case 1: /* fabs */ - gen_helper_fabs_ST0(cpu_env); + case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ + case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ + case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ + { + int op1; + + op1 = op & 7; + if (op >= 0x20) { + gen_helper_fp_arith_STN_ST0(op1, opreg); + if (op >= 0x30) { + gen_helper_fpop(cpu_env); + } + } else { + gen_helper_fmov_FT0_STN(cpu_env, + tcg_const_i32(opreg)); + gen_helper_fp_arith_ST0_FT0(op1); + } + } break; - case 4: /* ftst */ - gen_helper_fldz_FT0(cpu_env); + case 0x02: /* fcom */ + case 0x22: /* fcom2, undocumented op */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fcom_ST0_FT0(cpu_env); break; - case 5: /* fxam */ - gen_helper_fxam_ST0(cpu_env); + case 0x03: /* fcomp */ + case 0x23: /* fcomp3, undocumented op */ + case 0x32: /* fcomp5, undocumented op */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); break; - default: - goto unknown_op; - } - break; - case 0x0d: /* grp d9/5 */ - { - switch(rm) { - case 0: - gen_helper_fpush(cpu_env); - gen_helper_fld1_ST0(cpu_env); - break; - case 1: - gen_helper_fpush(cpu_env); - gen_helper_fldl2t_ST0(cpu_env); + case 0x15: /* da/5 */ + switch (rm) { + case 1: /* fucompp */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + gen_helper_fucom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); + gen_helper_fpop(cpu_env); break; - case 2: - gen_helper_fpush(cpu_env); - gen_helper_fldl2e_ST0(cpu_env); + default: + goto unknown_op; + } + break; + case 0x1c: + switch (rm) { + case 0: /* feni (287 only, just do nop here) */ break; - case 3: - gen_helper_fpush(cpu_env); - gen_helper_fldpi_ST0(cpu_env); + case 1: /* fdisi (287 only, just do nop here) */ break; - case 4: - gen_helper_fpush(cpu_env); - gen_helper_fldlg2_ST0(cpu_env); + case 2: /* fclex */ + gen_helper_fclex(cpu_env); + update_fip = false; break; - case 5: - gen_helper_fpush(cpu_env); - gen_helper_fldln2_ST0(cpu_env); + case 3: /* fninit */ + gen_helper_fninit(cpu_env); + update_fip = false; break; - case 6: - gen_helper_fpush(cpu_env); - gen_helper_fldz_ST0(cpu_env); + case 4: /* fsetpm (287 only, just do nop here) */ break; default: goto unknown_op; } - } - break; - case 0x0e: /* grp d9/6 */ - switch(rm) { - case 0: /* f2xm1 */ - gen_helper_f2xm1(cpu_env); - break; - case 1: /* fyl2x */ - gen_helper_fyl2x(cpu_env); - break; - case 2: /* fptan */ - gen_helper_fptan(cpu_env); - break; - case 3: /* fpatan */ - gen_helper_fpatan(cpu_env); - break; - case 4: /* fxtract */ - gen_helper_fxtract(cpu_env); - break; - case 5: /* fprem1 */ - gen_helper_fprem1(cpu_env); - break; - case 6: /* fdecstp */ - gen_helper_fdecstp(cpu_env); break; - default: - case 7: /* fincstp */ - gen_helper_fincstp(cpu_env); - break; - } - break; - case 0x0f: /* grp d9/7 */ - switch(rm) { - case 0: /* fprem */ - gen_helper_fprem(cpu_env); - break; - case 1: /* fyl2xp1 */ - gen_helper_fyl2xp1(cpu_env); - break; - case 2: /* fsqrt */ - gen_helper_fsqrt(cpu_env); + case 0x1d: /* fucomi */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucomi_ST0_FT0(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); break; - case 3: /* fsincos */ - gen_helper_fsincos(cpu_env); + case 0x1e: /* fcomi */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcomi_ST0_FT0(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); break; - case 5: /* fscale */ - gen_helper_fscale(cpu_env); + case 0x28: /* ffree sti */ + gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); break; - case 4: /* frndint */ - gen_helper_frndint(cpu_env); + case 0x2a: /* fst sti */ + gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); break; - case 6: /* fsin */ - gen_helper_fsin(cpu_env); + case 0x2b: /* fstp sti */ + case 0x0b: /* fstp1 sti, undocumented op */ + case 0x3a: /* fstp8 sti, undocumented op */ + case 0x3b: /* fstp9 sti, undocumented op */ + gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); + gen_helper_fpop(cpu_env); break; - default: - case 7: /* fcos */ - gen_helper_fcos(cpu_env); + case 0x2c: /* fucom st(i) */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucom_ST0_FT0(cpu_env); break; - } - break; - case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ - case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ - case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ - { - int op1; - - op1 = op & 7; - if (op >= 0x20) { - gen_helper_fp_arith_STN_ST0(op1, opreg); - if (op >= 0x30) - gen_helper_fpop(cpu_env); - } else { - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fp_arith_ST0_FT0(op1); - } - } - break; - case 0x02: /* fcom */ - case 0x22: /* fcom2, undocumented op */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcom_ST0_FT0(cpu_env); - break; - case 0x03: /* fcomp */ - case 0x23: /* fcomp3, undocumented op */ - case 0x32: /* fcomp5, undocumented op */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcom_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - break; - case 0x15: /* da/5 */ - switch(rm) { - case 1: /* fucompp */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + case 0x2d: /* fucomp st(i) */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); gen_helper_fucom_ST0_FT0(cpu_env); gen_helper_fpop(cpu_env); - gen_helper_fpop(cpu_env); break; - default: - goto unknown_op; - } - break; - case 0x1c: - switch(rm) { - case 0: /* feni (287 only, just do nop here) */ - break; - case 1: /* fdisi (287 only, just do nop here) */ - break; - case 2: /* fclex */ - gen_helper_fclex(cpu_env); + case 0x33: /* de/3 */ + switch (rm) { + case 1: /* fcompp */ + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); + gen_helper_fcom_ST0_FT0(cpu_env); + gen_helper_fpop(cpu_env); + gen_helper_fpop(cpu_env); + break; + default: + goto unknown_op; + } break; - case 3: /* fninit */ - gen_helper_fninit(cpu_env); + case 0x38: /* ffreep sti, undocumented op */ + gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fpop(cpu_env); break; - case 4: /* fsetpm (287 only, just do nop here) */ + case 0x3c: /* df/4 */ + switch (rm) { + case 0: + gen_helper_fnstsw(s->tmp2_i32, cpu_env); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + break; + default: + goto unknown_op; + } break; - default: - goto unknown_op; - } - break; - case 0x1d: /* fucomi */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucomi_ST0_FT0(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x1e: /* fcomi */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcomi_ST0_FT0(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x28: /* ffree sti */ - gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); - break; - case 0x2a: /* fst sti */ - gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); - break; - case 0x2b: /* fstp sti */ - case 0x0b: /* fstp1 sti, undocumented op */ - case 0x3a: /* fstp8 sti, undocumented op */ - case 0x3b: /* fstp9 sti, undocumented op */ - gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg)); - gen_helper_fpop(cpu_env); - break; - case 0x2c: /* fucom st(i) */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucom_ST0_FT0(cpu_env); - break; - case 0x2d: /* fucomp st(i) */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucom_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - break; - case 0x33: /* de/3 */ - switch(rm) { - case 1: /* fcompp */ - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1)); - gen_helper_fcom_ST0_FT0(cpu_env); + case 0x3d: /* fucomip */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fucomi_ST0_FT0(cpu_env); gen_helper_fpop(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); + break; + case 0x3e: /* fcomip */ + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + gen_update_cc_op(s); + gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); + gen_helper_fcomi_ST0_FT0(cpu_env); gen_helper_fpop(cpu_env); + set_cc_op(s, CC_OP_EFLAGS); break; - default: - goto unknown_op; - } - break; - case 0x38: /* ffreep sti, undocumented op */ - gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fpop(cpu_env); - break; - case 0x3c: /* df/4 */ - switch(rm) { - case 0: - gen_helper_fnstsw(s->tmp2_i32, cpu_env); - tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); - gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + case 0x10 ... 0x13: /* fcmovxx */ + case 0x18 ... 0x1b: + { + int op1; + TCGLabel *l1; + static const uint8_t fcmov_cc[8] = { + (JCC_B << 1), + (JCC_Z << 1), + (JCC_BE << 1), + (JCC_P << 1), + }; + + if (!(s->cpuid_features & CPUID_CMOV)) { + goto illegal_op; + } + op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); + l1 = gen_new_label(); + gen_jcc1_noeob(s, op1, l1); + gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg)); + gen_set_label(l1); + } break; default: goto unknown_op; } - break; - case 0x3d: /* fucomip */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fucomi_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x3e: /* fcomip */ - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - gen_update_cc_op(s); - gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg)); - gen_helper_fcomi_ST0_FT0(cpu_env); - gen_helper_fpop(cpu_env); - set_cc_op(s, CC_OP_EFLAGS); - break; - case 0x10 ... 0x13: /* fcmovxx */ - case 0x18 ... 0x1b: - { - int op1; - TCGLabel *l1; - static const uint8_t fcmov_cc[8] = { - (JCC_B << 1), - (JCC_Z << 1), - (JCC_BE << 1), - (JCC_P << 1), - }; + } - if (!(s->cpuid_features & CPUID_CMOV)) { - goto illegal_op; - } - op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1); - l1 = gen_new_label(); - gen_jcc1_noeob(s, op1, l1); - gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg)); - gen_set_label(l1); - } - break; - default: - goto unknown_op; + if (update_fip) { + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, segs[R_CS].selector)); + tcg_gen_st16_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, fpcs)); + tcg_gen_st_tl(tcg_constant_tl(pc_start - s->cs_base), + cpu_env, offsetof(CPUX86State, fpip)); } } break; diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 37c3e3e0a3..059da48475 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -52,6 +52,8 @@ typedef struct DisasContext { /* The temporary corresponding to register 0 for this compilation. */ TCGv R0; + /* The constant zero. */ + TCGv zero; } DisasContext; static inline bool is_user(DisasContext *dc) @@ -129,9 +131,7 @@ void openrisc_translate_init(void) static void gen_exception(DisasContext *dc, unsigned int excp) { - TCGv_i32 tmp = tcg_const_i32(excp); - gen_helper_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); + gen_helper_exception(cpu_env, tcg_constant_i32(excp)); } static void gen_illegal_exception(DisasContext *dc) @@ -199,10 +199,10 @@ static void gen_ove_cyov(DisasContext *dc) static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv t0 = tcg_const_tl(0); + TCGv t0 = tcg_temp_new(); TCGv res = tcg_temp_new(); - tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0); + tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero); tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); tcg_gen_xor_tl(t0, res, srcb); tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); @@ -216,11 +216,11 @@ static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb) { - TCGv t0 = tcg_const_tl(0); + TCGv t0 = tcg_temp_new(); TCGv res = tcg_temp_new(); - tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0); - tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0); + tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero); + tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero); tcg_gen_xor_tl(cpu_sr_ov, srca, srcb); tcg_gen_xor_tl(t0, res, srcb); tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov); @@ -538,13 +538,9 @@ static bool trans_l_extbz(DisasContext *dc, arg_da *a) static bool trans_l_cmov(DisasContext *dc, arg_dab *a) { - TCGv zero; - check_r0_write(dc, a->d); - zero = tcg_const_tl(0); - tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero, + tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero, cpu_R(dc, a->a), cpu_R(dc, a->b)); - tcg_temp_free(zero); return true; } @@ -632,15 +628,10 @@ static bool trans_l_jal(DisasContext *dc, arg_l_jal *a) static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) { target_ulong tmp_pc = dc->base.pc_next + a->n * 4; - TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); - TCGv t_true = tcg_const_tl(tmp_pc); - TCGv t_zero = tcg_const_tl(0); - - tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); + TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8); + TCGv t_true = tcg_constant_tl(tmp_pc); - tcg_temp_free(t_next); - tcg_temp_free(t_true); - tcg_temp_free(t_zero); + tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next); dc->delayed_branch = 2; } @@ -740,12 +731,6 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a) ea = tcg_temp_new(); tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i); - /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned - to cpu_regs[0]. Since l.swa is quite often immediately followed by a - branch, don't bother reallocating; finish the TB using the "real" R0. - This also takes care of RB input across the branch. */ - dc->R0 = cpu_regs[0]; - lab_fail = gen_new_label(); lab_done = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail); @@ -753,7 +738,7 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a) val = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, - cpu_regs[a->b], dc->mem_idx, MO_TEUL); + cpu_R(dc, a->b), dc->mem_idx, MO_TEUL); tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); tcg_temp_free(val); @@ -813,44 +798,28 @@ static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a) static bool trans_l_addi(DisasContext *dc, arg_rri *a) { - TCGv t0; - check_r0_write(dc, a->d); - t0 = tcg_const_tl(a->i); - gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } static bool trans_l_addic(DisasContext *dc, arg_rri *a) { - TCGv t0; - check_r0_write(dc, a->d); - t0 = tcg_const_tl(a->i); - gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } static bool trans_l_muli(DisasContext *dc, arg_rri *a) { - TCGv t0; - check_r0_write(dc, a->d); - t0 = tcg_const_tl(a->i); - gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } static bool trans_l_maci(DisasContext *dc, arg_l_maci *a) { - TCGv t0; - - t0 = tcg_const_tl(a->i); - gen_mac(dc, cpu_R(dc, a->a), t0); - tcg_temp_free(t0); + gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i)); return true; } @@ -1624,8 +1593,9 @@ static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) /* Allow the TCG optimizer to see that R0 == 0, when it's true, which is the common case. */ + dc->zero = tcg_constant_tl(0); if (dc->tb_flags & TB_FLAGS_R0_0) { - dc->R0 = tcg_const_tl(0); + dc->R0 = dc->zero; } else { dc->R0 = cpu_regs[0]; } diff --git a/tests/Makefile.include b/tests/Makefile.include index e4dcb17329..6e16c05f10 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -96,7 +96,7 @@ AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS))) $(TESTS_VENV_DIR): $(TESTS_VENV_REQ) $(call quiet-command, \ - $(PYTHON) -m venv --system-site-packages $@, \ + $(PYTHON) -m venv $@, \ VENV, $@) $(call quiet-command, \ $(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \ diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index 93c4b9851f..2c4fef3e14 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -86,14 +86,17 @@ def _console_interaction(test, success_message, failure_message, assert not keep_sending or send_string if vm is None: vm = test.vm - console = vm.console_socket.makefile() + console = vm.console_socket.makefile(mode='rb', encoding='utf-8') console_logger = logging.getLogger('console') while True: if send_string: vm.console_socket.sendall(send_string.encode()) if not keep_sending: send_string = None # send only once - msg = console.readline().strip() + try: + msg = console.readline().decode().strip() + except UnicodeDecodeError: + msg = None if not msg: continue console_logger.debug(msg) @@ -210,6 +213,9 @@ class Test(avocado.Test): self.arch = self.params.get('arch', default=self._get_unique_tag_val('arch')) + self.cpu = self.params.get('cpu', + default=self._get_unique_tag_val('cpu')) + self.machine = self.params.get('machine', default=self._get_unique_tag_val('machine')) @@ -219,9 +225,13 @@ class Test(avocado.Test): if self.qemu_bin is None: self.cancel("No QEMU binary defined or found in the build tree") - def _new_vm(self, *args): + def _new_vm(self, name, *args): self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") - vm = QEMUMachine(self.qemu_bin, sock_dir=self._sd.name) + vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, + sock_dir=self._sd.name, log_dir=self.logdir) + self.log.debug('QEMUMachine "%s" created', name) + self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir) + self.log.debug('QEMUMachine "%s" log_dir: %s', name, vm.log_dir) if args: vm.add_args(*args) return vm @@ -234,11 +244,34 @@ class Test(avocado.Test): if not name: name = str(uuid.uuid4()) if self._vms.get(name) is None: - self._vms[name] = self._new_vm(*args) + self._vms[name] = self._new_vm(name, *args) + if self.cpu is not None: + self._vms[name].add_args('-cpu', self.cpu) if self.machine is not None: self._vms[name].set_machine(self.machine) return self._vms[name] + def set_vm_arg(self, arg, value): + """ + Set an argument to list of extra arguments to be given to the QEMU + binary. If the argument already exists then its value is replaced. + + :param arg: the QEMU argument, such as "-cpu" in "-cpu host" + :type arg: str + :param value: the argument value, such as "host" in "-cpu host" + :type value: str + """ + if not arg or not value: + return + if arg not in self.vm.args: + self.vm.args.extend([arg, value]) + else: + idx = self.vm.args.index(arg) + 1 + if idx < len(self.vm.args): + self.vm.args[idx] = value + else: + self.vm.args.append(value) + def tearDown(self): for vm in self._vms.values(): vm.shutdown() @@ -299,6 +332,103 @@ class LinuxSSHMixIn: f'Guest command failed: {command}') return stdout_lines, stderr_lines +class LinuxDistro: + """Represents a Linux distribution + + Holds information of known distros. + """ + #: A collection of known distros and their respective image checksum + KNOWN_DISTROS = { + 'fedora': { + '31': { + 'x86_64': + {'checksum': ('e3c1b309d9203604922d6e255c2c5d09' + '8a309c2d46215d8fc026954f3c5c27a0'), + 'pxeboot_url': ('https://archives.fedoraproject.org/' + 'pub/archive/fedora/linux/releases/31/' + 'Everything/x86_64/os/images/pxeboot/'), + 'kernel_params': ('root=UUID=b1438b9b-2cab-4065-a99a-' + '08a96687f73c ro no_timer_check ' + 'net.ifnames=0 console=tty1 ' + 'console=ttyS0,115200n8'), + }, + 'aarch64': + {'checksum': ('1e18d9c0cf734940c4b5d5ec592facae' + 'd2af0ad0329383d5639c997fdf16fe49'), + 'pxeboot_url': 'https://archives.fedoraproject.org/' + 'pub/archive/fedora/linux/releases/31/' + 'Everything/aarch64/os/images/pxeboot/', + 'kernel_params': ('root=UUID=b6950a44-9f3c-4076-a9c2-' + '355e8475b0a7 ro earlyprintk=pl011,0x9000000' + ' ignore_loglevel no_timer_check' + ' printk.time=1 rd_NO_PLYMOUTH' + ' console=ttyAMA0'), + }, + 'ppc64': + {'checksum': ('7c3528b85a3df4b2306e892199a9e1e4' + '3f991c506f2cc390dc4efa2026ad2f58')}, + 's390x': + {'checksum': ('4caaab5a434fd4d1079149a072fdc789' + '1e354f834d355069ca982fdcaf5a122d')}, + }, + '32': { + 'aarch64': + {'checksum': ('b367755c664a2d7a26955bbfff985855' + 'adfa2ca15e908baf15b4b176d68d3967'), + 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' + 'releases/32/Server/aarch64/os/images/' + 'pxeboot/'), + 'kernel_params': ('root=UUID=3df75b65-be8d-4db4-8655-' + '14d95c0e90c5 ro no_timer_check net.ifnames=0' + ' console=tty1 console=ttyS0,115200n8'), + }, + }, + '33': { + 'aarch64': + {'checksum': ('e7f75cdfd523fe5ac2ca9eeece68edc1' + 'a81f386a17f969c1d1c7c87031008a6b'), + 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' + 'releases/33/Server/aarch64/os/images/' + 'pxeboot/'), + 'kernel_params': ('root=UUID=d20b3ffa-6397-4a63-a734-' + '1126a0208f8a ro no_timer_check net.ifnames=0' + ' console=tty1 console=ttyS0,115200n8' + ' console=tty0'), + }, + }, + } + } + + def __init__(self, name, version, arch): + self.name = name + self.version = version + self.arch = arch + try: + info = self.KNOWN_DISTROS.get(name).get(version).get(arch) + except AttributeError: + # Unknown distro + info = None + self._info = info or {} + + @property + def checksum(self): + """Gets the cloud-image file checksum""" + return self._info.get('checksum', None) + + @checksum.setter + def checksum(self, value): + self._info['checksum'] = value + + @property + def pxeboot_url(self): + """Gets the repository url where pxeboot files can be found""" + return self._info.get('pxeboot_url', None) + + @property + def default_kernel_params(self): + """Gets the default kernel parameters""" + return self._info.get('kernel_params', None) + class LinuxTest(Test, LinuxSSHMixIn): """Facilitates having a cloud-image Linux based available. @@ -308,12 +438,39 @@ class LinuxTest(Test, LinuxSSHMixIn): """ timeout = 900 - chksum = None + distro = None username = 'root' password = 'password' + def _set_distro(self): + distro_name = self.params.get( + 'distro', + default=self._get_unique_tag_val('distro')) + if not distro_name: + distro_name = 'fedora' + + distro_version = self.params.get( + 'distro_version', + default=self._get_unique_tag_val('distro_version')) + if not distro_version: + distro_version = '31' + + self.distro = LinuxDistro(distro_name, distro_version, self.arch) + + # The distro checksum behaves differently than distro name and + # version. First, it does not respect a tag with the same + # name, given that it's not expected to be used for filtering + # (distro name versions are the natural choice). Second, the + # order of precedence is: parameter, attribute and then value + # from KNOWN_DISTROS. + distro_checksum = self.params.get('distro_checksum', + default=None) + if distro_checksum: + self.distro.checksum = distro_checksum + def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'): super(LinuxTest, self).setUp() + self._set_distro() self.vm.add_args('-smp', '2') self.vm.add_args('-m', '1024') # The following network device allows for SSH connections @@ -351,12 +508,14 @@ class LinuxTest(Test, LinuxSSHMixIn): self.log.info('Downloading/preparing boot image') # Fedora 31 only provides ppc64le images image_arch = self.arch - if image_arch == 'ppc64': - image_arch = 'ppc64le' + if self.distro.name == 'fedora': + if image_arch == 'ppc64': + image_arch = 'ppc64le' + try: boot = vmimage.get( - 'fedora', arch=image_arch, version='31', - checksum=self.chksum, + self.distro.name, arch=image_arch, version=self.distro.version, + checksum=self.distro.checksum, algorithm='sha256', cache_dir=self.cache_dirs[0], snapshot_dir=self.workdir) diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py index 4c8a5994b2..ab19146d1e 100644 --- a/tests/acceptance/boot_linux.py +++ b/tests/acceptance/boot_linux.py @@ -20,8 +20,6 @@ class BootLinuxX8664(LinuxTest): :avocado: tags=arch:x86_64 """ - chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0' - def test_pc_i440fx_tcg(self): """ :avocado: tags=machine:pc @@ -66,8 +64,6 @@ class BootLinuxAarch64(LinuxTest): :avocado: tags=machine:gic-version=2 """ - chksum = '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49' - def add_common_args(self): self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', @@ -83,7 +79,6 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") - self.vm.add_args("-cpu", "max") self.vm.add_args("-machine", "virt,gic-version=2") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -96,7 +91,6 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") - self.vm.add_args("-cpu", "max") self.vm.add_args("-machine", "virt,gic-version=3") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -108,7 +102,6 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("kvm") self.vm.add_args("-accel", "kvm") - self.vm.add_args("-cpu", "host") self.vm.add_args("-machine", "virt,gic-version=host") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -119,8 +112,6 @@ class BootLinuxPPC64(LinuxTest): :avocado: tags=arch:ppc64 """ - chksum = '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58' - def test_pseries_tcg(self): """ :avocado: tags=machine:pseries @@ -136,8 +127,6 @@ class BootLinuxS390X(LinuxTest): :avocado: tags=arch:s390x """ - chksum = '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d' - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_s390_ccw_virtio_tcg(self): """ diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 3ae11a7a8f..5248c8097d 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -239,6 +239,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mips64el :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:5KEc """ kernel_url = ('https://github.com/philmd/qemu-testing-blob/' 'raw/9ad2df38/mips/malta/mips64el/' @@ -258,8 +259,7 @@ class BootLinuxConsole(LinuxKernelTest): kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') - self.vm.add_args('-cpu', '5KEc', - '-kernel', kernel_path, + self.vm.add_args('-kernel', kernel_path, '-initrd', initrd_path, '-append', kernel_command_line, '-no-reboot') @@ -287,7 +287,6 @@ class BootLinuxConsole(LinuxKernelTest): + 'mem=256m@@0x0 ' + 'console=ttyS0') self.vm.add_args('-no-reboot', - '-cpu', 'I7200', '-kernel', kernel_path, '-append', kernel_command_line) self.vm.launch() @@ -299,6 +298,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -311,6 +311,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -323,6 +324,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -335,6 +337,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:aarch64 :avocado: tags=machine:virt :avocado: tags=accel:tcg + :avocado: tags=cpu:cortex-a53 """ kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/29/Everything/aarch64/os/images/pxeboot' @@ -905,6 +908,7 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc :avocado: tags=device:sd + :avocado: tags=os:netbsd """ # This test download a 304MB compressed image and expand it to 2GB deb_url = ('http://snapshot.debian.org/archive/debian/' @@ -1167,9 +1171,9 @@ class BootLinuxConsole(LinuxKernelTest): """ :avocado: tags=arch:ppc64 :avocado: tags=machine:ppce500 + :avocado: tags=cpu:e5500 """ tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' - self.vm.add_args('-cpu', 'e5500') self.do_test_advcal_2018('19', tar_hash, 'uImage') def test_ppc_g3beige(self): @@ -1211,7 +1215,7 @@ class BootLinuxConsole(LinuxKernelTest): """ :avocado: tags=arch:xtensa :avocado: tags=machine:lx60 + :avocado: tags=cpu:dc233c """ tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' - self.vm.add_args('-cpu', 'dc233c') self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf') diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py index 75c2d44492..3479b5233b 100644 --- a/tests/acceptance/boot_xen.py +++ b/tests/acceptance/boot_xen.py @@ -48,7 +48,6 @@ class BootXenBase(LinuxKernelTest): xen_command_line = self.XEN_COMMON_COMMAND_LINE self.vm.add_args('-machine', 'virtualization=on', - '-cpu', 'cortex-a57', '-m', '768', '-kernel', xen_path, '-append', xen_command_line, diff --git a/tests/acceptance/cpu_queries.py b/tests/acceptance/cpu_queries.py index 293dccb89a..cc9e380cc7 100644 --- a/tests/acceptance/cpu_queries.py +++ b/tests/acceptance/cpu_queries.py @@ -8,8 +8,6 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -import logging - from avocado_qemu import Test class QueryCPUModelExpansion(Test): @@ -27,7 +25,7 @@ class QueryCPUModelExpansion(Test): cpus = self.vm.command('query-cpu-definitions') for c in cpus: - print(repr(c)) + self.log.info("Checking CPU: %s", c) self.assertNotIn('', c['unavailable-features'], c['name']) for c in cpus: diff --git a/tests/acceptance/intel_iommu.py b/tests/acceptance/intel_iommu.py new file mode 100644 index 0000000000..474d62f6bf --- /dev/null +++ b/tests/acceptance/intel_iommu.py @@ -0,0 +1,119 @@ +# INTEL_IOMMU Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger <eric.auger@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os + +from avocado import skipIf +from avocado_qemu import LinuxTest + +@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +class IntelIOMMU(LinuxTest): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=distro:fedora + :avocado: tags=distro_version:31 + :avocado: tags=machine:q35 + :avocado: tags=accel:kvm + :avocado: tags=intel_iommu + """ + + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + 'file=%s,if=none,cache=writethrough,id=drv0' % path) + + def setUp(self): + super(IntelIOMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) + + def add_common_args(self): + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + def common_vm_setup(self, custom_kernel=None): + self.require_accelerator("kvm") + self.add_common_args() + self.vm.add_args("-accel", "kvm") + + if custom_kernel is None: + return + + kernel_url = self.distro.pxeboot_url + 'vmlinuz' + initrd_url = self.distro.pxeboot_url + 'initrd.img' + self.kernel_path = self.fetch_asset(kernel_url) + self.initrd_path = self.fetch_asset(initrd_url) + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.launch_and_wait() + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dmesg | grep -e DMAR -e IOMMU') + self.ssh_command('find /sys/kernel/iommu_groups/ -type l') + self.ssh_command('dnf -y install numactl-devel') + + def test_intel_iommu(self): + """ + :avocado: tags=intel_iommu_intremap + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on') + self.run_and_check() + + def test_intel_iommu_strict(self): + """ + :avocado: tags=intel_iommu_strict + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on,strict') + self.run_and_check() + + def test_intel_iommu_strict_cm(self): + """ + :avocado: tags=intel_iommu_strict_cm + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on,strict') + self.run_and_check() + + def test_intel_iommu_pt(self): + """ + :avocado: tags=intel_iommu_pt + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on iommu=pt') + self.run_and_check() diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py index 61c9079d04..4de1947418 100644 --- a/tests/acceptance/linux_ssh_mips_malta.py +++ b/tests/acceptance/linux_ssh_mips_malta.py @@ -19,6 +19,8 @@ from avocado.utils import archive from avocado.utils import ssh +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') class LinuxSSH(Test, LinuxSSHMixIn): timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' @@ -65,11 +67,6 @@ class LinuxSSH(Test, LinuxSSHMixIn): kernel_hash = self.IMAGE_INFO[endianess]['kernel_hash'][wordsize] return kernel_url, kernel_hash - @skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') - @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') - def setUp(self): - super(LinuxSSH, self).setUp() - def ssh_disconnect_vm(self): self.ssh_session.quit() diff --git a/tests/acceptance/machine_mips_malta.py b/tests/acceptance/machine_mips_malta.py index 7c9a4ee4d2..b67d8cb141 100644 --- a/tests/acceptance/machine_mips_malta.py +++ b/tests/acceptance/machine_mips_malta.py @@ -62,7 +62,6 @@ class MaltaMachineFramebuffer(Test): kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'clocksource=GIC console=tty0 console=ttyS0') self.vm.add_args('-kernel', kernel_path, - '-cpu', 'I6400', '-smp', '%u' % cpu_cores_count, '-vga', 'std', '-append', kernel_command_line) @@ -96,7 +95,7 @@ class MaltaMachineFramebuffer(Test): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta - :avocado: tags=cpu:i6400 + :avocado: tags=cpu:I6400 """ self.do_test_i6400_framebuffer_logo(1) @@ -105,7 +104,7 @@ class MaltaMachineFramebuffer(Test): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta - :avocado: tags=cpu:i6400 + :avocado: tags=cpu:I6400 :avocado: tags=mips:smp """ self.do_test_i6400_framebuffer_logo(7) @@ -115,7 +114,7 @@ class MaltaMachineFramebuffer(Test): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta - :avocado: tags=cpu:i6400 + :avocado: tags=cpu:I6400 :avocado: tags=mips:smp """ self.do_test_i6400_framebuffer_logo(8) diff --git a/tests/acceptance/pc_cpu_hotplug_props.py b/tests/acceptance/pc_cpu_hotplug_props.py index f48f68fc6b..2e86d5017a 100644 --- a/tests/acceptance/pc_cpu_hotplug_props.py +++ b/tests/acceptance/pc_cpu_hotplug_props.py @@ -25,11 +25,11 @@ from avocado_qemu import Test class OmittedCPUProps(Test): """ :avocado: tags=arch:x86_64 + :avocado: tags=cpu:qemu64 """ def test_no_die_id(self): self.vm.add_args('-nodefaults', '-S') self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') - self.vm.add_args('-cpu', 'qemu64') self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') self.vm.launch() self.assertEquals(len(self.vm.command('query-cpus-fast')), 2) diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py index 96ba13b894..2993ee3b07 100644 --- a/tests/acceptance/ppc_prep_40p.py +++ b/tests/acceptance/ppc_prep_40p.py @@ -27,6 +27,7 @@ class IbmPrep40pMachine(Test): """ :avocado: tags=arch:ppc :avocado: tags=machine:40p + :avocado: tags=os:netbsd :avocado: tags=slowness:high """ bios_url = ('http://ftpmirror.your.org/pub/misc/' @@ -64,6 +65,7 @@ class IbmPrep40pMachine(Test): """ :avocado: tags=arch:ppc :avocado: tags=machine:40p + :avocado: tags=os:netbsd """ drive_url = ('https://cdn.netbsd.org/pub/NetBSD/iso/7.1.2/' 'NetBSD-7.1.2-prep.iso') diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py index 71facdaa75..bb32b31240 100644 --- a/tests/acceptance/replay_kernel.py +++ b/tests/acceptance/replay_kernel.py @@ -156,8 +156,7 @@ class ReplayKernelNormal(ReplayKernelBase): 'console=ttyAMA0') console_pattern = 'VFS: Cannot open root device' - self.run_rr(kernel_path, kernel_command_line, console_pattern, - args=('-cpu', 'cortex-a53')) + self.run_rr(kernel_path, kernel_command_line, console_pattern) def test_arm_virt(self): """ @@ -301,7 +300,7 @@ class ReplayKernelNormal(ReplayKernelBase): tar_url = ('https://www.qemu-advent-calendar.org' '/2018/download/day19.tar.xz') file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'uImage', ('-cpu', 'e5500')) + self.do_test_advcal_2018(file_path, 'uImage') def test_ppc_g3beige(self): """ @@ -348,8 +347,7 @@ class ReplayKernelNormal(ReplayKernelBase): tar_url = ('https://www.qemu-advent-calendar.org' '/2018/download/day02.tar.xz') file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf', - args=('-cpu', 'dc233c')) + self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf') @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') class ReplayKernelSlow(ReplayKernelBase): @@ -394,6 +392,7 @@ class ReplayKernelSlow(ReplayKernelBase): :avocado: tags=machine:malta :avocado: tags=endian:little :avocado: tags=slowness:high + :avocado: tags=cpu:5KEc """ kernel_url = ('https://github.com/philmd/qemu-testing-blob/' 'raw/9ad2df38/mips/malta/mips64el/' @@ -414,7 +413,7 @@ class ReplayKernelSlow(ReplayKernelBase): 'rdinit=/sbin/init noreboot') console_pattern = 'Boot successful.' self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-initrd', initrd_path, '-cpu', '5KEc')) + args=('-initrd', initrd_path)) def do_test_mips_malta32el_nanomips(self, kernel_path_xz): kernel_path = self.workdir + "kernel" @@ -426,14 +425,14 @@ class ReplayKernelSlow(ReplayKernelBase): 'mem=256m@@0x0 ' 'console=ttyS0') console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-cpu', 'I7200')) + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) def test_mips_malta32el_nanomips_4k(self): """ :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -447,6 +446,7 @@ class ReplayKernelSlow(ReplayKernelBase): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' @@ -460,6 +460,7 @@ class ReplayKernelSlow(ReplayKernelBase): :avocado: tags=arch:mipsel :avocado: tags=machine:malta :avocado: tags=endian:little + :avocado: tags=cpu:I7200 """ kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' diff --git a/tests/acceptance/reverse_debugging.py b/tests/acceptance/reverse_debugging.py index be01aca217..d2921e70c3 100644 --- a/tests/acceptance/reverse_debugging.py +++ b/tests/acceptance/reverse_debugging.py @@ -207,4 +207,4 @@ class ReverseDebugging_AArch64(ReverseDebugging): kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) self.reverse_debugging( - args=('-kernel', kernel_path, '-cpu', 'cortex-a53')) + args=('-kernel', kernel_path)) diff --git a/tests/acceptance/smmu.py b/tests/acceptance/smmu.py new file mode 100644 index 0000000000..b3c4de6bf4 --- /dev/null +++ b/tests/acceptance/smmu.py @@ -0,0 +1,137 @@ +# SMMUv3 Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger <eric.auger@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os + +from avocado import skipIf +from avocado_qemu import LinuxTest, BUILD_DIR + +@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +class SMMU(LinuxTest): + """ + :avocado: tags=accel:kvm + :avocado: tags=cpu:host + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=distro:fedora + :avocado: tags=smmu + """ + + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + 'file=%s,if=none,cache=writethrough,id=drv0' % path) + + def setUp(self): + super(SMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) + + def common_vm_setup(self, custom_kernel=False): + self.require_accelerator("kvm") + self.vm.add_args("-accel", "kvm") + self.vm.add_args("-cpu", "host") + self.vm.add_args("-machine", "iommu=smmuv3") + self.vm.add_args("-d", "guest_errors") + self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', + 'edk2-aarch64-code.fd')) + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + if custom_kernel is False: + return + + kernel_url = self.distro.pxeboot_url + 'vmlinuz' + initrd_url = self.distro.pxeboot_url + 'initrd.img' + self.kernel_path = self.fetch_asset(kernel_url) + self.initrd_path = self.fetch_asset(initrd_url) + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.launch_and_wait() + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dnf -y install numactl-devel') + + + # 5.3 kernel without RIL # + + def test_smmu_noril(self): + """ + :avocado: tags=smmu_noril + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup() + self.run_and_check() + + def test_smmu_noril_passthrough(self): + """ + :avocado: tags=smmu_noril_passthrough + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check() + + def test_smmu_noril_nostrict(self): + """ + :avocado: tags=smmu_noril_nostrict + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.strict=0') + self.run_and_check() + + # 5.8 kernel featuring range invalidation + # >= v5.7 kernel + + def test_smmu_ril(self): + """ + :avocado: tags=smmu_ril + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup() + self.run_and_check() + + def test_smmu_ril_passthrough(self): + """ + :avocado: tags=smmu_ril_passthrough + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check() + + def test_smmu_ril_nostrict(self): + """ + :avocado: tags=smmu_ril_nostrict + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.strict=0') + self.run_and_check() diff --git a/tests/acceptance/tcg_plugins.py b/tests/acceptance/tcg_plugins.py index c21bf9e52a..9ca1515c3b 100644 --- a/tests/acceptance/tcg_plugins.py +++ b/tests/acceptance/tcg_plugins.py @@ -25,7 +25,7 @@ class PluginKernelBase(LinuxKernelTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' def run_vm(self, kernel_path, kernel_command_line, - plugin, plugin_log, console_pattern, args): + plugin, plugin_log, console_pattern, args=None): vm = self.get_vm() vm.set_console() @@ -68,7 +68,7 @@ class PluginKernelNormal(PluginKernelBase): :avocado: tags=accel:tcg :avocado: tags=arch:aarch64 :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a57 + :avocado: tags=cpu:cortex-a53 """ kernel_path = self._grab_aarch64_kernel() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -80,8 +80,7 @@ class PluginKernelNormal(PluginKernelBase): self.run_vm(kernel_path, kernel_command_line, "tests/plugin/libinsn.so", plugin_log.name, - console_pattern, - args=('-cpu', 'cortex-a53')) + console_pattern) with plugin_log as lf, \ mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: @@ -95,7 +94,7 @@ class PluginKernelNormal(PluginKernelBase): :avocado: tags=accel:tcg :avocado: tags=arch:aarch64 :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a57 + :avocado: tags=cpu:cortex-a53 """ kernel_path = self._grab_aarch64_kernel() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -108,7 +107,7 @@ class PluginKernelNormal(PluginKernelBase): self.run_vm(kernel_path, kernel_command_line, "tests/plugin/libinsn.so", plugin_log.name, console_pattern, - args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) + args=('-icount', 'shift=1')) with plugin_log as lf, \ mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: @@ -121,7 +120,7 @@ class PluginKernelNormal(PluginKernelBase): :avocado: tags=accel:tcg :avocado: tags=arch:aarch64 :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a57 + :avocado: tags=cpu:cortex-a53 """ kernel_path = self._grab_aarch64_kernel() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -134,7 +133,7 @@ class PluginKernelNormal(PluginKernelBase): self.run_vm(kernel_path, kernel_command_line, "tests/plugin/libmem.so,arg=both", plugin_log.name, console_pattern, - args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) + args=('-icount', 'shift=1')) with plugin_log as lf, \ mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: diff --git a/tests/acceptance/virtio-gpu.py b/tests/acceptance/virtio-gpu.py index e7979343e9..589332c1b7 100644 --- a/tests/acceptance/virtio-gpu.py +++ b/tests/acceptance/virtio-gpu.py @@ -60,6 +60,7 @@ class VirtioGPUx86(Test): """ :avocado: tags=arch:x86_64 :avocado: tags=device:virtio-vga + :avocado: tags=cpu:host """ kernel_command_line = ( self.KERNEL_COMMON_COMMAND_LINE + "console=ttyS0 rdinit=/bin/bash" @@ -72,7 +73,6 @@ class VirtioGPUx86(Test): initrd_path = self.fetch_asset(self.INITRD_URL) self.vm.set_console() - self.vm.add_args("-cpu", "host") self.vm.add_args("-m", "2G") self.vm.add_args("-machine", "pc,accel=kvm") self.vm.add_args("-device", "virtio-vga,virgl=on") @@ -101,6 +101,7 @@ class VirtioGPUx86(Test): """ :avocado: tags=arch:x86_64 :avocado: tags=device:vhost-user-vga + :avocado: tags=cpu:host """ kernel_command_line = ( self.KERNEL_COMMON_COMMAND_LINE + "console=ttyS0 rdinit=/bin/bash" @@ -140,7 +141,6 @@ class VirtioGPUx86(Test): ) self.vm.set_console() - self.vm.add_args("-cpu", "host") self.vm.add_args("-m", "2G") self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") diff --git a/tests/acceptance/x86_cpu_model_versions.py b/tests/acceptance/x86_cpu_model_versions.py index 77ed8597a4..0e9feda62d 100644 --- a/tests/acceptance/x86_cpu_model_versions.py +++ b/tests/acceptance/x86_cpu_model_versions.py @@ -252,10 +252,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_4_1(self): """ :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server """ # machine-type only: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') @@ -263,9 +266,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') @@ -273,10 +279,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_set_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ # command line must override machine-type if CPU model is not versioned: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,+arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,+arch-capabilities') self.vm.launch() self.assertTrue(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') @@ -284,9 +293,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_unset_4_1(self): """ :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,enforce=off,-arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') @@ -294,10 +306,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v1_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ # versioned CPU model overrides machine-type: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v1,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') @@ -305,9 +320,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v2_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,enforce=off') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off') self.vm.launch() self.assertTrue(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') @@ -315,10 +333,13 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v1_set_4_0(self): """ :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server """ # command line must override machine-type and versioned CPU model: self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off,+arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v1,x-force-features=on,check=off,' + 'enforce=off,+arch-capabilities') self.vm.launch() self.assertTrue(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') @@ -326,9 +347,12 @@ class CascadelakeArchCapabilities(avocado_qemu.Test): def test_v2_unset_4_1(self): """ :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server """ self.vm.add_args('-S') - self.vm.add_args('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,enforce=off,-arch-capabilities') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') |