[QEMU-devel][RFC PATCH 1/1] backends/hostmem: qapi/qom: Add an ObjectOption for memory-backend-* called HostMemType and its arg 'cxlram'
Introduce a new configuration option 'host-mem-type=' in the '-object memory-backend-ram', allowing users to specify from which type of memory to allocate. Users can specify 'cxlram' as an argument, and QEMU will then automatically locate CXL RAM NUMA nodes and use them as the backend memory. For example: -object memory-backend-ram,id=vmem0,size=19G,host-mem-type=cxlram \ -device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1 \ -device cxl-rp,port=0,bus=cxl.1,id=root_port13,chassis=0,slot=2 \ -device cxl-type3,bus=root_port13,volatile-memdev=vmem0,id=cxl-vmem0 \ -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=19G,cxl-fmw.0.interleave-granularity=8k \ In v1, we plan to move most of the implementations to util and break down this patch into different smaller patches. Signed-off-by: Ho-Ren (Jack) Chuang Signed-off-by: Hao Xiang --- backends/hostmem.c | 184 +++ include/sysemu/hostmem.h | 1 + qapi/common.json | 19 qapi/qom.json| 1 + qemu-options.hx | 2 +- 5 files changed, 206 insertions(+), 1 deletion(-) diff --git a/backends/hostmem.c b/backends/hostmem.c index 747e7838c0..3bede13879 100644 --- a/backends/hostmem.c +++ b/backends/hostmem.c @@ -44,6 +44,133 @@ host_memory_backend_get_name(HostMemoryBackend *backend) return object_get_canonical_path(OBJECT(backend)); } +#define FILE_LINE_LEN 256 +static int +is_valid_node(const char *path) { +FILE *file = fopen(path, "r"); +if (file == NULL) { +return -1; +} + +char line[FILE_LINE_LEN]; +if (fgets(line, sizeof(line), file) != NULL) { +int target_node = atoi(line); + +if (target_node >= 0) { +fclose(file); +return target_node; +} +} + +fclose(file); +return -1; +} + +static int +is_directory(const char *path) { +struct stat path_stat; +stat(path, &path_stat); +return S_ISDIR(path_stat.st_mode); +} + +static int +is_symlink(const char *path) { +struct stat path_stat; +if (lstat(path, &path_stat) == -1) { +return 0; +} +return S_ISLNK(path_stat.st_mode); +} + +#define CXL_DEVICE_PATH "/sys/bus/cxl/devices/" +#define REGION_PATH_LEN 307 +#define DAX_REGION_PATH_LEN 563 +#define DAX_PATH_LEN 819 +#define TARGET_FILE_PATH_LEN 831 +/* + * return: the number of valid numa node id found + */ +static int +host_memory_backend_get_cxlram_nodes(int *valid_cxlram_nodes) { +DIR *base_dir = NULL, *region_dir = NULL, *dax_region_dir = NULL; +const char *base_dir_path = CXL_DEVICE_PATH; +struct dirent *entry; +int valid_node = 0, ret = 0; + +base_dir = opendir(base_dir_path); +if (base_dir == NULL) { +return valid_node; +} + +while ((entry = readdir(base_dir)) != NULL) { +char region_path[REGION_PATH_LEN]; + +ret = snprintf(region_path, sizeof(region_path), "%s%s", +base_dir_path, entry->d_name); +if (ret < 0 || +!is_symlink(region_path) || +strncmp(entry->d_name, "region", ARRAY_SIZE("region") - 1)) { +continue; +} + +region_dir = opendir(region_path); +if (region_dir == NULL) { +goto region_exit; +} + +while ((entry = readdir(region_dir)) != NULL) { +char dax_region_path[DAX_REGION_PATH_LEN]; + +ret = snprintf(dax_region_path, sizeof(dax_region_path), "%s/%s", +region_path, entry->d_name); +if (ret < 0 || +!is_directory(dax_region_path) || +strncmp(entry->d_name, "dax_region", +ARRAY_SIZE("dax_region") - 1)) { + +continue; +} + +dax_region_dir = opendir(dax_region_path); +if (dax_region_dir == NULL) { +goto dax_region_exit; +} + +while ((entry = readdir(dax_region_dir)) != NULL) { +int target_node; +char dax_path[DAX_PATH_LEN]; +char target_file_path[TARGET_FILE_PATH_LEN]; +ret = snprintf(dax_path, sizeof(dax_path), "%s/%s", +dax_region_path, entry->d_name); +if (ret < 0 || +!is_directory(dax_path) || +strncmp(entry->d_name, "dax", ARRAY_SIZE("dax") - 1)) { +continue; +} + +ret = snprintf(target_file_path, sizeof(target_file_path), +"%s/target_node", dax_path); +if (ret < 0) { +continue; +} + +target_node = is_valid_node(target_file_path); +if (target_node >= 0) { +valid_cxlram_nodes[valid_node] = target_node; +v
Re: [PATCH for-8.2?] target/i386: Fix 32-bit wrapping of pc/eip computation
On 12/25/23 07:49, Michael Tokarev wrote: 12.12.2023 20:25, Richard Henderson: In 32-bit mode, pc = eip + cs_base is also 32-bit, and must wrap. Failure to do so results in incorrect memory exceptions to the guest. Before 732d548732ed, this was implicitly done via truncation to target_ulong but only in qemu-system-i386, not qemu-system-x86_64. To fix this, we must add conditional zero-extensions. Since we have to test for 32 vs 64-bit anyway, note that cs_base is always zero in 64-bit mode. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2022 Signed-off-by: Richard Henderson --- This may be too late for 8.2; if not, then 8.2.1 and 8.1.next. I think I have found all forms of pc <-> eip, but another set of eyes would be appreciated. This change breaks trivial 4M edk2 boot - both in 8.2.0 and in 8.1.4 (which also has this commit now). qemu-system-x86_64 -machine q35 -no-user-config -nodefaults -display none \ -serial stdio \ -drive file=/usr/share/OVMF/OVMF_CODE_4M.secboot.fd,if=pflash,format=raw,readonly=on \ -drive file=/usr/share/OVMF/OVMF_VARS_4M.ms.fd,if=pflash,format=raw,snapshot=on After this change, nothing is printed on the serial console anymore (or in vga, whatever). Before that commit, usual edk2 boot sequence is seen. Nothing has changed with the 2M variant though. Ack. Looking at it r~
Re: [PATCH] tcg/i386: use 8-bit OR or XOR for unsigned 8-bit immediates
On 12/28/23 23:05, Paolo Bonzini wrote: In the case where OR or XOR has an 8-bit immediate between 128 and 255, we can operate on a low-byte register and shorten the output by two or three bytes (two if a prefix byte is needed for REX.B). Signed-off-by: Paolo Bonzini --- tcg/i386/tcg-target.c.inc | 7 +++ 1 file changed, 7 insertions(+) Queued. I adjusted the function a bit to use a switch. r~ diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index 1791b959738..a24a23f43b1 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -244,6 +244,7 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct, int vece) #define P_VEXL 0x8 /* Set VEX.L = 1 */ #define P_EVEX 0x10/* Requires EVEX encoding */ +#define OPC_ARITH_EbIb (0x80) #define OPC_ARITH_EvIz(0x81) #define OPC_ARITH_EvIb(0x83) #define OPC_ARITH_GvEv(0x03) /* ... plus (ARITH_FOO << 3) */ @@ -1366,6 +1367,12 @@ static void tgen_arithi(TCGContext *s, int c, int r0, tcg_out8(s, val); return; } +if (val == (uint8_t)val && (c == ARITH_OR || c == ARITH_XOR) && +(r0 < 4 || TCG_TARGET_REG_BITS == 64)) { +tcg_out_modrm(s, OPC_ARITH_EbIb + P_REXB_RM, c, r0); +tcg_out8(s, val); +return; +} if (rexw == 0 || val == (int32_t)val) { tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0); tcg_out32(s, val);
Re: [PATCH v2] tcg/i386: convert add/sub of 128 to sub/add of -128
On 12/28/23 23:05, Paolo Bonzini wrote: Extend the existing conditional that generates INC/DEC, to also swap an ADD for a SUB and vice versa when the immediate is 128. This facilitates using OPC_ARITH_EvIb instead of OPC_ARITH_EvIz. Best reviewed with "git diff -b". Signed-off-by: Paolo Bonzini --- tcg/i386/tcg-target.c.inc | 40 +++ 1 file changed, 24 insertions(+), 16 deletions(-) Queued, thanks. r~
[PATCH 4/5] migration: Implement 'qatzip' methods using QAT
Uses QAT to offload deflate compression in the 'qatzip' compression method for multifd migration. Signed-off-by: Bryan Zhang Signed-off-by: Hao Xiang --- migration/multifd-qatzip.c | 314 +++-- 1 file changed, 301 insertions(+), 13 deletions(-) diff --git a/migration/multifd-qatzip.c b/migration/multifd-qatzip.c index 1733bbddb7..3fb0bb5b27 100644 --- a/migration/multifd-qatzip.c +++ b/migration/multifd-qatzip.c @@ -18,50 +18,338 @@ #include "migration.h" #include "options.h" #include "multifd.h" +#include +struct qatzip_data { +/* + * Unique session for use with QATzip API + */ +QzSession_T sess; + +/* + * For compression: Buffer for pages to compress + * For decompression: Buffer for data to decompress + */ +uint8_t *in_buf; +uint32_t in_len; + +/* + * For compression: Output buffer of compressed data + * For decompression: Output buffer of decompressed data + */ +uint8_t *out_buf; +uint32_t out_len; +}; + +/** + * qatzip_send_setup: Set up QATzip session and private buffers. + * + * @param pMultifd channel params + * @param errp Pointer to error, which will be set in case of error + * @return 0 on success, -1 on error (and *errp will be set) + */ static int qatzip_send_setup(MultiFDSendParams *p, Error **errp) { +struct qatzip_data *q; +QzSessionParamsDeflate_T params; +const char *err_msg; +int ret; + +q = g_new0(struct qatzip_data, 1); +p->data = q; + +ret = qzInit(&q->sess, 0); +if (ret != QZ_OK && ret != QZ_DUPLICATE) { +err_msg = "qzInit failed"; +goto err_free_q; +} + +ret = qzGetDefaultsDeflate(¶ms); +if (ret != QZ_OK) { +err_msg = "qzGetDefaultsDeflate failed"; +goto err_close; +} + +/* Use maximum hardware buffer size to improve batching. */ +params.common_params.hw_buff_sz = QZ_HW_BUFF_MAX_SZ; + +/* Make sure to use configured QATzip compression level. */ +params.common_params.comp_lvl = migrate_multifd_qatzip_level(); + +ret = qzSetupSessionDeflate(&q->sess, ¶ms); +if (ret != QZ_OK && ret != QZ_DUPLICATE) { +err_msg = "qzSetupSessionDeflate failed"; +goto err_close; +} + +/* TODO Add support for larger packets. */ +if (MULTIFD_PACKET_SIZE > UINT32_MAX) { +err_msg = "packet size too large for QAT"; +goto err_close; +} + +q->in_len = MULTIFD_PACKET_SIZE; +q->in_buf = g_try_malloc(q->in_len); +if (!q->in_buf) { +err_msg = "malloc failed"; +goto err_close; +} + +q->out_len = qzMaxCompressedLength(MULTIFD_PACKET_SIZE, &q->sess); +q->out_buf = g_try_malloc(q->out_len); +if (!q->out_buf) { +err_msg = "malloc failed"; +goto err_free_inbuf; +} + return 0; + +err_free_inbuf: +g_free(q->in_buf); +err_close: +qzClose(&q->sess); +err_free_q: +g_free(q); +error_setg(errp, "multifd %u: %s", p->id, err_msg); +return -1; } -static void qatzip_send_cleanup(MultiFDSendParams *p, Error **errp) {}; +/** + * qatzip_send_cleanup: Tear down QATzip session and release private buffers. + * + * @param pMultifd channel params + * @param errp Pointer to error, which will be set in case of error + * @return None + */ +static void qatzip_send_cleanup(MultiFDSendParams *p, Error **errp) +{ +struct qatzip_data *q = p->data; +const char *err_msg; +int ret; + +ret = qzTeardownSession(&q->sess); +if (ret != QZ_OK) { +err_msg = "qzTeardownSession failed"; +goto err; +} + +ret = qzClose(&q->sess); +if (ret != QZ_OK) { +err_msg = "qzClose failed"; +goto err; +} + +g_free(q->in_buf); +q->in_buf = NULL; +g_free(q->out_buf); +q->out_buf = NULL; +g_free(p->data); +p->data = NULL; +return; + +err: +error_setg(errp, "multifd %u: %s", p->id, err_msg); +} +/** + * qatzip_send_prepare: Compress pages and update IO channel info. + * + * @param pMultifd channel params + * @param errp Pointer to error, which will be set in case of error + * @return 0 on success, -1 on error (and *errp will be set) + */ static int qatzip_send_prepare(MultiFDSendParams *p, Error **errp) { -MultiFDPages_t *pages = p->pages; +struct qatzip_data *q = p->data; +int ret; +unsigned int in_len, out_len; +/* memcpy all the pages into one buffer. */ for (int i = 0; i < p->normal_num; i++) { -p->iov[p->iovs_num].iov_base = pages->block->host + p->normal[i]; -p->iov[p->iovs_num].iov_len = p->page_size; -p->iovs_num++; +memcpy(q->in_buf + (i * p->page_size), + p->pages->block->host + p->normal[i], + p->page_size); +} + +in_len = p->normal_num * p->page_size; +if (in_len > q->in_len) { +error_setg(errp, "multifd %u: unexpectedly large input", p->id); +return -1; +} +out_len = q->ou
[PATCH 2/5] migration: Add compression level parameter for QATzip
Adds support for a parameter to specify QATzip compression level. This is a preparatory commit for a subsequent commit that will actually use QATzip compression. Signed-off-by: Bryan Zhang Signed-off-by: Hao Xiang --- migration/migration-hmp-cmds.c | 4 migration/options.c| 27 +++ migration/options.h| 1 + qapi/migration.json| 19 ++- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index 99710c8ffb..c3a8f1888d 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -628,6 +628,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->has_multifd_zlib_level = true; visit_type_uint8(v, param, &p->multifd_zlib_level, &err); break; +case MIGRATION_PARAMETER_MULTIFD_QATZIP_LEVEL: +p->has_multifd_qatzip_level = true; +visit_type_uint8(v, param, &p->multifd_qatzip_level, &err); +break; case MIGRATION_PARAMETER_MULTIFD_ZSTD_LEVEL: p->has_multifd_zstd_level = true; visit_type_uint8(v, param, &p->multifd_zstd_level, &err); diff --git a/migration/options.c b/migration/options.c index 8d8ec73ad9..4a931effae 100644 --- a/migration/options.c +++ b/migration/options.c @@ -62,6 +62,12 @@ #define DEFAULT_MIGRATE_MULTIFD_COMPRESSION MULTIFD_COMPRESSION_NONE /* 0: means nocompress, 1: best speed, ... 9: best compress ratio */ #define DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL 1 +/* + * 1: best speed, ... 9: best compress ratio + * There is some nuance here. Refer to QATzip documentation to understand + * the mapping of QATzip levels to standard deflate levels. + */ +#define DEFAULT_MIGRATE_MULTIFD_QATZIP_LEVEL 1 /* 0: means nocompress, 1: best speed, ... 20: best compress ratio */ #define DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL 1 @@ -143,6 +149,9 @@ Property migration_properties[] = { DEFINE_PROP_UINT8("multifd-zlib-level", MigrationState, parameters.multifd_zlib_level, DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL), +DEFINE_PROP_UINT8("multifd-qatzip-level", MigrationState, + parameters.multifd_qatzip_level, + DEFAULT_MIGRATE_MULTIFD_QATZIP_LEVEL), DEFINE_PROP_UINT8("multifd-zstd-level", MigrationState, parameters.multifd_zstd_level, DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL), @@ -859,6 +868,13 @@ int migrate_multifd_zlib_level(void) return s->parameters.multifd_zlib_level; } +int migrate_multifd_qatzip_level(void) +{ +MigrationState *s = migrate_get_current(); + +return s->parameters.multifd_qatzip_level; +} + int migrate_multifd_zstd_level(void) { MigrationState *s = migrate_get_current(); @@ -981,6 +997,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->multifd_compression = s->parameters.multifd_compression; params->has_multifd_zlib_level = true; params->multifd_zlib_level = s->parameters.multifd_zlib_level; +params->has_multifd_qatzip_level = true; +params->multifd_qatzip_level = s->parameters.multifd_qatzip_level; params->has_multifd_zstd_level = true; params->multifd_zstd_level = s->parameters.multifd_zstd_level; params->has_xbzrle_cache_size = true; @@ -1036,6 +1054,7 @@ void migrate_params_init(MigrationParameters *params) params->has_multifd_channels = true; params->has_multifd_compression = true; params->has_multifd_zlib_level = true; +params->has_multifd_qatzip_level = true; params->has_multifd_zstd_level = true; params->has_xbzrle_cache_size = true; params->has_max_postcopy_bandwidth = true; @@ -1145,6 +1164,14 @@ bool migrate_params_check(MigrationParameters *params, Error **errp) return false; } +if (params->has_multifd_qatzip_level && +((params->multifd_qatzip_level > 9) || +(params->multifd_qatzip_level < 1))) { +error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_qatzip_level", + "a value between 1 and 9"); +return false; +} + if (params->has_multifd_zstd_level && (params->multifd_zstd_level > 20)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zstd_level", diff --git a/migration/options.h b/migration/options.h index 246c160aee..82707f34d0 100644 --- a/migration/options.h +++ b/migration/options.h @@ -87,6 +87,7 @@ MigMode migrate_mode(void); int migrate_multifd_channels(void); MultiFDCompression migrate_multifd_compression(void); int migrate_multifd_zlib_level(void); +int migrate_multifd_qatzip_level(void); int migrate_multifd_zstd_level(void); uint8_t migrate_throttle_trigger_threshold(void); const char *migrate_tls_authz(void); diff --git a/qapi/migration.json b/qapi/migration.json index eb2f883513..6d5a4b0489 100644 --- a/qapi/migration.json +++ b/qapi/migrati
[PATCH 5/5] migration: Add integration test for 'qatzip' compression method
Adds an integration test for 'qatzip'. Signed-off-by: Bryan Zhang Signed-off-by: Hao Xiang --- tests/qtest/meson.build | 4 tests/qtest/migration-test.c | 37 2 files changed, 41 insertions(+) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 47dabf91d0..5931bd6418 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -302,6 +302,10 @@ if gnutls.found() endif endif +if qatzip.found() + migration_files += [qatzip] +endif + qtests = { 'bios-tables-test': [io, 'boot-sector.c', 'acpi-utils.c', 'tpm-emu.c'], 'cdrom-test': files('boot-sector.c'), diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index d520c587f7..f51bc4056f 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -35,6 +35,10 @@ # endif /* CONFIG_TASN1 */ #endif /* CONFIG_GNUTLS */ +#ifdef CONFIG_QATZIP +#include +#endif /* CONFIG_QATZIP */ + /* For dirty ring test; so far only x86_64 is supported */ #if defined(__linux__) && defined(HOST_X86_64) #include "linux/kvm.h" @@ -2572,6 +2576,15 @@ test_migrate_precopy_tcp_multifd_zstd_start(QTestState *from, } #endif /* CONFIG_ZSTD */ +#ifdef CONFIG_QATZIP +static void * +test_migrate_precopy_tcp_multifd_qatzip_start(QTestState *from, + QTestState *to) +{ +return test_migrate_precopy_tcp_multifd_start_common(from, to, "qatzip"); +} +#endif + static void test_multifd_tcp_none(void) { MigrateCommon args = { @@ -2607,6 +2620,17 @@ static void test_multifd_tcp_zstd(void) } #endif +#ifdef CONFIG_QATZIP +static void test_multifd_tcp_qatzip(void) +{ +MigrateCommon args = { +.listen_uri = "defer", +.start_hook = test_migrate_precopy_tcp_multifd_qatzip_start, +}; +test_precopy_common(&args); +} +#endif + #ifdef CONFIG_GNUTLS static void * test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from, @@ -3480,6 +3504,19 @@ int main(int argc, char **argv) qtest_add_func("/migration/multifd/tcp/plain/zstd", test_multifd_tcp_zstd); #endif +#ifdef CONFIG_QATZIP +/* + * Use QATzip's qzInit() function as a runtime hardware check. + * Ideally there might be a cleaner way to probe for the presence of QAT. + */ +QzSession_T sess; +memset(&sess, 0, sizeof(QzSession_T)); +if (qzInit(&sess, 0) == QZ_OK) { +qzClose(&sess); +qtest_add_func("/migration/multifd/tcp/plain/qatzip", +test_multifd_tcp_qatzip); +} +#endif #ifdef CONFIG_GNUTLS qtest_add_func("/migration/multifd/tcp/tls/psk/match", test_multifd_tcp_tls_psk_match); -- 2.30.2
[PATCH 3/5] migration: Introduce unimplemented 'qatzip' compression method
Adds support for 'qatzip' as an option for the multifd compression method parameter, but copy-pastes the no-op logic to leave the actual methods effectively unimplemented. This is in preparation of a subsequent commit that will implement actually using QAT for compression and decompression. Signed-off-by: Bryan Zhang Signed-off-by: Hao Xiang --- hw/core/qdev-properties-system.c | 6 ++- migration/meson.build| 1 + migration/multifd-qatzip.c | 81 migration/multifd.h | 1 + qapi/migration.json | 5 +- 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 migration/multifd-qatzip.c diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 1a396521d5..d8e48dcb0e 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -658,7 +658,11 @@ const PropertyInfo qdev_prop_fdc_drive_type = { const PropertyInfo qdev_prop_multifd_compression = { .name = "MultiFDCompression", .description = "multifd_compression values, " - "none/zlib/zstd", + "none/zlib/zstd" +#ifdef CONFIG_QATZIP + "/qatzip" +#endif + , .enum_table = &MultiFDCompression_lookup, .get = qdev_propinfo_get_enum, .set = qdev_propinfo_set_enum, diff --git a/migration/meson.build b/migration/meson.build index 92b1cc4297..e20f318379 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -40,6 +40,7 @@ if get_option('live_block_migration').allowed() system_ss.add(files('block.c')) endif system_ss.add(when: zstd, if_true: files('multifd-zstd.c')) +system_ss.add(when: qatzip, if_true: files('multifd-qatzip.c')) specific_ss.add(when: 'CONFIG_SYSTEM_ONLY', if_true: files('ram.c', diff --git a/migration/multifd-qatzip.c b/migration/multifd-qatzip.c new file mode 100644 index 00..1733bbddb7 --- /dev/null +++ b/migration/multifd-qatzip.c @@ -0,0 +1,81 @@ +/* + * Multifd QATzip compression implementation + * + * Copyright (c) Bytedance + * + * Authors: + * Bryan Zhang + * Hao Xiang + * + * 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 "exec/ramblock.h" +#include "exec/target_page.h" +#include "qapi/error.h" +#include "migration.h" +#include "options.h" +#include "multifd.h" + +static int qatzip_send_setup(MultiFDSendParams *p, Error **errp) +{ +return 0; +} + +static void qatzip_send_cleanup(MultiFDSendParams *p, Error **errp) {}; + +static int qatzip_send_prepare(MultiFDSendParams *p, Error **errp) +{ +MultiFDPages_t *pages = p->pages; + +for (int i = 0; i < p->normal_num; i++) { +p->iov[p->iovs_num].iov_base = pages->block->host + p->normal[i]; +p->iov[p->iovs_num].iov_len = p->page_size; +p->iovs_num++; +} + +p->next_packet_size = p->normal_num * p->page_size; +p->flags |= MULTIFD_FLAG_NOCOMP; +return 0; +} + +static int qatzip_recv_setup(MultiFDRecvParams *p, Error **errp) +{ +return 0; +} + +static void qatzip_recv_cleanup(MultiFDRecvParams *p) {}; + +static int qatzip_recv_pages(MultiFDRecvParams *p, Error **errp) +{ +uint32_t flags = p->flags & MULTIFD_FLAG_COMPRESSION_MASK; + +if (flags != MULTIFD_FLAG_NOCOMP) { +error_setg(errp, "multifd %u: flags received %x flags expected %x", + p->id, flags, MULTIFD_FLAG_NOCOMP); +return -1; +} +for (int i = 0; i < p->normal_num; i++) { +p->iov[i].iov_base = p->host + p->normal[i]; +p->iov[i].iov_len = p->page_size; +} +return qio_channel_readv_all(p->c, p->iov, p->normal_num, errp); +} + +static MultiFDMethods multifd_qatzip_ops = { +.send_setup = qatzip_send_setup, +.send_cleanup = qatzip_send_cleanup, +.send_prepare = qatzip_send_prepare, +.recv_setup = qatzip_recv_setup, +.recv_cleanup = qatzip_recv_cleanup, +.recv_pages = qatzip_recv_pages +}; + +static void multifd_qatzip_register(void) +{ +multifd_register_ops(MULTIFD_COMPRESSION_QATZIP, &multifd_qatzip_ops); +} + +migration_init(multifd_qatzip_register); diff --git a/migration/multifd.h b/migration/multifd.h index a835643b48..5600f7fc82 100644 --- a/migration/multifd.h +++ b/migration/multifd.h @@ -33,6 +33,7 @@ int multifd_queue_page(QEMUFile *f, RAMBlock *block, ram_addr_t offset); #define MULTIFD_FLAG_NOCOMP (0 << 1) #define MULTIFD_FLAG_ZLIB (1 << 1) #define MULTIFD_FLAG_ZSTD (2 << 1) +#define MULTIFD_FLAG_QATZIP (3 << 1) /* This value needs to be a multiple of qemu_target_page_size() */ #define MULTIFD_PACKET_SIZE (512 * 1024) diff --git a/qapi/migration.json b/qapi/migration.json index 6d5a4b0489..e3cc195aed 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -625,11 +625,14 @@ # # @zstd: use zstd compression method. # +# @qatzip: use qatzip compression method.
[PATCH 1/5] meson: Introduce 'qatzip' feature to the build system.
Add a 'qatzip' feature, which is automatically disabled, and which depends on the QATzip library if enabled. Signed-off-by: Bryan Zhang Signed-off-by: Hao Xiang --- meson.build | 10 ++ meson_options.txt | 2 ++ scripts/meson-buildoptions.sh | 3 +++ 3 files changed, 15 insertions(+) diff --git a/meson.build b/meson.build index 6c77d9687d..99050b1109 100644 --- a/meson.build +++ b/meson.build @@ -1041,6 +1041,14 @@ if not get_option('zstd').auto() or have_block required: get_option('zstd'), method: 'pkg-config') endif + +qatzip = not_found +if get_option('qatzip').enabled() + qatzip = dependency('qatzip', version: '>=1.1.2', + required: get_option('qatzip'), + method: 'pkg-config') +endif + virgl = not_found have_vhost_user_gpu = have_tools and targetos == 'linux' and pixman.found() @@ -2208,6 +2216,7 @@ config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim) config_host_data.set('CONFIG_STATX', has_statx) config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id) config_host_data.set('CONFIG_ZSTD', zstd.found()) +config_host_data.set('CONFIG_QATZIP', qatzip.found()) config_host_data.set('CONFIG_FUSE', fuse.found()) config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found()) config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found()) @@ -4379,6 +4388,7 @@ summary_info += {'snappy support':snappy} summary_info += {'bzip2 support': libbzip2} summary_info += {'lzfse support': liblzfse} summary_info += {'zstd support': zstd} +summary_info += {'QATzip support':qatzip} summary_info += {'NUMA host support': numa} summary_info += {'capstone': capstone} summary_info += {'libpmem support': libpmem} diff --git a/meson_options.txt b/meson_options.txt index c9baeda639..0f3b380f82 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -259,6 +259,8 @@ option('xkbcommon', type : 'feature', value : 'auto', description: 'xkbcommon support') option('zstd', type : 'feature', value : 'auto', description: 'zstd compression support') +option('qatzip', type: 'feature', value: 'disabled', + description: 'QATzip compression support') option('fuse', type: 'feature', value: 'auto', description: 'FUSE block device export') option('fuse_lseek', type : 'feature', value : 'auto', diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 680fa3f581..1afd373606 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -164,6 +164,7 @@ meson_options_help() { printf "%s\n" ' plugins TCG plugins via shared library loading' printf "%s\n" ' png PNG support with libpng' printf "%s\n" ' pvrdma Enable PVRDMA support' + printf "%s\n" ' qatzip QATzip compression support' printf "%s\n" ' qcow1 qcow1 image format support' printf "%s\n" ' qed qed image format support' printf "%s\n" ' qga-vss build QGA VSS support (broken with MinGW)' @@ -430,6 +431,8 @@ _meson_option_parse() { --prefix=*) quote_sh "-Dprefix=$2" ;; --enable-pvrdma) printf "%s" -Dpvrdma=enabled ;; --disable-pvrdma) printf "%s" -Dpvrdma=disabled ;; +--enable-qatzip) printf "%s" -Dqatzip=enabled ;; +--disable-qatzip) printf "%s" -Dqatzip=disabled ;; --enable-qcow1) printf "%s" -Dqcow1=enabled ;; --disable-qcow1) printf "%s" -Dqcow1=disabled ;; --enable-qed) printf "%s" -Dqed=enabled ;; -- 2.30.2
Re: [PATCH 5/8] vga: optimize horizontal pel panning in 256-color modes
On Sun, 31 Dec 2023, Paolo Bonzini wrote: Do not go through the panning buffer unless the address wraps in the middle of the line. Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 12 1 file changed, 12 insertions(+) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 29933562c45..60ddb27d946 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -265,6 +265,18 @@ static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d, palette = vga->last_palette; hpel = (hpel >> 1) & 3; + +/* For 256 color modes, we can adjust the source address and write directly + * to the destination, even if horizontal pel panning is active. However, + * the loop below assumes that the address does not wrap in the middle of a + * plane. If that happens... + */ +if (addr + (width >> 3) * 4 < VGA_VRAM_SIZE) { +addr += hpel * 4; +hpel = 0; +} + +/* ... use the panning buffer as in planar modes. */ if (hpel) { width += 8; d = vga->panning_buf; Is it possible to do these checks once in vga.c and instead of changing the return value of the draw functions pass panning_buf as d if needed? Maybe that way the draw funcs could be left unchanged? Regards, BALATON Zoltan
Re: [PATCH 3/8] vga: mask addresses in non-VESA modes to 256k
On Sun, 31 Dec 2023, Paolo Bonzini wrote: This allows setting the start address to a high value, and reading the bottom of the screen from the beginning of VRAM. Commander Keen 4 ("Goodbye, Galaxy!") relies on this behavior. Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 9 + hw/display/vga.c | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 10e9cfd40a0..83b9a15604a 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -108,7 +108,7 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -144,7 +144,7 @@ static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -177,7 +177,7 @@ static void vga_draw_line4(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -209,7 +209,7 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -242,6 +242,7 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, palette = vga->last_palette; width >>= 3; for(x = 0; x < width; x++) { +addr &= VGA_VRAM_SIZE - 1; PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); diff --git a/hw/display/vga.c b/hw/display/vga.c index 3bd357d72c2..b1660bdde67 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -47,6 +47,9 @@ bool have_vga = true; /* 16 state changes per vertical frame @60 Hz */ #define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60) +/* Address mask for non-VESA modes. */ +#define VGA_VRAM_SIZE 262144 (256 * KiB) maybe? + /* * Video Graphics Array (VGA) *
Re: [PATCH 1/8] vga: remove unused macros
On Sun, 31 Dec 2023, Paolo Bonzini wrote: Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 14 -- 1 file changed, 14 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 37557c3442a..18d966ecd3e 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -103,12 +103,6 @@ const uint8_t gr_mask[16] = { #define PAT(x) (x) #endif While at it you could also move this definiton dows to where it's used so it's clear where it's needed. Reviewed-by: BALATON Zoltan -#if HOST_BIG_ENDIAN -#define BIG 1 -#else -#define BIG 0 -#endif - #if HOST_BIG_ENDIAN #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) #else @@ -134,14 +128,6 @@ static const uint32_t mask16[16] = { PAT(0x), }; -#undef PAT - -#if HOST_BIG_ENDIAN -#define PAT(x) (x) -#else -#define PAT(x) cbswap_32(x) -#endif - static uint32_t expand4[256]; static uint16_t expand2[256]; static uint8_t expand4to8[16];
Re: [PATCH v2 1/1] docs: pcie: describe PCIe option ROMs
On 8/14/22 17:32, Heinrich Schuchardt wrote: Provide a descriptions of the options that control the emulation of option ROMS for PCIe devices. Signed-off-by: Heinrich Schuchardt --- v2: correct description of rombar property use romfile= to suppress option ROM loading --- docs/pcie.txt | 28 1 file changed, 28 insertions(+) diff --git a/docs/pcie.txt b/docs/pcie.txt index 89e3502075..b60f189bd4 100644 --- a/docs/pcie.txt +++ b/docs/pcie.txt @@ -292,6 +292,34 @@ PCI-PCI Bridge slots can be used for legacy PCI host devices. If you can see the "Express Endpoint" capability in the output, then the device is indeed PCI Express. +8. Option ROM += +PCIe devices may provide an option ROM. The following properties control the +emulation of the option ROM: + +``rombar`` (default: ``1``) + For vfio-pci devices a vendor and product ID based denylist exists which + controls if an available option ROM shall be probed. The 'rombar' option + allows to override this setting. The value is used as follows: + 0 = skip probing, 1 = force probing + +``romfile`` + Defines the name of the file to be loaded as option ROM. + The file size may neither exceed 2 GiB nor ``romsize``. + Some devices like virtio-net-pci define a default file name. + +``romsize`` (default: ``-1``) + Specifies the size of the option ROM in bytes. The value must be either + ``-1`` or a power of two. ``-1`` signifies unlimited size. + +Some QEMU PCIe devices like virtio-net-pci use an option ROM by default. In the +following example the option ROM of a virtio-net-pci device is disabled by +specifying an empty ``romfile`` property. This is useful for architectures where +QEMU does not supply an option ROM file. + +.. code-block:: console + +-device virtio-net-pci,netdev=eth1,mq=on,romfile= 7. Virtio devices = Hello Michael, hello Marcel, Unfortunately the patch was never reviewed. The patch is available at: https://lore.kernel.org/qemu-devel/20220814153220.2439468-1-heinrich.schucha...@canonical.com/ https://patchwork.kernel.org/project/qemu-devel/patch/20220814153220.2439468-1-heinrich.schucha...@canonical.com/ Best regards Heinrich
[PATCH] vfio/migration: Add helper function to set state or reset device
There are several places where failure in setting the device state leads to a device reset, which is done by setting ERROR as the recover state. Add a helper function that sets the device state and resets the device in case of failure. This will make the code cleaner and remove duplicate comments. Signed-off-by: Avihai Horon --- hw/vfio/migration.c | 41 + 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 28d422b39f..70e6b1a709 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -163,6 +163,19 @@ reset_device: return ret; } +/* + * Some device state transitions require resetting the device if they fail. + * This function sets the device in new_state and resets the device if that + * fails. Reset is done by using ERROR as the recover state. + */ +static int +vfio_migration_set_state_or_reset(VFIODevice *vbasedev, + enum vfio_device_mig_state new_state) +{ +return vfio_migration_set_state(vbasedev, new_state, +VFIO_DEVICE_STATE_ERROR); +} + static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, uint64_t data_size) { @@ -422,12 +435,7 @@ static void vfio_save_cleanup(void *opaque) * after migration has completed, so it won't increase downtime. */ if (migration->device_state == VFIO_DEVICE_STATE_STOP_COPY) { -/* - * If setting the device in STOP state fails, the device should be - * reset. To do so, use ERROR state as a recover state. - */ -vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_STOP, - VFIO_DEVICE_STATE_ERROR); +vfio_migration_set_state_or_reset(vbasedev, VFIO_DEVICE_STATE_STOP); } g_free(migration->data_buffer); @@ -699,12 +707,7 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running, VFIO_DEVICE_STATE_PRE_COPY_P2P : VFIO_DEVICE_STATE_RUNNING_P2P; -/* - * If setting the device in new_state fails, the device should be reset. - * To do so, use ERROR state as a recover state. - */ -ret = vfio_migration_set_state(vbasedev, new_state, - VFIO_DEVICE_STATE_ERROR); +ret = vfio_migration_set_state_or_reset(vbasedev, new_state); if (ret) { /* * Migration should be aborted in this case, but vm_state_notify() @@ -736,12 +739,7 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state) VFIO_DEVICE_STATE_STOP; } -/* - * If setting the device in new_state fails, the device should be reset. - * To do so, use ERROR state as a recover state. - */ -ret = vfio_migration_set_state(vbasedev, new_state, - VFIO_DEVICE_STATE_ERROR); +ret = vfio_migration_set_state_or_reset(vbasedev, new_state); if (ret) { /* * Migration should be aborted in this case, but vm_state_notify() @@ -770,12 +768,7 @@ static void vfio_migration_state_notifier(Notifier *notifier, void *data) case MIGRATION_STATUS_CANCELLING: case MIGRATION_STATUS_CANCELLED: case MIGRATION_STATUS_FAILED: -/* - * If setting the device in RUNNING state fails, the device should - * be reset. To do so, use ERROR state as a recover state. - */ -vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_RUNNING, - VFIO_DEVICE_STATE_ERROR); +vfio_migration_set_state_or_reset(vbasedev, VFIO_DEVICE_STATE_RUNNING); } } -- 2.26.3
[PATCH 0/8] vga: improve emulation fidelity
This implements horizontal pel panning, which is used by games such as the Commander Keen series, and also reimplements word and odd/even modes so that they work in graphics modes; this mostly fixes Jazz Jackrabbit's graphics. There are still some issues with Cirrus VGA, and also Keen expects the display parameters to be latched in ways that I don't fully understand and that seem to differ between Keen 1 (EGA) and 4 (VGA). So there is still a bit of tearing, but I have been sitting on these patches since the Christmas holidays of 2014, so let's flush this first part. Paolo Paolo Bonzini (8): vga: remove unused macros vga: introduce VGADisplayParams vga: mask addresses in non-VESA modes to 256k vga: implement horizontal pel panning in graphics modes vga: optimize horizontal pel panning in 256-color modes vga: reindent memory access code vga: use latches in odd/even mode too vga: sort-of implement word and double-word access modes hw/display/cirrus_vga.c | 28 +-- hw/display/vga-helpers.h | 121 +--- hw/display/vga.c | 418 +-- hw/display/vga_int.h | 18 +- hw/display/vga_regs.h| 4 + 5 files changed, 347 insertions(+), 242 deletions(-) -- 2.43.0
[PATCH 6/8] vga: reindent memory access code
The next patch will reuse latched memory access in text modes. Start with a patch that moves the latched access code out of the "if". Best reviewed with "git diff -b". Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 211 --- 1 file changed, 110 insertions(+), 101 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 2467f3f6c65..08ba5bb1118 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -832,37 +832,41 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) } if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { -/* chain 4 mode : simplest access */ +/* chain 4 mode : simplest access (but it should use the same + * algorithms as below; see e.g. vga_mem_writeb's plane mask check). + */ assert(addr < s->vram_size); -ret = s->vram_ptr[addr]; -} else if (s->gr[VGA_GFX_MODE] & 0x10) { +return s->vram_ptr[addr]; +} + +if (s->gr[VGA_GFX_MODE] & 0x10) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); addr = ((addr & ~1) << 1) | plane; if (addr >= s->vram_size) { return 0xff; } -ret = s->vram_ptr[addr]; -} else { -/* standard VGA latched access */ -if (addr * sizeof(uint32_t) >= s->vram_size) { -return 0xff; -} -s->latch = ((uint32_t *)s->vram_ptr)[addr]; - -if (!(s->gr[VGA_GFX_MODE] & 0x08)) { -/* read mode 0 */ -plane = s->gr[VGA_GFX_PLANE_READ]; -ret = GET_PLANE(s->latch, plane); -} else { -/* read mode 1 */ -ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) & -mask16[s->gr[VGA_GFX_COMPARE_MASK]]; -ret |= ret >> 16; -ret |= ret >> 8; -ret = (~ret) & 0xff; -} +return s->vram_ptr[addr]; } + +/* standard VGA latched access */ +plane = s->gr[VGA_GFX_PLANE_READ]; +if (addr * sizeof(uint32_t) >= s->vram_size) { +return 0xff; +} +s->latch = ((uint32_t *)s->vram_ptr)[addr]; +if (!(s->gr[VGA_GFX_MODE] & 0x08)) { +/* read mode 0 */ +ret = GET_PLANE(s->latch, plane); +} else { +/* read mode 1 */ +ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) & +mask16[s->gr[VGA_GFX_COMPARE_MASK]]; +ret |= ret >> 16; +ret |= ret >> 8; +ret = (~ret) & 0xff; +} + return ret; } @@ -912,7 +916,10 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) s->plane_updated |= mask; /* only used to detect font change */ memory_region_set_dirty(&s->vram, addr, 1); } -} else if (s->gr[VGA_GFX_MODE] & 0x10) { +return; +} + +if (s->gr[VGA_GFX_MODE] & 0x10) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); mask = (1 << plane); @@ -928,84 +935,86 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) s->plane_updated |= mask; /* only used to detect font change */ memory_region_set_dirty(&s->vram, addr, 1); } -} else { -/* standard VGA latched access */ -write_mode = s->gr[VGA_GFX_MODE] & 3; -switch(write_mode) { -default: -case 0: -/* rotate */ -b = s->gr[VGA_GFX_DATA_ROTATE] & 7; -val = ((val >> b) | (val << (8 - b))) & 0xff; -val |= val << 8; -val |= val << 16; - -/* apply set/reset mask */ -set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]]; -val = (val & ~set_mask) | -(mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask); -bit_mask = s->gr[VGA_GFX_BIT_MASK]; -break; -case 1: -val = s->latch; -goto do_write; -case 2: -val = mask16[val & 0x0f]; -bit_mask = s->gr[VGA_GFX_BIT_MASK]; -break; -case 3: -/* rotate */ -b = s->gr[VGA_GFX_DATA_ROTATE] & 7; -val = (val >> b) | (val << (8 - b)); - -bit_mask = s->gr[VGA_GFX_BIT_MASK] & val; -val = mask16[s->gr[VGA_GFX_SR_VALUE]]; -break; -} - -/* apply logical operation */ -func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3; -switch(func_select) { -case 0: -default: -/* nothing to do */ -break; -case 1: -/* and */ -val &= s->latch; -break; -case 2: -/* or */ -val |= s->latch; -break; -case 3: -/* xor */ -val ^= s->latch; -break; -} - -/* apply bit mask */ -bit_mask |= bit_mask << 8; -bit_mask
[PATCH 4/8] vga: implement horizontal pel panning in graphics modes
This implements smooth scrolling, as used for example by Commander Keen and Second Reality. Unfortunately, this is not enough to avoid tearing in Commander Keen, because sometimes the wrong start address is used for a frame. On real EGA, the panning register is sampled on every line, while the display start is latched for the next frame at the start of the vertical retrace. On real VGA, the panning register is also latched, but at the end of the vertical retrace. It looks like Keen exploits this by only waiting for horizontal retrace when setting the display start, but implementing it breaks the 256-color Keen games... Signed-off-by: Paolo Bonzini --- hw/display/cirrus_vga.c | 4 ++ hw/display/vga-helpers.h | 100 --- hw/display/vga.c | 36 -- hw/display/vga_int.h | 3 ++ 4 files changed, 111 insertions(+), 32 deletions(-) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index e6d2581d4eb..849eff43898 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -43,6 +43,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "ui/pixel_ops.h" +#include "vga_regs.h" #include "cirrus_vga_internal.h" #include "qom/object.h" #include "ui/console.h" @@ -1121,6 +1122,9 @@ static void cirrus_get_params(VGACommonState *s1, params->line_compare = s->vga.cr[0x18] | ((s->vga.cr[0x07] & 0x10) << 4) | ((s->vga.cr[0x09] & 0x40) << 3); + +params->hpel = s->vga.ar[VGA_ATC_PEL]; +params->hpel_split = s->vga.ar[VGA_ATC_MODE] & 0x20; } static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 83b9a15604a..29933562c45 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -98,14 +98,19 @@ static void vga_draw_glyph9(uint8_t *d, int linesize, /* * 4 color mode */ -static void vga_draw_line2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line2(VGACommonState *vga, uint8_t *d, +uint32_t addr, int width, int hpel) { uint32_t plane_mask, *palette, data, v; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; +hpel &= 7; +if (hpel) { +width += 8; +d = vga->panning_buf; +} width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -126,6 +131,7 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, d += 32; addr += 4; } +return hpel ? vga->panning_buf + 4 * hpel : NULL; } #define PUT_PIXEL2(d, n, v) \ @@ -134,14 +140,19 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, /* * 4 color mode, dup2 horizontal */ -static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line2d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t plane_mask, *palette, data, v; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; +hpel &= 7; +if (hpel) { +width += 8; +d = vga->panning_buf; +} width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -162,19 +173,25 @@ static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, d += 64; addr += 4; } +return hpel ? vga->panning_buf + 8 * hpel : NULL; } /* * 16 color mode */ -static void vga_draw_line4(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line4(VGACommonState *vga, uint8_t *d, +uint32_t addr, int width, int hpel) { uint32_t plane_mask, data, v, *palette; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; +hpel &= 7; +if (hpel) { +width += 8; +d = vga->panning_buf; +} width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -194,19 +211,25 @@ static void vga_draw_line4(VGACommonState *vga, uint8_t *d, d += 32; addr += 4; } +return hpel ? vga->panning_buf + 4 * hpel : NULL; } /* * 16 color mode, dup2 horizontal */ -static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line4d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t plane_mask, data, v, *palette; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; +hpel &= 7; +if (hpel
[PATCH 1/8] vga: remove unused macros
Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 14 -- 1 file changed, 14 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 37557c3442a..18d966ecd3e 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -103,12 +103,6 @@ const uint8_t gr_mask[16] = { #define PAT(x) (x) #endif -#if HOST_BIG_ENDIAN -#define BIG 1 -#else -#define BIG 0 -#endif - #if HOST_BIG_ENDIAN #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) #else @@ -134,14 +128,6 @@ static const uint32_t mask16[16] = { PAT(0x), }; -#undef PAT - -#if HOST_BIG_ENDIAN -#define PAT(x) (x) -#else -#define PAT(x) cbswap_32(x) -#endif - static uint32_t expand4[256]; static uint16_t expand2[256]; static uint8_t expand4to8[16]; -- 2.43.0
[PATCH 7/8] vga: use latches in odd/even mode too
Jazz Jackrabbit uses odd/even mode with 256-color graphics. This is probably so that it can do very fast blitting with a decent resolution (two pixels, compared to four pixels for "regular" mode X). Accesses still use all planes (reads go to the latches and the game uses read mode 1 so that the CPU always gets 0xFF; writes use the plane mask register because the game sets bit 2 of the sequencer's memory mode register). For this to work, QEMU needs to use the code for latched memory accesses in odd/even mode. The only difference between odd/even mode and "regular" planar mode is how the plane is computed in read mode 0, and how the planes are masked if the aforementioned bit 2 is reset. It is almost enough to fix the game. You also need to honor byte/word mode selection, which is done in the next patch. Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 40 +--- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 08ba5bb1118..731501cb7af 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -842,15 +842,12 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) if (s->gr[VGA_GFX_MODE] & 0x10) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); -addr = ((addr & ~1) << 1) | plane; -if (addr >= s->vram_size) { -return 0xff; -} -return s->vram_ptr[addr]; +addr >>= 1; +} else { +/* standard VGA latched access */ +plane = s->gr[VGA_GFX_PLANE_READ]; } -/* standard VGA latched access */ -plane = s->gr[VGA_GFX_PLANE_READ]; if (addr * sizeof(uint32_t) >= s->vram_size) { return 0xff; } @@ -903,11 +900,12 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) break; } +mask = sr(s, VGA_SEQ_PLANE_WRITE); if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { /* chain 4 mode : simplest access */ plane = addr & 3; -mask = (1 << plane); -if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) { +mask &= (1 << plane); +if (mask) { assert(addr < s->vram_size); s->vram_ptr[addr] = val; #ifdef DEBUG_VGA_MEM @@ -919,26 +917,14 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) return; } -if (s->gr[VGA_GFX_MODE] & 0x10) { -/* odd/even mode (aka text mode mapping) */ -plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); -mask = (1 << plane); -if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) { -addr = ((addr & ~1) << 1) | plane; -if (addr >= s->vram_size) { -return; -} -s->vram_ptr[addr] = val; -#ifdef DEBUG_VGA_MEM -printf("vga: odd/even: [0x" HWADDR_FMT_plx "]\n", addr); -#endif -s->plane_updated |= mask; /* only used to detect font change */ -memory_region_set_dirty(&s->vram, addr, 1); -} -return; +if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) { +mask &= (addr & 1) ? 0x0a : 0x05; } -mask = sr(s, VGA_SEQ_PLANE_WRITE); +if (s->gr[VGA_GFX_MODE] & 0x10) { +/* odd/even mode (aka text mode mapping) */ +addr >>= 1; +} /* standard VGA latched access */ write_mode = s->gr[VGA_GFX_MODE] & 3; -- 2.43.0
[PATCH 2/8] vga: introduce VGADisplayParams
The next patches will introduce more parameters that cause a full refresh. Instead of adding arguments to get_offsets and lines to update_basic_params, do everything through a struct. Signed-off-by: Paolo Bonzini --- hw/display/cirrus_vga.c | 24 +--- hw/display/vga.c| 82 + hw/display/vga_int.h| 15 3 files changed, 52 insertions(+), 69 deletions(-) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index b80f98b6c4c..e6d2581d4eb 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -798,9 +798,9 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) if (blit_is_unsafe(s, false)) return 0; -return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, -s->cirrus_blt_srcaddr - s->vga.start_addr, -s->cirrus_blt_width, s->cirrus_blt_height); +return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.params.start_addr, + s->cirrus_blt_srcaddr - s->vga.params.start_addr, + s->cirrus_blt_width, s->cirrus_blt_height); } /*** @@ -1101,30 +1101,26 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) * ***/ -static void cirrus_get_offsets(VGACommonState *s1, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare) +static void cirrus_get_params(VGACommonState *s1, + VGADisplayParams *params) { CirrusVGAState * s = container_of(s1, CirrusVGAState, vga); -uint32_t start_addr, line_offset, line_compare; +uint32_t line_offset; line_offset = s->vga.cr[0x13] | ((s->vga.cr[0x1b] & 0x10) << 4); line_offset <<= 3; -*pline_offset = line_offset; +params->line_offset = line_offset; -start_addr = (s->vga.cr[0x0c] << 8) +params->start_addr = (s->vga.cr[0x0c] << 8) | s->vga.cr[0x0d] | ((s->vga.cr[0x1b] & 0x01) << 16) | ((s->vga.cr[0x1b] & 0x0c) << 15) | ((s->vga.cr[0x1d] & 0x80) << 12); -*pstart_addr = start_addr; -line_compare = s->vga.cr[0x18] | +params->line_compare = s->vga.cr[0x18] | ((s->vga.cr[0x07] & 0x10) << 4) | ((s->vga.cr[0x09] & 0x40) << 3); -*pline_compare = line_compare; } static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) @@ -2925,7 +2921,7 @@ void cirrus_init_common(CirrusVGAState *s, Object *owner, s->linear_mmio_mask = s->real_vram_size - 256; s->vga.get_bpp = cirrus_get_bpp; -s->vga.get_offsets = cirrus_get_offsets; +s->vga.get_params = cirrus_get_params; s->vga.get_resolution = cirrus_get_resolution; s->vga.cursor_invalidate = cirrus_cursor_invalidate; s->vga.cursor_draw_line = cirrus_cursor_draw_line; diff --git a/hw/display/vga.c b/hw/display/vga.c index 18d966ecd3e..3bd357d72c2 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1059,52 +1059,40 @@ static int update_palette256(VGACommonState *s) return full_update; } -static void vga_get_offsets(VGACommonState *s, -uint32_t *pline_offset, -uint32_t *pstart_addr, -uint32_t *pline_compare) +static void vga_get_params(VGACommonState *s, + VGADisplayParams *params) { -uint32_t start_addr, line_offset, line_compare; - if (vbe_enabled(s)) { -line_offset = s->vbe_line_offset; -start_addr = s->vbe_start_addr; -line_compare = 65535; +params->line_offset = s->vbe_line_offset; +params->start_addr = s->vbe_start_addr; +params->line_compare = 65535; } else { /* compute line_offset in bytes */ -line_offset = s->cr[VGA_CRTC_OFFSET]; -line_offset <<= 3; +params->line_offset = s->cr[VGA_CRTC_OFFSET] << 3; /* starting address */ -start_addr = s->cr[VGA_CRTC_START_LO] | +params->start_addr = s->cr[VGA_CRTC_START_LO] | (s->cr[VGA_CRTC_START_HI] << 8); /* line compare */ -line_compare = s->cr[VGA_CRTC_LINE_COMPARE] | +params->line_compare = s->cr[VGA_CRTC_LINE_COMPARE] | ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) | ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3); } -*pline_offset = line_offset; -*pstart_addr = start_addr; -*pline_compare = line_compare; } /* update start_addr and line_offset. Return TRUE if modified */ static int update_basic_params(VGACommonState *s) { int full_update; -uint32_t start_addr, line_offset, line_compare; +VGADisplayParams current; full_update = 0; -s->get_offsets(s, &line_offset, &start_addr, &line_compare); +s->get_params(s, ¤t); -if (line_offset != s->line_offset || -
[PATCH 5/8] vga: optimize horizontal pel panning in 256-color modes
Do not go through the panning buffer unless the address wraps in the middle of the line. Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 12 1 file changed, 12 insertions(+) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 29933562c45..60ddb27d946 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -265,6 +265,18 @@ static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d, palette = vga->last_palette; hpel = (hpel >> 1) & 3; + +/* For 256 color modes, we can adjust the source address and write directly + * to the destination, even if horizontal pel panning is active. However, + * the loop below assumes that the address does not wrap in the middle of a + * plane. If that happens... + */ +if (addr + (width >> 3) * 4 < VGA_VRAM_SIZE) { +addr += hpel * 4; +hpel = 0; +} + +/* ... use the panning buffer as in planar modes. */ if (hpel) { width += 8; d = vga->panning_buf; -- 2.43.0
[PATCH 8/8] vga: sort-of implement word and double-word access modes
Jazz Jackrabbit has a very unusual VGA setup, where it uses odd/even mode with 256-color graphics. Probably, it wants to use fast VRAM-to-VRAM copies without having to store 4 copies of the sprites as needed in mode X, one for each mod-4 alignment; odd/even mode simplifies the code a lot if it's okay to place on a 160-pixels horizontal grid. At the same time, because it wants to use double buffering (a la "mode X") it uses byte mode, not word mode as is the case in text modes. In order to implement the combination of odd/even mode (plane number comes from bit 0 of the address) and byte mode (use all bytes of VRAM, whereas word mode only uses bytes 0, 2, 4,... on each of the four planes), we need to separate the effect on the plane number from the effect on the address. Implementing the modes properly is a mess in QEMU, because it would change the layout of VRAM and break migration. As an approximation, shift right when the CPU accesses memory instead of shifting left when the CRT controller reads it. A hack is needed in order to write font data properly (see comment in the code), but it works well enough for the game. Because doubleword and chain4 modes are now independent, chain4 does not assert anymore that the address is in range. Instead it just returns all ones and discards writes, like other modes. Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 90 +++ hw/display/vga_regs.h | 4 ++ 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 731501cb7af..02b250ec0e6 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -832,25 +832,40 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) } if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { -/* chain 4 mode : simplest access (but it should use the same - * algorithms as below; see e.g. vga_mem_writeb's plane mask check). - */ -assert(addr < s->vram_size); -return s->vram_ptr[addr]; -} - -if (s->gr[VGA_GFX_MODE] & 0x10) { +/* chain4 mode */ +plane = addr & 3; +addr &= ~3; +} else if (s->gr[VGA_GFX_MODE] & VGA_GR05_HOST_ODD_EVEN) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); -addr >>= 1; } else { /* standard VGA latched access */ plane = s->gr[VGA_GFX_PLANE_READ]; } +if (s->gr[VGA_GFX_MISC] & VGA_GR06_CHAIN_ODD_EVEN) { +addr &= ~1; +} + +/* Doubleword/word mode. See comment in vga_mem_writeb */ +if (s->cr[VGA_CRTC_UNDERLINE] & VGA_CR14_DW) { +addr >>= 2; +} else if ((s->gr[VGA_GFX_MODE] & VGA_GR05_HOST_ODD_EVEN) && + (s->cr[VGA_CRTC_MODE] & VGA_CR17_WORD_BYTE) == 0) { +addr >>= 1; +} + if (addr * sizeof(uint32_t) >= s->vram_size) { return 0xff; } + +if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) { +/* chain 4 mode: simplified access (but it should use the same + * algorithms as below, see e.g. vga_mem_writeb's plane mask check). + */ +return s->vram_ptr[(addr << 2) | plane]; +} + s->latch = ((uint32_t *)s->vram_ptr)[addr]; if (!(s->gr[VGA_GFX_MODE] & 0x08)) { /* read mode 0 */ @@ -870,8 +885,9 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) /* called for accesses between 0xa and 0xc */ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) { -int memory_map_mode, plane, write_mode, b, func_select, mask; +int memory_map_mode, write_mode, b, func_select, mask; uint32_t write_mask, bit_mask, set_mask; +int plane = 0; #ifdef DEBUG_VGA_MEM printf("vga: [0x" HWADDR_FMT_plx "] = 0x%02x\n", addr, val); @@ -905,9 +921,47 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) /* chain 4 mode : simplest access */ plane = addr & 3; mask &= (1 << plane); +addr &= ~3; +} else { +if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) { +mask &= (addr & 1) ? 0x0a : 0x05; +} +} + +if (s->gr[VGA_GFX_MISC] & VGA_GR06_CHAIN_ODD_EVEN) { +addr &= ~1; +} + +/* Doubleword/word mode. These should be honored when displaying, + * not when reading/writing to memory! For example, chain4 modes + * use double-word mode and, on real hardware, would fetch bytes + * 0,1,2,3, 16,17,18,19, 32,33,34,35, etc. Text modes use word + * mode and, on real hardware, would fetch bytes 0,1, 8,9, etc. + * + * QEMU instead shifted addresses on memory accesses because it + * allows more optimizations (e.g. chain4_alias) and simplifies + * the draw_line handlers. Unfortunately, there is one case where + * the difference shows. When fetching font data, accesses are + * always in consecutive bytes, even if the text/attribute pairs + * are done i
[PATCH 3/8] vga: mask addresses in non-VESA modes to 256k
This allows setting the start address to a high value, and reading the bottom of the screen from the beginning of VRAM. Commander Keen 4 ("Goodbye, Galaxy!") relies on this behavior. Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 9 + hw/display/vga.c | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 10e9cfd40a0..83b9a15604a 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -108,7 +108,7 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -144,7 +144,7 @@ static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -177,7 +177,7 @@ static void vga_draw_line4(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -209,7 +209,7 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { -data = vga_read_dword_le(vga, addr); +data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -242,6 +242,7 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, palette = vga->last_palette; width >>= 3; for(x = 0; x < width; x++) { +addr &= VGA_VRAM_SIZE - 1; PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); diff --git a/hw/display/vga.c b/hw/display/vga.c index 3bd357d72c2..b1660bdde67 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -47,6 +47,9 @@ bool have_vga = true; /* 16 state changes per vertical frame @60 Hz */ #define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60) +/* Address mask for non-VESA modes. */ +#define VGA_VRAM_SIZE 262144 + /* * Video Graphics Array (VGA) * -- 2.43.0
[PATCH 00/11] migration: Misc cleanups and fixes
Hi, This series contains misc cleanups and fixes in migration code that I noticed while going over the code. Thanks. Avihai Horon (11): migration: Remove migrate_max_downtime() declaration migration: Remove nulling of hostname in migrate_init() migration: Refactor migration_incoming_setup() migration: Remove errp parameter in migration_fd_process_incoming() migration/multifd: Fix error message in multifd_recv_initial_packet() migration/multifd: Simplify multifd_channel_connect() if else statement migration/multifd: Fix leaking of Error in TLS error flow migration/multifd: Remove error_setg() in migration_ioc_process_incoming() migration: Fix migration_channel_read_peek() error path migration: Remove unnecessary usage of local Error migration/multifd: Remove unnecessary usage of local Error migration/migration.h | 4 +--- migration/channel.c | 9 ++--- migration/migration.c | 27 ++- migration/multifd.c | 27 --- migration/rdma.c | 6 +- 5 files changed, 26 insertions(+), 47 deletions(-) -- 2.26.3
[PATCH 03/11] migration: Refactor migration_incoming_setup()
Commit 6720c2b32725 ("migration: check magic value for deciding the mapping of channels") extracted the only code that could fail in migration_incoming_setup(). Now migration_incoming_setup() can't fail, so refactor it to return void and remove errp parameter. Signed-off-by: Avihai Horon --- migration/migration.c | 15 +++ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 1e25d7966f..55d77572d8 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -724,11 +724,8 @@ fail: /** * migration_incoming_setup: Setup incoming migration * @f: file for main migration channel - * @errp: where to put errors - * - * Returns: %true on success, %false on error. */ -static bool migration_incoming_setup(QEMUFile *f, Error **errp) +static void migration_incoming_setup(QEMUFile *f) { MigrationIncomingState *mis = migration_incoming_get_current(); @@ -736,7 +733,6 @@ static bool migration_incoming_setup(QEMUFile *f, Error **errp) mis->from_src_file = f; } qemu_file_set_blocking(f, false); -return true; } void migration_incoming_process(void) @@ -780,9 +776,7 @@ static bool postcopy_try_recover(void) void migration_fd_process_incoming(QEMUFile *f, Error **errp) { -if (!migration_incoming_setup(f, errp)) { -return; -} +migration_incoming_setup(f); if (postcopy_try_recover()) { return; } @@ -855,10 +849,7 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) if (default_channel) { f = qemu_file_new_input(ioc); - -if (!migration_incoming_setup(f, errp)) { -return; -} +migration_incoming_setup(f); } else { /* Multiple connections */ assert(migration_needs_multiple_sockets()); -- 2.26.3
[PATCH 01/11] migration: Remove migrate_max_downtime() declaration
migrate_max_downtime() has been removed long ago, but its declaration was mistakenly left. Remove it. Signed-off-by: Avihai Horon --- migration/migration.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/migration/migration.h b/migration/migration.h index cf2c9c88e0..b3c9288c38 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -480,8 +480,6 @@ void migration_incoming_process(void); bool migration_has_all_channels(void); -uint64_t migrate_max_downtime(void); - void migrate_set_error(MigrationState *s, const Error *error); bool migrate_has_error(MigrationState *s); -- 2.26.3
[PATCH 09/11] migration: Fix migration_channel_read_peek() error path
migration_channel_read_peek() calls qio_channel_readv_full() and handles both cases of return value == 0 and return value < 0 the same way, by calling error_setg() with errp. However, if return value < 0, errp is already set, so calling error_setg() with errp will lead to an assert. Fix it by handling these cases separately, calling error_setg() with errp only in return value == 0 case. Fixes: 6720c2b32725 ("migration: check magic value for deciding the mapping of channels") Signed-off-by: Avihai Horon --- migration/channel.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/migration/channel.c b/migration/channel.c index ca3319a309..f9de064f3b 100644 --- a/migration/channel.c +++ b/migration/channel.c @@ -117,9 +117,12 @@ int migration_channel_read_peek(QIOChannel *ioc, len = qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, QIO_CHANNEL_READ_FLAG_MSG_PEEK, errp); -if (len <= 0 && len != QIO_CHANNEL_ERR_BLOCK) { -error_setg(errp, - "Failed to peek at channel"); +if (len < 0 && len != QIO_CHANNEL_ERR_BLOCK) { +return -1; +} + +if (len == 0) { +error_setg(errp, "Failed to peek at channel"); return -1; } -- 2.26.3
[PATCH 02/11] migration: Remove nulling of hostname in migrate_init()
MigrationState->hostname is set to NULL in migrate_init(). This is redundant because it is already freed and set to NULL in migrade_fd_cleanup(). Remove it. Signed-off-by: Avihai Horon --- migration/migration.c | 1 - 1 file changed, 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c index 3ce04b2aaf..1e25d7966f 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1588,7 +1588,6 @@ int migrate_init(MigrationState *s, Error **errp) s->migration_thread_running = false; error_free(s->error); s->error = NULL; -s->hostname = NULL; s->vmdesc = NULL; migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); -- 2.26.3
[PATCH 07/11] migration/multifd: Fix leaking of Error in TLS error flow
If there is an error in multifd TLS handshake task, multifd_tls_outgoing_handshake() retrieves the error with qio_task_propagate_error() but never frees it. Fix it by freeing the obtained Error. In addition, the error is not reported at all, so report it with migrate_set_error(). Fixes: 29647140157a ("migration/tls: add support for multifd tls-handshake") Signed-off-by: Avihai Horon --- migration/multifd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/migration/multifd.c b/migration/multifd.c index 55d5fd55f8..9ac24866ad 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -787,6 +787,7 @@ static void multifd_tls_outgoing_handshake(QIOTask *task, trace_multifd_tls_outgoing_handshake_error(ioc, error_get_pretty(err)); +migrate_set_error(migrate_get_current(), err); /* * Error happen, mark multifd_send_thread status as 'quit' although it * is not created, and then tell who pay attention to me. @@ -794,6 +795,7 @@ static void multifd_tls_outgoing_handshake(QIOTask *task, p->quit = true; qemu_sem_post(&multifd_send_state->channels_ready); qemu_sem_post(&p->sem_sync); +error_free(err); } static void *multifd_tls_handshake_thread(void *opaque) -- 2.26.3
[PATCH 05/11] migration/multifd: Fix error message in multifd_recv_initial_packet()
In multifd_recv_initial_packet(), if MultiFDInit_t->id is greater than the configured number of multifd channels, an irrelevant error message about multifd version is printed. Change the error message to a relevant one about the channel id. Signed-off-by: Avihai Horon --- migration/multifd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/multifd.c b/migration/multifd.c index 409460684f..a6204fc72f 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -228,8 +228,8 @@ static int multifd_recv_initial_packet(QIOChannel *c, Error **errp) } if (msg.id > migrate_multifd_channels()) { -error_setg(errp, "multifd: received channel version %u " - "expected %u", msg.version, MULTIFD_VERSION); +error_setg(errp, "multifd: received channel id %u is greater than " + "number of channels %u", msg.id, migrate_multifd_channels()); return -1; } -- 2.26.3
[PATCH 11/11] migration/multifd: Remove unnecessary usage of local Error
According to Error API, usage of ERRP_GUARD() or a local Error instead of errp is needed if errp is passed to void functions, where it is later dereferenced to see if an error occurred. There are several places in multifd.c that use local Error although it is not needed. Change these places to use errp directly. Signed-off-by: Avihai Horon --- migration/multifd.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/migration/multifd.c b/migration/multifd.c index 9ac24866ad..9f353aecfa 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -951,12 +951,10 @@ int multifd_save_setup(Error **errp) for (i = 0; i < thread_count; i++) { MultiFDSendParams *p = &multifd_send_state->params[i]; -Error *local_err = NULL; int ret; -ret = multifd_send_state->ops->send_setup(p, &local_err); +ret = multifd_send_state->ops->send_setup(p, errp); if (ret) { -error_propagate(errp, local_err); return ret; } } @@ -1195,12 +1193,10 @@ int multifd_load_setup(Error **errp) for (i = 0; i < thread_count; i++) { MultiFDRecvParams *p = &multifd_recv_state->params[i]; -Error *local_err = NULL; int ret; -ret = multifd_recv_state->ops->recv_setup(p, &local_err); +ret = multifd_recv_state->ops->recv_setup(p, errp); if (ret) { -error_propagate(errp, local_err); return ret; } } -- 2.26.3
[PATCH 08/11] migration/multifd: Remove error_setg() in migration_ioc_process_incoming()
If multifd_load_setup() fails in migration_ioc_process_incoming(), error_setg() is called with errp. This will lead to an assert because in that case errp already contains an error. Fix it by removing the redundant error_setg(). Fixes: 6720c2b32725 ("migration: check magic value for deciding the mapping of channels") Signed-off-by: Avihai Horon --- migration/migration.c | 1 - 1 file changed, 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c index 732e3dadd9..b0c3b4c23a 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -843,7 +843,6 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) } if (multifd_load_setup(errp) != 0) { -error_setg(errp, "Failed to setup multifd channels"); return; } -- 2.26.3
[PATCH 04/11] migration: Remove errp parameter in migration_fd_process_incoming()
Errp parameter in migration_fd_process_incoming() is unused. Remove it. Signed-off-by: Avihai Horon --- migration/migration.h | 2 +- migration/migration.c | 2 +- migration/rdma.c | 6 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/migration/migration.h b/migration/migration.h index b3c9288c38..17972dac34 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -474,7 +474,7 @@ struct MigrationState { void migrate_set_state(int *state, int old_state, int new_state); -void migration_fd_process_incoming(QEMUFile *f, Error **errp); +void migration_fd_process_incoming(QEMUFile *f); void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp); void migration_incoming_process(void); diff --git a/migration/migration.c b/migration/migration.c index 55d77572d8..732e3dadd9 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -774,7 +774,7 @@ static bool postcopy_try_recover(void) return false; } -void migration_fd_process_incoming(QEMUFile *f, Error **errp) +void migration_fd_process_incoming(QEMUFile *f) { migration_incoming_setup(f); if (postcopy_try_recover()) { diff --git a/migration/rdma.c b/migration/rdma.c index 04debab5d9..94c0f871f0 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -4035,7 +4035,6 @@ static void rdma_accept_incoming_migration(void *opaque) { RDMAContext *rdma = opaque; QEMUFile *f; -Error *local_err = NULL; trace_qemu_rdma_accept_incoming_migration(); if (qemu_rdma_accept(rdma) < 0) { @@ -4057,10 +4056,7 @@ static void rdma_accept_incoming_migration(void *opaque) } rdma->migration_started_on_destination = 1; -migration_fd_process_incoming(f, &local_err); -if (local_err) { -error_reportf_err(local_err, "RDMA ERROR:"); -} +migration_fd_process_incoming(f); } void rdma_start_incoming_migration(InetSocketAddress *host_port, -- 2.26.3
[PATCH 10/11] migration: Remove unnecessary usage of local Error
According to Error API, usage of ERRP_GUARD() or a local Error instead of errp is needed if errp is passed to void functions, where it is later dereferenced to see if an error occurred. There are several places in migration.c that use local Error although it is not needed. Change these places to use errp directly. Signed-off-by: Avihai Horon --- migration/migration.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index b0c3b4c23a..fc7f4fd263 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -830,10 +830,9 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) * issue is not possible. */ ret = migration_channel_read_peek(ioc, (void *)&channel_magic, - sizeof(channel_magic), &local_err); + sizeof(channel_magic), errp); if (ret != 0) { -error_propagate(errp, local_err); return; } @@ -1825,8 +1824,6 @@ bool migration_is_blocked(Error **errp) static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, bool resume, Error **errp) { -Error *local_err = NULL; - if (blk_inc) { warn_report("parameter 'inc' is deprecated;" " use blockdev-mirror with NBD instead"); @@ -1896,8 +1893,7 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, "current migration capabilities"); return false; } -if (!migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, true, &local_err)) { -error_propagate(errp, local_err); +if (!migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, true, errp)) { return false; } s->must_remove_block_options = true; -- 2.26.3
[PATCH 06/11] migration/multifd: Simplify multifd_channel_connect() if else statement
The else branch in multifd_channel_connect() is redundant because when the if branch is taken the function returns. Simplify the code by removing the else branch. Signed-off-by: Avihai Horon --- migration/multifd.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/migration/multifd.c b/migration/multifd.c index a6204fc72f..55d5fd55f8 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -847,14 +847,13 @@ static bool multifd_channel_connect(MultiFDSendParams *p, * so we mustn't call multifd_send_thread until then */ return multifd_tls_channel_connect(p, ioc, errp); - -} else { -migration_ioc_register_yank(ioc); -p->registered_yank = true; -p->c = ioc; -qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, - QEMU_THREAD_JOINABLE); } + +migration_ioc_register_yank(ioc); +p->registered_yank = true; +p->c = ioc; +qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, + QEMU_THREAD_JOINABLE); return true; } -- 2.26.3
[PULL 32/46] meson: move program checks together
Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- meson.build | 107 +++- 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/meson.build b/meson.build index c437e9f55e6..3a1f4cbb90f 100644 --- a/meson.build +++ b/meson.build @@ -19,21 +19,8 @@ ss = import('sourceset') fs = import('fs') targetos = host_machine.system() -sh = find_program('sh') config_host = keyval.load(meson.current_build_dir() / 'config-host.mak') -cc = meson.get_compiler('c') -all_languages = ['c'] -if targetos == 'windows' and add_languages('cpp', required: false, native: false) - all_languages += ['cpp'] - cxx = meson.get_compiler('cpp') -endif -if targetos == 'darwin' and \ - add_languages('objc', required: get_option('cocoa'), native: false) - all_languages += ['objc'] - objc = meson.get_compiler('objc') -endif - # Temporary directory used for files created while # configure runs. Since it is in the build directory # we can safely blow away any previous version of it @@ -65,6 +52,62 @@ supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64' cpu = host_machine.cpu_family() target_dirs = config_host['TARGET_DIRS'].split() + + +# Programs # + + +sh = find_program('sh') +python = import('python').find_installation() + +cc = meson.get_compiler('c') +all_languages = ['c'] +if targetos == 'windows' and add_languages('cpp', required: false, native: false) + all_languages += ['cpp'] + cxx = meson.get_compiler('cpp') +endif +if targetos == 'darwin' and \ + add_languages('objc', required: get_option('cocoa'), native: false) + all_languages += ['objc'] + objc = meson.get_compiler('objc') +endif + +dtrace = not_found +stap = not_found +if 'dtrace' in get_option('trace_backends') + dtrace = find_program('dtrace', required: true) + stap = find_program('stap', required: false) + if stap.found() +# Workaround to avoid dtrace(1) producing a file with 'hidden' symbol +# visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility +# instead. QEMU --enable-modules depends on this because the SystemTap +# semaphores are linked into the main binary and not the module's shared +# object. +add_global_arguments('-DSTAP_SDT_V2', + native: false, language: all_languages) + endif +endif + +if get_option('iasl') == '' + iasl = find_program('iasl', required: false) +else + iasl = find_program(get_option('iasl'), required: true) +endif + +edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ] +unpack_edk2_blobs = false +foreach target : edk2_targets + if target in target_dirs +bzip2 = find_program('bzip2', required: get_option('install_blobs')) +unpack_edk2_blobs = bzip2.found() +break + endif +endforeach + +# +# Option validation # +# + have_linux_user = false have_bsd_user = false have_system = false @@ -90,12 +133,6 @@ enable_modules = get_option('modules') \ .allowed() have_block = have_system or have_tools - -# Programs # - - -python = import('python').find_installation() - ### # Variables for host and accelerators # ### @@ -167,38 +204,6 @@ if targetos != 'darwin' modular_tcg = ['i386-softmmu', 'x86_64-softmmu'] endif -edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ] -unpack_edk2_blobs = false -foreach target : edk2_targets - if target in target_dirs -bzip2 = find_program('bzip2', required: get_option('install_blobs')) -unpack_edk2_blobs = bzip2.found() -break - endif -endforeach - -dtrace = not_found -stap = not_found -if 'dtrace' in get_option('trace_backends') - dtrace = find_program('dtrace', required: true) - stap = find_program('stap', required: false) - if stap.found() -# Workaround to avoid dtrace(1) producing a file with 'hidden' symbol -# visibility. Define STAP_SDT_V2 to produce 'default' symbol visibility -# instead. QEMU --enable-modules depends on this because the SystemTap -# semaphores are linked into the main binary and not the module's shared -# object. -add_global_arguments('-DSTAP_SDT_V2', - native: false, language: all_languages) - endif -endif - -if get_option('iasl') == '' - iasl = find_program('iasl', required: false) -else - iasl = find_program(get_option('iasl'), required: true) -endif - ## # Compiler flags # ## -- 2.43.0
[PULL 22/46] target/i386: implement CMPccXADD
The main difficulty here is that a page fault when writing to the destination must not overwrite the flags. Therefore, the flags computation must be inlined instead of using gen_jcc1*. For simplicity, I am using an unconditional cmpxchg operation, that becomes a NOP if the comparison fails. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/cpu.c| 2 +- target/i386/tcg/decode-new.c.inc | 25 target/i386/tcg/decode-new.h | 1 + target/i386/tcg/emit.c.inc | 104 +++ target/i386/tcg/translate.c | 2 + 5 files changed, 133 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 95d5f16cd5e..fd47ee7defb 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -738,7 +738,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, #define TCG_7_0_EDX_FEATURES (CPUID_7_0_EDX_FSRM | CPUID_7_0_EDX_KERNEL_FEATURES) #define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \ - CPUID_7_1_EAX_FSRC) + CPUID_7_1_EAX_FSRC | CPUID_7_1_EAX_CMPCCXADD) #define TCG_7_1_EDX_FEATURES 0 #define TCG_7_2_EDX_FEATURES 0 #define TCG_APM_FEATURES 0 diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 717d7307722..426c4594120 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -538,6 +538,28 @@ static const X86OpEntry opcodes_0F38_00toEF[240] = { [0xdd] = X86_OP_ENTRY3(VAESENCLAST, V,x, H,x, W,x, vex4 cpuid(AES) p_66), [0xde] = X86_OP_ENTRY3(VAESDEC, V,x, H,x, W,x, vex4 cpuid(AES) p_66), [0xdf] = X86_OP_ENTRY3(VAESDECLAST, V,x, H,x, W,x, vex4 cpuid(AES) p_66), + +/* + * REG selects srcdest2 operand, VEX. selects src3. VEX class not found + * in manual, assumed to be 13 from the VEX.L0 constraint. + */ +[0xe0] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe1] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe2] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe3] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe4] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe5] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe6] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe7] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), + +[0xe8] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xe9] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xea] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xeb] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xec] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xed] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xee] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), +[0xef] = X86_OP_ENTRY3(CMPccXADD, M,y, G,y, B,y, vex13 xchg chk(o64) cpuid(CMPCCXADD) p_66), }; /* five rows for no prefix, 66, F3, F2, 66+F2 */ @@ -1503,6 +1525,9 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid) return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_AVX2); case X86_FEAT_SHA_NI: return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SHA_NI); + +case X86_FEAT_CMPCCXADD: +return (s->cpuid_7_1_eax_features & CPUID_7_1_EAX_CMPCCXADD); } g_assert_not_reached(); } diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 25220fc4362..15e6bfef4b1 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -104,6 +104,7 @@ typedef enum X86CPUIDFeature { X86_FEAT_AVX2, X86_FEAT_BMI1, X86_FEAT_BMI2, +X86_FEAT_CMPCCXADD, X86_FEAT_F16C, X86_FEAT_FMA, X86_FEAT_MOVBE, diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index fd120e7b9b4..6bcf88ecd71 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1190,6 +1190,110 @@ static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) prepare_update2_cc(decode, s, CC_OP_BMILGB + ot); } +static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) +{ +TCGLabel *label_top = gen_new_label(); +TCGLabel *label_bottom = gen_new_label(); +TCGv oldv = tcg_temp_new(); +TCGv newv = tcg_temp_new(); +TCGv cmpv = tcg_temp_new()
[PULL 40/46] meson: remove OS definitions from config_targetos
CONFIG_DARWIN, CONFIG_LINUX and CONFIG_BSD are used in some rules, but only CONFIG_LINUX has substantial use. Convert them all to if...endif. Signed-off-by: Paolo Bonzini --- accel/tcg/meson.build | 4 +++- backends/meson.build | 4 +++- block/meson.build | 4 +++- fsdev/meson.build | 5 +++-- hw/9pfs/meson.build| 7 +-- hw/display/meson.build | 7 +-- hw/ppc/meson.build | 8 +--- hw/usb/meson.build | 4 +++- meson.build| 8 net/can/meson.build| 4 +++- qga/meson.build| 11 +-- scsi/meson.build | 8 +--- system/meson.build | 4 +++- ui/meson.build | 7 +++ util/meson.build | 14 -- 15 files changed, 57 insertions(+), 42 deletions(-) diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build index 8783edd06ee..1dad6bbbfbd 100644 --- a/accel/tcg/meson.build +++ b/accel/tcg/meson.build @@ -17,7 +17,9 @@ if get_option('plugins') tcg_ss.add(files('plugin-gen.c')) endif tcg_ss.add(when: libdw, if_true: files('debuginfo.c')) -tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c')) +if targetos == 'linux' + tcg_ss.add(files('perf.c')) +endif specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss) specific_ss.add(when: ['CONFIG_SYSTEM_ONLY', 'CONFIG_TCG'], if_true: files( diff --git a/backends/meson.build b/backends/meson.build index 9a5cea480d1..248ce4923c6 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -12,7 +12,9 @@ system_ss.add([files( system_ss.add(when: 'CONFIG_POSIX', if_true: files('rng-random.c')) system_ss.add(when: 'CONFIG_POSIX', if_true: files('hostmem-file.c')) -system_ss.add(when: 'CONFIG_LINUX', if_true: files('hostmem-memfd.c')) +if targetos == 'linux' + system_ss.add(files('hostmem-memfd.c')) +endif if keyutils.found() system_ss.add(keyutils, files('cryptodev-lkcf.c')) endif diff --git a/block/meson.build b/block/meson.build index 59ff6d380c0..7faed96c1e7 100644 --- a/block/meson.build +++ b/block/meson.build @@ -91,7 +91,9 @@ endif block_ss.add(when: 'CONFIG_WIN32', if_true: files('file-win32.c', 'win32-aio.c')) block_ss.add(when: 'CONFIG_POSIX', if_true: [files('file-posix.c'), coref, iokit]) block_ss.add(when: libiscsi, if_true: files('iscsi-opts.c')) -block_ss.add(when: 'CONFIG_LINUX', if_true: files('nvme.c')) +if targetos == 'linux' + block_ss.add(files('nvme.c')) +endif if get_option('replication').allowed() block_ss.add(files('replication.c')) endif diff --git a/fsdev/meson.build b/fsdev/meson.build index 1bec0659245..c76347615df 100644 --- a/fsdev/meson.build +++ b/fsdev/meson.build @@ -6,8 +6,9 @@ fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files( '9p-marshal.c', 'qemu-fsdev.c', ), if_false: files('qemu-fsdev-dummy.c')) -system_ss.add_all(when: 'CONFIG_LINUX', if_true: fsdev_ss) -system_ss.add_all(when: 'CONFIG_DARWIN', if_true: fsdev_ss) +if targetos in ['linux', 'darwin'] + system_ss.add_all(fsdev_ss) +endif if have_virtfs_proxy_helper executable('virtfs-proxy-helper', diff --git a/hw/9pfs/meson.build b/hw/9pfs/meson.build index 2944ea63c38..3eee7c268a9 100644 --- a/hw/9pfs/meson.build +++ b/hw/9pfs/meson.build @@ -13,8 +13,11 @@ fs_ss.add(files( 'coth.c', 'coxattr.c', )) -fs_ss.add(when: 'CONFIG_LINUX', if_true: files('9p-util-linux.c')) -fs_ss.add(when: 'CONFIG_DARWIN', if_true: files('9p-util-darwin.c')) +if targetos == 'darwin' + fs_ss.add(files('9p-util-darwin.c')) +elif targetos == 'linux' + fs_ss.add(files('9p-util-linux.c')) +endif fs_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-9p-backend.c')) system_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss) diff --git a/hw/display/meson.build b/hw/display/meson.build index 344dfe3d8c2..02b0044c9ec 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -69,8 +69,11 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU') virtio_gpu_ss = ss.source_set() virtio_gpu_ss.add(when: 'CONFIG_VIRTIO_GPU', if_true: [files('virtio-gpu-base.c', 'virtio-gpu.c'), pixman]) - virtio_gpu_ss.add(when: 'CONFIG_LINUX', if_true: files('virtio-gpu-udmabuf.c'), - if_false: files('virtio-gpu-udmabuf-stubs.c')) + if targetos == 'linux' +virtio_gpu_ss.add(files('virtio-gpu-udmabuf.c')) + else +virtio_gpu_ss.add(files('virtio-gpu-udmabuf-stubs.c')) + endif virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true: files('vhost-user-gpu.c')) hw_display_modules += {'virtio-gpu': virtio_gpu_ss} diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index ea44856d43b..3dedcf3043d 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -34,9 +34,11 @@ ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_TCG'], if_true: files( 'spapr_softmmu.c', )) ppc_ss.add(when: 'CONFIG_SPAPR_RNG', if_true: files('spapr_rng.c')) -ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_LINUX'], if_true: files( - 'spapr_pci_vfio.c', -)) +if targetos == 'linux' + pp
[PULL 38/46] meson: move subdirs to "Collect sources" section
Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- meson.build | 66 ++--- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/meson.build b/meson.build index 151db21c038..21335055ef8 100644 --- a/meson.build +++ b/meson.build @@ -3257,39 +3257,6 @@ foreach d : hx_headers endforeach genh += hxdep -### -# Collect sources # -### - -authz_ss = ss.source_set() -blockdev_ss = ss.source_set() -block_ss = ss.source_set() -chardev_ss = ss.source_set() -common_ss = ss.source_set() -crypto_ss = ss.source_set() -hwcore_ss = ss.source_set() -io_ss = ss.source_set() -qmp_ss = ss.source_set() -qom_ss = ss.source_set() -system_ss = ss.source_set() -specific_fuzz_ss = ss.source_set() -specific_ss = ss.source_set() -stub_ss = ss.source_set() -trace_ss = ss.source_set() -user_ss = ss.source_set() -util_ss = ss.source_set() - -# accel modules -qtest_module_ss = ss.source_set() -tcg_module_ss = ss.source_set() - -modules = {} -target_modules = {} -hw_arch = {} -target_arch = {} -target_system_arch = {} -target_user_arch = {} - ### # Trace files # ### @@ -3404,6 +3371,39 @@ if have_system or have_user ] endif +### +# Collect sources # +### + +authz_ss = ss.source_set() +blockdev_ss = ss.source_set() +block_ss = ss.source_set() +chardev_ss = ss.source_set() +common_ss = ss.source_set() +crypto_ss = ss.source_set() +hwcore_ss = ss.source_set() +io_ss = ss.source_set() +qmp_ss = ss.source_set() +qom_ss = ss.source_set() +system_ss = ss.source_set() +specific_fuzz_ss = ss.source_set() +specific_ss = ss.source_set() +stub_ss = ss.source_set() +trace_ss = ss.source_set() +user_ss = ss.source_set() +util_ss = ss.source_set() + +# accel modules +qtest_module_ss = ss.source_set() +tcg_module_ss = ss.source_set() + +modules = {} +target_modules = {} +hw_arch = {} +target_arch = {} +target_system_arch = {} +target_user_arch = {} + # NOTE: the trace/ subdirectory needs the qapi_trace_events variable # that is filled in by qapi/. subdir('qapi') -- 2.43.0
[PULL 33/46] meson: move option validation together
Check options before compiler flags, because some compiler flags are incompatible with modules. Signed-off-by: Paolo Bonzini --- meson.build | 137 ++-- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/meson.build b/meson.build index 3a1f4cbb90f..2c6f09352c9 100644 --- a/meson.build +++ b/meson.build @@ -108,6 +108,71 @@ endforeach # Option validation # # +# Fuzzing +if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \ +not cc.links(''' + #include + #include + int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } +''', +args: ['-Werror', '-fsanitize=fuzzer']) + error('Your compiler does not support -fsanitize=fuzzer') +endif + +# Tracing backends +if 'ftrace' in get_option('trace_backends') and targetos != 'linux' + error('ftrace is supported only on Linux') +endif +if 'syslog' in get_option('trace_backends') and not cc.compiles(''' +#include +int main(void) { +openlog("qemu", LOG_PID, LOG_DAEMON); +syslog(LOG_INFO, "configure"); +return 0; +}''') + error('syslog is not supported on this system') +endif + +# Miscellaneous Linux-only features +get_option('mpath') \ + .require(targetos == 'linux', error_message: 'Multipath is supported only on Linux') + +multiprocess_allowed = get_option('multiprocess') \ + .require(targetos == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \ + .allowed() + +vfio_user_server_allowed = get_option('vfio_user_server') \ + .require(targetos == 'linux', error_message: 'vfio-user server is supported only on Linux') \ + .allowed() + +have_tpm = get_option('tpm') \ + .require(targetos != 'windows', error_message: 'TPM emulation only available on POSIX systems') \ + .allowed() + +# vhost +have_vhost_user = get_option('vhost_user') \ + .disable_auto_if(targetos != 'linux') \ + .require(targetos != 'windows', + error_message: 'vhost-user is not available on Windows').allowed() +have_vhost_vdpa = get_option('vhost_vdpa') \ + .require(targetos == 'linux', + error_message: 'vhost-vdpa is only available on Linux').allowed() +have_vhost_kernel = get_option('vhost_kernel') \ + .require(targetos == 'linux', + error_message: 'vhost-kernel is only available on Linux').allowed() +have_vhost_user_crypto = get_option('vhost_crypto') \ + .require(have_vhost_user, + error_message: 'vhost-crypto requires vhost-user to be enabled').allowed() + +have_vhost = have_vhost_user or have_vhost_vdpa or have_vhost_kernel + +have_vhost_net_user = have_vhost_user and get_option('vhost_net').allowed() +have_vhost_net_vdpa = have_vhost_vdpa and get_option('vhost_net').allowed() +have_vhost_net_kernel = have_vhost_kernel and get_option('vhost_net').allowed() +have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_vdpa + +# type of binaries to build have_linux_user = false have_bsd_user = false have_system = false @@ -117,6 +182,7 @@ foreach target : target_dirs have_system = have_system or target.endswith('-softmmu') endforeach have_user = have_linux_user or have_bsd_user + have_tools = get_option('tools') \ .disable_auto_if(not have_system) \ .allowed() @@ -125,13 +191,14 @@ have_ga = get_option('guest_agent') \ .require(targetos in ['sunos', 'linux', 'windows', 'freebsd', 'netbsd', 'openbsd'], error_message: 'unsupported OS for QEMU guest agent') \ .allowed() +have_block = have_system or have_tools + enable_modules = get_option('modules') \ .require(targetos != 'windows', error_message: 'Modules are not available for Windows') \ .require(not get_option('prefer_static'), error_message: 'Modules are incompatible with static linking') \ .allowed() -have_block = have_system or have_tools ### # Variables for host and accelerators # @@ -535,74 +602,6 @@ if sparse.found() '-Wno-non-pointer-null']) endif -# -# Option validation # -# - -# Fuzzing -if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \ -not cc.links(''' - #include - #include - int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); - int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } -''', -args: ['-Werror', '-fsanitize=fuzzer']) - error('Your compiler does not support -fsanitize=fuzzer') -endif - -# Tracing backends -if 'ftrace' in get_option('trace_backends') and targetos != 'linux' - error('ftrace is supported only on Linux') -endif -if 'syslog' in get_option('trace_backends') and not cc.compiles(''' -#include -int main(void) { -openlog("qemu", LOG_PID, LOG_DAEMON); -
[PULL 39/46] meson: always probe u2f and canokey if the option is enabled
Signed-off-by: Paolo Bonzini --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 21335055ef8..7344e363826 100644 --- a/meson.build +++ b/meson.build @@ -1828,12 +1828,12 @@ if not get_option('smartcard').auto() or have_system version: '>=2.5.1', method: 'pkg-config') endif u2f = not_found -if have_system +if not get_option('u2f').auto() or have_system u2f = dependency('u2f-emu', required: get_option('u2f'), method: 'pkg-config') endif canokey = not_found -if have_system +if not get_option('canokey').auto() or have_system canokey = dependency('canokey-qemu', required: get_option('canokey'), method: 'pkg-config') endif -- 2.43.0
[PULL 31/46] meson: add more sections to main meson.build
Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- meson.build | 24 ++-- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 6c77d9687de..c437e9f55e6 100644 --- a/meson.build +++ b/meson.build @@ -9,6 +9,10 @@ add_test_setup('thorough', env: ['G_TEST_SLOW=1', 'SPEED=thorough']) meson.add_postconf_script(find_program('scripts/symlink-install-tree.py')) + +# Global variables # + + not_found = dependency('', required: false) keyval = import('keyval') ss = import('sourceset') @@ -86,8 +90,16 @@ enable_modules = get_option('modules') \ .allowed() have_block = have_system or have_tools + +# Programs # + + python = import('python').find_installation() +### +# Variables for host and accelerators # +### + if cpu not in supported_cpus host_arch = 'unknown' elif cpu == 'x86' @@ -518,9 +530,9 @@ if sparse.found() '-Wno-non-pointer-null']) endif -### -# Target-specific checks and dependencies # -### +# +# Option validation # +# # Fuzzing if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \ @@ -3524,9 +3536,9 @@ specific_ss.add_all(when: 'CONFIG_TCG_BUILTIN', if_true: tcg_module_ss) target_modules += { 'accel' : { 'qtest': qtest_module_ss, 'tcg': tcg_real_module_ss }} - -# Library dependencies # - +## +# Internal static_libraries and dependencies # +## modinfo_collect = find_program('scripts/modinfo-collect.py') modinfo_generate = find_program('scripts/modinfo-generate.py') -- 2.43.0
[PULL 21/46] target/i386: introduce flags writeback mechanism
ALU instructions can write to both memory and flags. If the CC_SRC* and CC_DST locations have been written already when a memory access causes a fault, the value in CC_SRC* and CC_DST might be interpreted with the wrong CC_OP (the one that is in effect before the instruction. Besides just using the wrong result for the flags, something like subtracting -1 can have disastrous effects if the current CC_OP is CC_OP_EFLAGS: this is because QEMU does not expect bits outside the ALU flags to be set in CC_SRC, and env->eflags can end up set to all-ones. In the case of the attached testcase, this sets IOPL to 3 and would cause an assertion failure if SUB is moved to the new decoder. This mechanism is not really needed for BMI instructions, which can only write to a register, but put it to use anyway for cleanliness. In the case of BZHI, the code has to be modified slightly to ensure that decode->cc_src is written, otherwise the new assertions trigger. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/cpu.h| 1 + target/i386/tcg/decode-new.c.inc | 34 + target/i386/tcg/decode-new.h | 4 target/i386/tcg/emit.c.inc | 36 --- tests/tcg/i386/Makefile.target | 2 +- tests/tcg/i386/test-flags.c | 37 6 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 tests/tcg/i386/test-flags.c diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ecdd4518c64..7f0786e8b98 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1285,6 +1285,7 @@ typedef enum { CC_OP_NB, } CCOp; +QEMU_BUILD_BUG_ON(CC_OP_NB >= 128); typedef struct SegmentCache { uint32_t selector; diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index f30889dbc0a..717d7307722 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -1662,6 +1662,7 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) bool first = true; X86DecodedInsn decode; X86DecodeFunc decode_func = decode_root; +uint8_t cc_live; s->has_modrm = false; @@ -1815,6 +1816,7 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) } memset(&decode, 0, sizeof(decode)); +decode.cc_op = -1; decode.b = b; if (!decode_insn(s, env, decode_func, &decode)) { goto illegal_op; @@ -1953,6 +1955,38 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) decode.e.gen(s, env, &decode); gen_writeback(s, &decode, 0, s->T0); } + +/* + * Write back flags after last memory access. Some newer ALU instructions, as + * well as SSE instructions, write flags in the gen_* function, but that can + * cause incorrect tracking of CC_OP for instructions that write to both memory + * and flags. + */ +if (decode.cc_op != -1) { +if (decode.cc_dst) { +tcg_gen_mov_tl(cpu_cc_dst, decode.cc_dst); +} +if (decode.cc_src) { +tcg_gen_mov_tl(cpu_cc_src, decode.cc_src); +} +if (decode.cc_src2) { +tcg_gen_mov_tl(cpu_cc_src2, decode.cc_src2); +} +if (decode.cc_op == CC_OP_DYNAMIC) { +tcg_gen_mov_i32(cpu_cc_op, decode.cc_op_dynamic); +} +set_cc_op(s, decode.cc_op); +cc_live = cc_op_live[decode.cc_op]; +} else { +cc_live = 0; +} +if (decode.cc_op != CC_OP_DYNAMIC) { +assert(!decode.cc_op_dynamic); +assert(!!decode.cc_dst == !!(cc_live & USES_CC_DST)); +assert(!!decode.cc_src == !!(cc_live & USES_CC_SRC)); +assert(!!decode.cc_src2 == !!(cc_live & USES_CC_SRC2)); +} + return; gp_fault: gen_exception_gpf(s); diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 70b6717227f..25220fc4362 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -283,6 +283,10 @@ struct X86DecodedInsn { target_ulong immediate; AddressParts mem; +TCGv cc_dst, cc_src, cc_src2; +TCGv_i32 cc_op_dynamic; +int8_t cc_op; + uint8_t b; }; diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 4c2006fdd09..fd120e7b9b4 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -339,6 +339,19 @@ static inline int vector_len(DisasContext *s, X86DecodedInsn *decode) return s->vex_l ? 32 : 16; } +static void prepare_update1_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op) +{ +decode->cc_dst = s->T0; +decode->cc_op = op; +} + +static void prepare_update2_cc(X86DecodedInsn *decode, DisasContext *s, CCOp op) +{ +decode->cc_src = s->T1; +decode->cc_dst = s->T0; +decode->cc_op = op; +} + static void gen_store_sse(DisasContext *s, X86DecodedInsn *decode, int src_ofs) { MemOp ot = decode->op[0].ot; @@ -1027,6 +1040,7 @@ static vo
[PULL 26/46] meson: remove unused variable
Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- tests/bench/meson.build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bench/meson.build b/tests/bench/meson.build index 3c799dbd983..7e76338a52d 100644 --- a/tests/bench/meson.build +++ b/tests/bench/meson.build @@ -3,9 +3,9 @@ qht_bench = executable('qht-bench', sources: 'qht-bench.c', dependencies: [qemuutil]) -qtree_bench = executable('qtree-bench', - sources: 'qtree-bench.c', - dependencies: [qemuutil]) +executable('qtree-bench', + sources: 'qtree-bench.c', + dependencies: [qemuutil]) executable('atomic_add-bench', sources: files('atomic_add-bench.c'), -- 2.43.0
[PULL 43/46] meson: remove CONFIG_ALL
CONFIG_ALL is tricky to use and was ported over to Meson from the recursive processing of Makefile variables. Meson sourcesets however have all_sources() and all_dependencies() methods that remove the need for it. Signed-off-by: Paolo Bonzini --- docs/devel/build-system.rst | 15 --- fsdev/meson.build | 1 - hw/acpi/meson.build | 5 - hw/cxl/meson.build | 2 -- hw/display/meson.build | 1 - hw/mem/meson.build | 1 - hw/net/meson.build | 2 -- hw/pci-bridge/meson.build | 2 -- hw/pci/meson.build | 1 - hw/remote/meson.build | 1 - hw/smbios/meson.build | 5 - hw/virtio/meson.build | 2 -- meson.build | 32 +++- net/meson.build | 2 -- 14 files changed, 7 insertions(+), 65 deletions(-) diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst index 43d6005881e..09caf2f8e19 100644 --- a/docs/devel/build-system.rst +++ b/docs/devel/build-system.rst @@ -256,21 +256,6 @@ Target-independent emulator sourcesets: ``system_ss`` only in system emulators, ``user_ss`` only in user-mode emulators. - Target-independent sourcesets must exercise particular care when using - ``if_false`` rules. The ``if_false`` rule will be used correctly when linking - emulator binaries; however, when *compiling* target-independent files - into .o files, Meson may need to pick *both* the ``if_true`` and - ``if_false`` sides to cater for targets that want either side. To - achieve that, you can add a special rule using the ``CONFIG_ALL`` - symbol:: - -# Some targets have CONFIG_ACPI, some don't, so this is not enough -system_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi.c'), -if_false: files('acpi-stub.c')) - -# This is required as well: -system_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c')) - Target-dependent emulator sourcesets: In the target-dependent set lives CPU emulation, some device emulation and much glue code. This sometimes also has to be compiled multiple times, diff --git a/fsdev/meson.build b/fsdev/meson.build index c76347615df..db67530d7f2 100644 --- a/fsdev/meson.build +++ b/fsdev/meson.build @@ -1,6 +1,5 @@ fsdev_ss = ss.source_set() fsdev_ss.add(files('qemu-fsdev-opts.c', 'qemu-fsdev-throttle.c')) -fsdev_ss.add(when: 'CONFIG_ALL', if_true: files('qemu-fsdev-dummy.c')) fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files( '9p-iov-marshal.c', '9p-marshal.c', diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index fc1b952379a..5441c9b1e4c 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -33,9 +33,4 @@ endif system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c')) system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c')) system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) -system_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c', - 'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c', - 'acpi-mem-hotplug-stub.c', 'acpi-cpu-hotplug-stub.c', - 'acpi-pci-hotplug-stub.c', 'acpi-nvdimm-stub.c', - 'cxl-stub.c', 'pci-bridge-stub.c')) system_ss.add(files('acpi-qmp-cmds.c')) diff --git a/hw/cxl/meson.build b/hw/cxl/meson.build index ea0aebf6e3c..3e375f61a98 100644 --- a/hw/cxl/meson.build +++ b/hw/cxl/meson.build @@ -11,5 +11,3 @@ system_ss.add(when: 'CONFIG_CXL', if_false: files( 'cxl-host-stubs.c', )) - -system_ss.add(when: 'CONFIG_ALL', if_true: files('cxl-host-stubs.c')) diff --git a/hw/display/meson.build b/hw/display/meson.build index 02b0044c9ec..ac0159c516e 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -143,5 +143,4 @@ endif system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_lcdc.c')) -system_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-vga-stub.c')) modules += { 'hw-display': hw_display_modules } diff --git a/hw/mem/meson.build b/hw/mem/meson.build index ec26ef55443..faee1fe9360 100644 --- a/hw/mem/meson.build +++ b/hw/mem/meson.build @@ -5,7 +5,6 @@ mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c')) mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c')) mem_ss.add(when: 'CONFIG_CXL_MEM_DEVICE', if_true: files('cxl_type3.c')) system_ss.add(when: 'CONFIG_CXL_MEM_DEVICE', if_false: files('cxl_type3_stubs.c')) -system_ss.add(when: 'CONFIG_ALL', if_true: files('cxl_type3_stubs.c')) system_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss) diff --git a/hw/net/meson.build b/hw/net/meson.build index f64651c467e..9afceb06191 100644 --- a/hw/net/meson.build +++ b/hw/net/meson.build @@ -50,7 +
[PULL 19/46] target/i386: move operand load and writeback out of gen_cmovcc1
Similar to gen_setcc1, make gen_cmovcc1 receive TCGv. This is more friendly to simultaneous implementation in the old and the new decoder. A small wart is that s->T0 of CMOV is currently the *second* argument (which would ordinarily be in T1). Therefore, the condition has to be inverted in order to overwrite s->T0 with cpu_regs[reg] if the MOV is not performed. This only applies to the old decoder, and this code will go away soon. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 16 ++-- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index ecbd80a19ad..fe82d421576 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2500,14 +2500,10 @@ static void gen_jcc(DisasContext *s, int b, int diff) gen_jmp_rel(s, s->dflag, diff, 0); } -static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b, -int modrm, int reg) +static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src) { -CCPrepare cc; +CCPrepare cc = gen_prepare_cc(s, b, s->T1); -gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - -cc = gen_prepare_cc(s, b, s->T1); if (cc.mask != -1) { TCGv t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, cc.reg, cc.mask); @@ -2517,9 +2513,7 @@ static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b, cc.reg2 = tcg_constant_tl(cc.imm); } -tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2, - s->T0, cpu_regs[reg]); -gen_op_mov_reg_v(s, ot, reg, s->T0); +tcg_gen_movcond_tl(cc.cond, dest, cc.reg, cc.reg2, src, dest); } static inline void gen_op_movl_T0_seg(DisasContext *s, X86Seg seg_reg) @@ -5228,7 +5222,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) ot = dflag; modrm = x86_ldub_code(env, s); reg = ((modrm >> 3) & 7) | REX_R(s); -gen_cmovcc1(env, s, ot, b, modrm, reg); +gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); +gen_cmovcc1(s, b ^ 1, s->T0, cpu_regs[reg]); +gen_op_mov_reg_v(s, ot, reg, s->T0); break; // -- 2.43.0
[PULL 44/46] meson: rename config_all
config_all now lists only accelerators, rename it to indicate its actual content. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/mips/meson.build | 2 +- meson.build | 16 target/arm/meson.build | 2 +- target/mips/meson.build | 2 +- tests/fp/meson.build| 2 +- tests/meson.build | 2 +- tests/qtest/meson.build | 8 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/hw/mips/meson.build b/hw/mips/meson.build index 900613fc087..f06d88f3430 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -5,7 +5,7 @@ mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 'loon mips_ss.add(when: 'CONFIG_MALTA', if_true: files('malta.c')) mips_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('cps.c')) -if 'CONFIG_TCG' in config_all +if 'CONFIG_TCG' in config_all_accel mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) diff --git a/meson.build b/meson.build index 6e5a8a5b48e..754c469ec98 100644 --- a/meson.build +++ b/meson.build @@ -2886,7 +2886,7 @@ endif minikconf = find_program('scripts/minikconf.py') -config_all = {} +config_all_accel = {} config_all_devices = {} config_devices_mak_list = [] config_devices_h = {} @@ -2974,7 +2974,7 @@ foreach target : target_dirs foreach sym: accelerators if sym == 'CONFIG_TCG' or target in accelerator_targets.get(sym, []) config_target += { sym: 'y' } - config_all += { sym: 'y' } + config_all_accel += { sym: 'y' } if target in modular_tcg config_target += { 'CONFIG_TCG_MODULAR': 'y' } else @@ -4204,18 +4204,18 @@ endif # Targets and accelerators summary_info = {} if have_system - summary_info += {'KVM support': config_all.has_key('CONFIG_KVM')} - summary_info += {'HVF support': config_all.has_key('CONFIG_HVF')} - summary_info += {'WHPX support': config_all.has_key('CONFIG_WHPX')} - summary_info += {'NVMM support': config_all.has_key('CONFIG_NVMM')} + summary_info += {'KVM support': config_all_accel.has_key('CONFIG_KVM')} + summary_info += {'HVF support': config_all_accel.has_key('CONFIG_HVF')} + summary_info += {'WHPX support': config_all_accel.has_key('CONFIG_WHPX')} + summary_info += {'NVMM support': config_all_accel.has_key('CONFIG_NVMM')} summary_info += {'Xen support': xen.found()} if xen.found() summary_info += {'xen ctrl version': xen.version()} endif summary_info += {'Xen emulation': config_all_devices.has_key('CONFIG_XEN_EMU')} endif -summary_info += {'TCG support': config_all.has_key('CONFIG_TCG')} -if config_all.has_key('CONFIG_TCG') +summary_info += {'TCG support': config_all_accel.has_key('CONFIG_TCG')} +if config_all_accel.has_key('CONFIG_TCG') if get_option('tcg_interpreter') summary_info += {'TCG backend': 'TCI (TCG with bytecode interpreter, slow)'} else diff --git a/target/arm/meson.build b/target/arm/meson.build index d6c3902e676..46b5a21eb31 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -28,7 +28,7 @@ arm_system_ss.add(files( subdir('hvf') -if 'CONFIG_TCG' in config_all +if 'CONFIG_TCG' in config_all_accel subdir('tcg') else arm_ss.add(files('tcg-stubs.c')) diff --git a/target/mips/meson.build b/target/mips/meson.build index e57ef24ecf4..a26d1e1f792 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -12,7 +12,7 @@ if have_system subdir('sysemu') endif -if 'CONFIG_TCG' in config_all +if 'CONFIG_TCG' in config_all_accel subdir('tcg') endif diff --git a/tests/fp/meson.build b/tests/fp/meson.build index cbc17392d67..9ef322afc42 100644 --- a/tests/fp/meson.build +++ b/tests/fp/meson.build @@ -1,4 +1,4 @@ -if 'CONFIG_TCG' not in config_all +if 'CONFIG_TCG' not in config_all_accel subdir_done() endif # There are namespace pollution issues on Windows, due to osdep.h diff --git a/tests/meson.build b/tests/meson.build index 9996a293fbb..32cc15a3ef7 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -76,7 +76,7 @@ endif subdir('decode') -if 'CONFIG_TCG' in config_all +if 'CONFIG_TCG' in config_all_accel subdir('fp') endif diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 40a8bb043e4..565eff4c0a2 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -155,8 +155,8 @@ qtests_ppc = \ qtests_filter + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) +\ (config_all_devices.has_key('CONFIG_M48T59') ? ['m48t59-test'] : []) + \ - (config_all.has_key('CONFIG_TCG') ? ['prom-env-test'] : []) + \ - (config_all.has_key('CONFIG_TCG') ? ['boot-serial-test'] : []) + \ + (config_all_accel.has_key('CONF
[PULL 35/46] meson: keep subprojects together
And move away dependencies that are not subprojects anymore. Signed-off-by: Paolo Bonzini --- meson.build | 72 ++--- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/meson.build b/meson.build index 1867e0428b1..efb36c762e9 100644 --- a/meson.build +++ b/meson.build @@ -1622,6 +1622,25 @@ if not gnutls_crypto.found() endif endif +capstone = not_found +if not get_option('capstone').auto() or have_system or have_user + capstone = dependency('capstone', version: '>=3.0.5', +method: 'pkg-config', +required: get_option('capstone')) + + # Some versions of capstone have broken pkg-config file + # that reports a wrong -I path, causing the #include to + # fail later. If the system has such a broken version + # do not use it. + if capstone.found() and not cc.compiles('#include ', + dependencies: [capstone]) +capstone = not_found +if get_option('capstone').enabled() + error('capstone requested, but it does not appear to work') +endif + endif +endif + gmp = dependency('gmp', required: false, method: 'pkg-config') if nettle.found() and gmp.found() hogweed = dependency('hogweed', version: '>=3.4', @@ -2127,6 +2146,7 @@ config_host_data.set('CONFIG_ATTR', libattr.found()) config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools')) config_host_data.set('CONFIG_BRLAPI', brlapi.found()) config_host_data.set('CONFIG_BSD', targetos in bsd_oses) +config_host_data.set('CONFIG_CAPSTONE', capstone.found()) config_host_data.set('CONFIG_COCOA', cocoa.found()) config_host_data.set('CONFIG_DARWIN', targetos == 'darwin') config_host_data.set('CONFIG_FUZZ', get_option('fuzzing')) @@ -2190,6 +2210,7 @@ if seccomp.found() config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc) endif config_host_data.set('CONFIG_PIXMAN', pixman.found()) +config_host_data.set('CONFIG_SLIRP', slirp.found()) config_host_data.set('CONFIG_SNAPPY', snappy.found()) config_host_data.set('CONFIG_SOLARIS', targetos == 'sunos') if get_option('tcg').allowed() @@ -3093,28 +3114,9 @@ genh += custom_target('config-poison.h', command: [find_program('scripts/make-config-poison.sh'), target_configs_h]) -## -# Submodules # -## - -capstone = not_found -if not get_option('capstone').auto() or have_system or have_user - capstone = dependency('capstone', version: '>=3.0.5', -method: 'pkg-config', -required: get_option('capstone')) - - # Some versions of capstone have broken pkg-config file - # that reports a wrong -I path, causing the #include to - # fail later. If the system has such a broken version - # do not use it. - if capstone.found() and not cc.compiles('#include ', - dependencies: [capstone]) -capstone = not_found -if get_option('capstone').enabled() - error('capstone requested, but it does not appear to work') -endif - endif -endif +### +# Subprojects # +### libvfio_user_dep = not_found if have_system and vfio_user_server_allowed @@ -3158,9 +3160,19 @@ else fdt_opt = 'disabled' endif -config_host_data.set('CONFIG_CAPSTONE', capstone.found()) config_host_data.set('CONFIG_FDT', fdt.found()) -config_host_data.set('CONFIG_SLIRP', slirp.found()) + +vhost_user = not_found +if targetos == 'linux' and have_vhost_user + libvhost_user = subproject('libvhost-user') + vhost_user = libvhost_user.get_variable('vhost_user_dep') +endif + +libvduse = not_found +if have_libvduse + libvduse_proj = subproject('libvduse') + libvduse = libvduse_proj.get_variable('libvduse_dep') +endif # # Generated sources # @@ -3391,18 +3403,6 @@ if have_system or have_user ] endif -vhost_user = not_found -if targetos == 'linux' and have_vhost_user - libvhost_user = subproject('libvhost-user') - vhost_user = libvhost_user.get_variable('vhost_user_dep') -endif - -libvduse = not_found -if have_libvduse - libvduse_proj = subproject('libvduse') - libvduse = libvduse_proj.get_variable('libvduse_dep') -endif - # NOTE: the trace/ subdirectory needs the qapi_trace_events variable # that is filled in by qapi/. subdir('qapi') -- 2.43.0
[PULL 37/46] meson: move config-host.h definitions together
Signed-off-by: Paolo Bonzini --- meson.build | 27 ++- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/meson.build b/meson.build index 5c54441a3cd..151db21c038 100644 --- a/meson.build +++ b/meson.build @@ -40,7 +40,6 @@ qemu_moddir = get_option('libdir') / get_option('qemu_suffix') qemu_desktopdir = get_option('datadir') / 'applications' qemu_icondir = get_option('datadir') / 'icons' -config_host_data = configuration_data() genh = [] qapi_trace_events = [] @@ -233,12 +232,6 @@ elif cpu in ['riscv64'] else kvm_targets = [] endif - -kvm_targets_c = '""' -if get_option('kvm').allowed() and targetos == 'linux' - kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"' -endif -config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c) accelerator_targets = { 'CONFIG_KVM': kvm_targets } if cpu in ['x86', 'x86_64'] @@ -1191,12 +1184,6 @@ if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu virgl = dependency('virglrenderer', method: 'pkg-config', required: get_option('virglrenderer')) - if virgl.found() -config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', - cc.has_member('struct virgl_renderer_resource_info_ext', 'd3d_tex2d', - prefix: '#include ', - dependencies: virgl)) - endif endif rutabaga = not_found if not get_option('rutabaga_gfx').auto() or have_system or have_vhost_user_gpu @@ -2008,6 +1995,8 @@ endif # config-host.h # # +config_host_data = configuration_data() + audio_drivers_selected = [] if have_system audio_drivers_available = { @@ -2137,6 +2126,12 @@ endif config_host_data.set('HOST_' + host_arch.to_upper(), 1) +kvm_targets_c = '""' +if get_option('kvm').allowed() and targetos == 'linux' + kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"' +endif +config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c) + if get_option('module_upgrades') and not enable_modules error('Cannot enable module-upgrades as modules are not enabled') endif @@ -2236,6 +2231,12 @@ config_host_data.set('CONFIG_PNG', png.found()) config_host_data.set('CONFIG_VNC', vnc.found()) config_host_data.set('CONFIG_VNC_JPEG', jpeg.found()) config_host_data.set('CONFIG_VNC_SASL', sasl.found()) +if virgl.found() + config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', + cc.has_member('struct virgl_renderer_resource_info_ext', 'd3d_tex2d', + prefix: '#include ', + dependencies: virgl)) +endif config_host_data.set('CONFIG_VIRTFS', have_virtfs) config_host_data.set('CONFIG_VTE', vte.found()) config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found()) -- 2.43.0
[PULL 06/46] target/i386: clean up cpu_cc_compute_all
cpu_cc_compute_all() has an argument that is always equal to CC_OP for historical reasons (dating back to commit a7812ae4123, "TCG variable type checking.", 2008-11-17, which added the argument to helper_cc_compute_all). It does not make sense for the argument to have any other value, so remove it and clean up some lines that are not too long anymore. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 4 ++-- target/i386/tcg/cc_helper.c | 6 +++--- target/i386/tcg/fpu_helper.c | 10 -- target/i386/tcg/int_helper.c | 8 target/i386/tcg/misc_helper.c | 2 +- target/i386/tcg/seg_helper.c | 8 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ef987f344cf..ecdd4518c64 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2344,13 +2344,13 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, uint64_t status, uint64_t mcg_status, uint64_t addr, uint64_t misc, int flags); -uint32_t cpu_cc_compute_all(CPUX86State *env1, int op); +uint32_t cpu_cc_compute_all(CPUX86State *env1); static inline uint32_t cpu_compute_eflags(CPUX86State *env) { uint32_t eflags = env->eflags; if (tcg_enabled()) { -eflags |= cpu_cc_compute_all(env, CC_OP) | (env->df & DF_MASK); +eflags |= cpu_cc_compute_all(env) | (env->df & DF_MASK); } return eflags; } diff --git a/target/i386/tcg/cc_helper.c b/target/i386/tcg/cc_helper.c index c310bd842f1..f76e9cb8cfb 100644 --- a/target/i386/tcg/cc_helper.c +++ b/target/i386/tcg/cc_helper.c @@ -220,9 +220,9 @@ target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1, } } -uint32_t cpu_cc_compute_all(CPUX86State *env, int op) +uint32_t cpu_cc_compute_all(CPUX86State *env) { -return helper_cc_compute_all(CC_DST, CC_SRC, CC_SRC2, op); +return helper_cc_compute_all(CC_DST, CC_SRC, CC_SRC2, CC_OP); } target_ulong helper_cc_compute_c(target_ulong dst, target_ulong src1, @@ -335,7 +335,7 @@ target_ulong helper_read_eflags(CPUX86State *env) { uint32_t eflags; -eflags = cpu_cc_compute_all(env, CC_OP); +eflags = cpu_cc_compute_all(env); eflags |= (env->df & DF_MASK); eflags |= env->eflags & ~(VM_MASK | RF_MASK); return eflags; diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index 4430d3d380c..4b965a5d6c4 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -484,9 +484,8 @@ void helper_fcomi_ST0_FT0(CPUX86State *env) FloatRelation ret; ret = floatx80_compare(ST0, FT0, &env->fp_status); -eflags = cpu_cc_compute_all(env, CC_OP); -eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; -CC_SRC = eflags; +eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C); +CC_SRC = eflags | fcomi_ccval[ret + 1]; merge_exception_flags(env, old_flags); } @@ -497,9 +496,8 @@ void helper_fucomi_ST0_FT0(CPUX86State *env) FloatRelation ret; ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); -eflags = cpu_cc_compute_all(env, CC_OP); -eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; -CC_SRC = eflags; +eflags = cpu_cc_compute_all(env) & ~(CC_Z | CC_P | CC_C); +CC_SRC = eflags | fcomi_ccval[ret + 1]; merge_exception_flags(env, old_flags); } diff --git a/target/i386/tcg/int_helper.c b/target/i386/tcg/int_helper.c index 05418f181f1..ab85dc55400 100644 --- a/target/i386/tcg/int_helper.c +++ b/target/i386/tcg/int_helper.c @@ -190,7 +190,7 @@ void helper_aaa(CPUX86State *env) int al, ah, af; int eflags; -eflags = cpu_cc_compute_all(env, CC_OP); +eflags = cpu_cc_compute_all(env); af = eflags & CC_A; al = env->regs[R_EAX] & 0xff; ah = (env->regs[R_EAX] >> 8) & 0xff; @@ -214,7 +214,7 @@ void helper_aas(CPUX86State *env) int al, ah, af; int eflags; -eflags = cpu_cc_compute_all(env, CC_OP); +eflags = cpu_cc_compute_all(env); af = eflags & CC_A; al = env->regs[R_EAX] & 0xff; ah = (env->regs[R_EAX] >> 8) & 0xff; @@ -237,7 +237,7 @@ void helper_daa(CPUX86State *env) int old_al, al, af, cf; int eflags; -eflags = cpu_cc_compute_all(env, CC_OP); +eflags = cpu_cc_compute_all(env); cf = eflags & CC_C; af = eflags & CC_A; old_al = al = env->regs[R_EAX] & 0xff; @@ -264,7 +264,7 @@ void helper_das(CPUX86State *env) int al, al1, af, cf; int eflags; -eflags = cpu_cc_compute_all(env, CC_OP); +eflags = cpu_cc_compute_all(env); cf = eflags & CC_C; af = eflags & CC_A; al = env->regs[R_EAX] & 0xff; diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c index 66b332a83c1..b0f0f7b893b 100644 --- a/target/i386/tcg/misc_helper.c +++ b/target/i386/tcg/misc_helper.c @@ -41,7 +41,7 @@ void helper_into(CPUX86State *env, int next_eip_add
[PULL 28/46] Makefile: clean qemu-iotests output
Signed-off-by: Paolo Bonzini --- Makefile | 1 + configure | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 676a4a54f48..8f369903356 100644 --- a/Makefile +++ b/Makefile @@ -202,6 +202,7 @@ clean: recurse-clean ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \ -exec rm {} + rm -f TAGS cscope.* *~ */*~ + @$(MAKE) -Ctests/qemu-iotests clean VERSION = $(shell cat $(SRC_PATH)/VERSION) diff --git a/configure b/configure index d7e0926ff19..9885cfed792 100755 --- a/configure +++ b/configure @@ -1559,7 +1559,7 @@ LINKS="$LINKS pc-bios/s390-ccw/Makefile" LINKS="$LINKS pc-bios/vof/Makefile" LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit LINKS="$LINKS tests/avocado tests/data" -LINKS="$LINKS tests/qemu-iotests/check" +LINKS="$LINKS tests/qemu-iotests/check tests/qemu-iotests/Makefile" LINKS="$LINKS python" LINKS="$LINKS contrib/plugins/Makefile " for f in $LINKS ; do -- 2.43.0
[PULL 36/46] meson: move CFI detection code with other compiler flags
Keep it together with the other compiler modes, and before dependencies. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- meson.build | 80 ++--- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/meson.build b/meson.build index efb36c762e9..5c54441a3cd 100644 --- a/meson.build +++ b/meson.build @@ -517,6 +517,46 @@ if get_option('fuzzing') endif endif +if get_option('cfi') + cfi_flags=[] + # Check for dependency on LTO + if not get_option('b_lto') +error('Selected Control-Flow Integrity but LTO is disabled') + endif + if enable_modules +error('Selected Control-Flow Integrity is not compatible with modules') + endif + # Check for cfi flags. CFI requires LTO so we can't use + # get_supported_arguments, but need a more complex "compiles" which allows + # custom arguments + if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall', + args: ['-flto', '-fsanitize=cfi-icall'] ) +cfi_flags += '-fsanitize=cfi-icall' + else +error('-fsanitize=cfi-icall is not supported by the compiler') + endif + if cc.compiles('int main () { return 0; }', + name: '-fsanitize-cfi-icall-generalize-pointers', + args: ['-flto', '-fsanitize=cfi-icall', +'-fsanitize-cfi-icall-generalize-pointers'] ) +cfi_flags += '-fsanitize-cfi-icall-generalize-pointers' + else +error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler') + endif + if get_option('cfi_debug') +if cc.compiles('int main () { return 0; }', + name: '-fno-sanitize-trap=cfi-icall', + args: ['-flto', '-fsanitize=cfi-icall', + '-fno-sanitize-trap=cfi-icall'] ) + cfi_flags += '-fno-sanitize-trap=cfi-icall' +else + error('-fno-sanitize-trap=cfi-icall is not supported by the compiler') +endif + endif + add_global_arguments(cfi_flags, native: false, language: all_languages) + add_global_link_arguments(cfi_flags, native: false, language: all_languages) +endif + add_global_arguments(qemu_common_flags, native: false, language: all_languages) add_global_link_arguments(qemu_ldflags, native: false, language: all_languages) @@ -2009,46 +2049,6 @@ endif config_host_data.set('CONFIG_AUDIO_DRIVERS', '"' + '", "'.join(audio_drivers_selected) + '", ') -if get_option('cfi') - cfi_flags=[] - # Check for dependency on LTO - if not get_option('b_lto') -error('Selected Control-Flow Integrity but LTO is disabled') - endif - if enable_modules -error('Selected Control-Flow Integrity is not compatible with modules') - endif - # Check for cfi flags. CFI requires LTO so we can't use - # get_supported_arguments, but need a more complex "compiles" which allows - # custom arguments - if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall', - args: ['-flto', '-fsanitize=cfi-icall'] ) -cfi_flags += '-fsanitize=cfi-icall' - else -error('-fsanitize=cfi-icall is not supported by the compiler') - endif - if cc.compiles('int main () { return 0; }', - name: '-fsanitize-cfi-icall-generalize-pointers', - args: ['-flto', '-fsanitize=cfi-icall', -'-fsanitize-cfi-icall-generalize-pointers'] ) -cfi_flags += '-fsanitize-cfi-icall-generalize-pointers' - else -error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler') - endif - if get_option('cfi_debug') -if cc.compiles('int main () { return 0; }', - name: '-fno-sanitize-trap=cfi-icall', - args: ['-flto', '-fsanitize=cfi-icall', - '-fno-sanitize-trap=cfi-icall'] ) - cfi_flags += '-fno-sanitize-trap=cfi-icall' -else - error('-fno-sanitize-trap=cfi-icall is not supported by the compiler') -endif - endif - add_global_arguments(cfi_flags, native: false, language: all_languages) - add_global_link_arguments(cfi_flags, native: false, language: all_languages) -endif - have_host_block_device = (targetos != 'darwin' or cc.has_header('IOKit/storage/IOMedia.h')) -- 2.43.0
[PULL 46/46] meson.build: report graphics backends separately
From: Alex Bennée To enable accelerated VirtIO GPUs for the guest we need the rendering support on the host, which currently it's reported in the configuration summary under the "dependencies" section. Add a graphics backend section and report the status of the VirGL and Rutabaga support libraries. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-ID: <20231222114846.2850741-1-alex.ben...@linaro.org> [Remove from dependencies as suggested by Philippe. - Paolo] Signed-off-by: Paolo Bonzini --- meson.build | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 44bc5bf0c0e..5a2582776ce 100644 --- a/meson.build +++ b/meson.build @@ -4302,6 +4302,12 @@ summary_info += {'curses support':curses} summary_info += {'brlapi support':brlapi} summary(summary_info, bool_yn: true, section: 'User interface') +# Graphics backends +summary_info = {} +summary_info += {'VirGL support': virgl} +summary_info += {'Rutabaga support': rutabaga} +summary(summary_info, bool_yn: true, section: 'Graphics backends') + # Audio backends summary_info = {} if host_os not in ['darwin', 'haiku', 'windows'] @@ -4337,8 +4343,6 @@ summary_info = {} summary_info += {'libtasn1': tasn1} summary_info += {'PAM': pam} summary_info += {'iconv support': iconv} -summary_info += {'virgl support': virgl} -summary_info += {'rutabaga support': rutabaga} summary_info += {'blkio support': blkio} summary_info += {'curl support': curl} summary_info += {'Multipath support': mpathpersist} -- 2.43.0
[PULL 23/46] target/i386: the sgx_epc_get_section stub is reachable
The sgx_epc_get_section stub is reachable from cpu_x86_cpuid. It should not assert, instead it should just return true just like the "real" sgx_epc_get_section does when SGX is disabled. Reported-by: Vladimír Beneš Cc: qemu-sta...@nongnu.org Signed-off-by: Paolo Bonzini Message-ID: <20220201190941.106001-1-pbonz...@redhat.com> Signed-off-by: Paolo Bonzini --- hw/i386/sgx-stub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c index 26833eb233c..16b1dfd90bb 100644 --- a/hw/i386/sgx-stub.c +++ b/hw/i386/sgx-stub.c @@ -34,5 +34,5 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms) bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size) { -g_assert_not_reached(); +return true; } -- 2.43.0
[PULL 30/46] configure: unify again the case arms in probe_target_compiler
Remove assignments that match the default, and group the targets for debian-legacy-test-cross and debian-all-test-cross into a single arm. Signed-off-by: Paolo Bonzini --- configure | 87 ++- 1 file changed, 28 insertions(+), 59 deletions(-) diff --git a/configure b/configure index ed2d220040d..0128fd30ea8 100755 --- a/configure +++ b/configure @@ -1231,6 +1231,7 @@ probe_target_compiler() { got_cross_cc=no container_image= container_hosts= + container_cross_prefix= container_cross_cc= container_cross_ar= container_cross_as= @@ -1272,16 +1273,33 @@ probe_target_compiler() { test "$container" != no || continue test "$host" = "$cpu" || continue case $target_arch in + # debian-all-test-cross architectures + + hppa|m68k|mips|riscv64|sparc64) +container_image=debian-all-test-cross +;; + mips64) +container_image=debian-all-test-cross +container_cross_prefix=mips64-linux-gnuabi64- +;; + ppc|ppc64|ppc64le) +container_image=debian-all-test-cross +container_cross_prefix=powerpc${target_arch#ppc}-linux-gnu- +;; + + # debian-legacy-test-cross architectures (need Debian 11) + # - libc6.1-dev-alpha-cross: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1054412 + # - sh4-linux-user: binaries don't run with bookworm compiler + + alpha|sh4) +container_image=debian-legacy-test-cross +;; + + # architectures with individual containers + aarch64) # We don't have any bigendian build tools so we only use this for AArch64 container_image=debian-arm64-cross -container_cross_prefix=aarch64-linux-gnu- -container_cross_cc=${container_cross_prefix}gcc -;; - alpha) -container_image=debian-legacy-test-cross -container_cross_prefix=alpha-linux-gnu- -container_cross_cc=${container_cross_prefix}gcc ;; arm) # We don't have any bigendian build tools so we only use this for ARM @@ -1290,18 +1308,11 @@ probe_target_compiler() { ;; cris) container_image=fedora-cris-cross -container_cross_prefix=cris-linux-gnu- ;; hexagon) -container_image=debian-hexagon-cross container_cross_prefix=hexagon-unknown-linux-musl- container_cross_cc=${container_cross_prefix}clang ;; - hppa) -container_image=debian-all-test-cross -container_cross_prefix=hppa-linux-gnu- -container_cross_cc=${container_cross_prefix}gcc -;; i386) container_image=debian-i686-cross container_cross_prefix=i686-linux-gnu- @@ -1310,59 +1321,19 @@ probe_target_compiler() { container_image=debian-loongarch-cross container_cross_prefix=loongarch64-unknown-linux-gnu- ;; - m68k) -container_image=debian-all-test-cross -container_cross_prefix=m68k-linux-gnu- -container_cross_cc=${container_cross_prefix}gcc -;; microblaze) -container_image=debian-microblaze-cross container_cross_prefix=microblaze-linux-musl- ;; mips64el) container_image=debian-mips64el-cross container_cross_prefix=mips64el-linux-gnuabi64- ;; - mips64) -container_image=debian-all-test-cross -container_cross_prefix=mips64-linux-gnuabi64- -;; - mips) -container_image=debian-all-test-cross -container_cross_prefix=mips-linux-gnu- -;; - nios2) -container_image=debian-nios2-cross -container_cross_prefix=nios2-linux-gnu- -;; - ppc) -container_image=debian-all-test-cross -container_cross_prefix=powerpc-linux-gnu- -container_cross_cc=${container_cross_prefix}gcc -;; - ppc64|ppc64le) -container_image=debian-all-test-cross -container_cross_prefix=powerpc${target_arch#ppc}-linux-gnu- -;; - riscv64) -container_image=debian-all-test-cross -container_cross_prefix=riscv64-linux-gnu- -;; - sh4) -container_image=debian-legacy-test-cross -container_cross_prefix=sh4-linux-gnu- -;; - sparc64) -container_image=debian-all-test-cross -container_cross_prefix=sparc64-linux-gnu- -;; tricore) container_image=debian-tricore-cross container_cross_prefix=tricore- ;; x86_64) container_image=debian-amd64-cross -container_cross_prefix=x86_64-linux-gnu- ;; xtensa*) container_image=debian-xtensa-cross @@ -1370,12 +1341,10 @@ probe_target_compiler() { # default to the dc232b cpu container_cross_prefix=/opt/2020.07/xtensa-dc232b-elf/bin/xtensa-dc232b-elf- ;; - *) -# Debian and GNU architecture names usually match -cont
[PULL 41/46] meson: remove CONFIG_POSIX and CONFIG_WIN32 from config_targetos
For consistency with other OSes, use if...endif for rules that are target-independent. Signed-off-by: Paolo Bonzini --- backends/meson.build | 6 -- block/meson.build| 7 +-- chardev/meson.build | 26 ++ hw/usb/meson.build | 4 +++- meson.build | 11 ++- qga/meson.build | 33 ++--- ui/meson.build | 8 ++-- util/meson.build | 44 +++- 8 files changed, 79 insertions(+), 60 deletions(-) diff --git a/backends/meson.build b/backends/meson.build index 248ce4923c6..6dee4e9203b 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -10,8 +10,10 @@ system_ss.add([files( 'confidential-guest-support.c', ), numa]) -system_ss.add(when: 'CONFIG_POSIX', if_true: files('rng-random.c')) -system_ss.add(when: 'CONFIG_POSIX', if_true: files('hostmem-file.c')) +if targetos != 'windows' + system_ss.add(files('rng-random.c')) + system_ss.add(files('hostmem-file.c')) +endif if targetos == 'linux' system_ss.add(files('hostmem-memfd.c')) endif diff --git a/block/meson.build b/block/meson.build index 7faed96c1e7..ddea1e40070 100644 --- a/block/meson.build +++ b/block/meson.build @@ -88,8 +88,11 @@ if get_option('parallels').allowed() block_ss.add(files('parallels.c', 'parallels-ext.c')) endif -block_ss.add(when: 'CONFIG_WIN32', if_true: files('file-win32.c', 'win32-aio.c')) -block_ss.add(when: 'CONFIG_POSIX', if_true: [files('file-posix.c'), coref, iokit]) +if targetos == 'windows' + block_ss.add(files('file-win32.c', 'win32-aio.c')) +else + block_ss.add(files('file-posix.c'), coref, iokit) +endif block_ss.add(when: libiscsi, if_true: files('iscsi-opts.c')) if targetos == 'linux' block_ss.add(files('nvme.c')) diff --git a/chardev/meson.build b/chardev/meson.build index 6d56ad32fdb..9564ace868b 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -12,20 +12,22 @@ chardev_ss.add(files( 'char-udp.c', 'char.c', )) -chardev_ss.add(when: 'CONFIG_POSIX', if_true: [files( - 'char-fd.c', - 'char-pty.c', -), util]) -if targetos in ['linux', 'gnu/kfreebsd', 'freebsd', 'dragonfly'] - chardev_ss.add(files('char-parallel.c')) +if targetos == 'windows' + chardev_ss.add(files( +'char-console.c', +'char-win-stdio.c', +'char-win.c', + )) +else + chardev_ss.add(files( + 'char-fd.c', + 'char-pty.c', +), util) + if targetos in ['linux', 'gnu/kfreebsd', 'freebsd', 'dragonfly'] +chardev_ss.add(files('char-parallel.c')) + endif endif -chardev_ss.add(when: 'CONFIG_WIN32', if_true: files( - 'char-console.c', - 'char-win-stdio.c', - 'char-win.c', -)) - chardev_ss = chardev_ss.apply(config_targetos, strict: false) system_ss.add(files( diff --git a/hw/usb/meson.build b/hw/usb/meson.build index 4b44db39cd3..b7755b638fc 100644 --- a/hw/usb/meson.build +++ b/hw/usb/meson.build @@ -44,7 +44,9 @@ system_ss.add(when: 'CONFIG_USB_STORAGE_UAS', if_true: files('dev-uas.c')) system_ss.add(when: 'CONFIG_USB_AUDIO', if_true: files('dev-audio.c')) system_ss.add(when: 'CONFIG_USB_SERIAL', if_true: files('dev-serial.c')) system_ss.add(when: 'CONFIG_USB_NETWORK', if_true: files('dev-network.c')) -system_ss.add(when: ['CONFIG_POSIX', 'CONFIG_USB_STORAGE_MTP'], if_true: files('dev-mtp.c')) +if targetos != 'windows' + system_ss.add(when: 'CONFIG_USB_STORAGE_MTP', if_true: files('dev-mtp.c')) +endif # smartcard system_ss.add(when: 'CONFIG_USB_SMARTCARD', if_true: files('dev-smartcard-reader.c')) diff --git a/meson.build b/meson.build index cf224e252c6..e37ab286c23 100644 --- a/meson.build +++ b/meson.build @@ -2885,9 +2885,7 @@ endif minikconf = find_program('scripts/minikconf.py') -config_targetos = { - (targetos == 'windows' ? 'CONFIG_WIN32' : 'CONFIG_POSIX'): 'y' -} +config_targetos = {} config_all = {} config_all_devices = {} @@ -3480,8 +3478,11 @@ if have_block # os-posix.c contains POSIX-specific functions used by qemu-storage-daemon, # os-win32.c does not - blockdev_ss.add(when: 'CONFIG_POSIX', if_true: files('os-posix.c')) - system_ss.add(when: 'CONFIG_WIN32', if_true: [files('os-win32.c')]) + if targetos == 'windows' +system_ss.add(files('os-win32.c')) + else +blockdev_ss.add(files('os-posix.c')) + endif endif common_ss.add(files('cpu-common.c')) diff --git a/qga/meson.build b/qga/meson.build index 50edaf1c3d4..1113e7c7fae 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -67,22 +67,25 @@ qga_ss.add(files( 'main.c', 'cutils.c', )) -qga_ss.add(when: 'CONFIG_POSIX', if_true: files( - 'channel-posix.c', - 'commands-posix.c', - 'commands-posix-ssh.c', -)) -if targetos == 'linux' - qga_ss.add(files('commands-linux.c')) -elif targetos in bsd_oses - qga_ss.add(files('commands-bsd.c')) +if targetos == 'windows' + qga_ss.add(files( +'channel-win32.c', +'commands-win32.c', +'service-win32.c', +'vss-win32.c' + )) +else + qga_ss.add(
[PULL 29/46] configure: remove unnecessary subshell
Do not use a subshell to hide the shadowing of $config_host_mak. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- configure | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 9885cfed792..ed2d220040d 100755 --- a/configure +++ b/configure @@ -1671,10 +1671,9 @@ if test "$targetos" = windows; then fi # tests/tcg configuration -(config_host_mak=tests/tcg/config-host.mak mkdir -p tests/tcg -echo "# Automatically generated by configure - do not modify" > $config_host_mak -echo "SRC_PATH=$source_path" >> $config_host_mak +echo "# Automatically generated by configure - do not modify" > tests/tcg/$config_host_mak +echo "SRC_PATH=$source_path" >> tests/tcg/$config_host_mak tcg_tests_targets= for target in $target_list; do @@ -1717,9 +1716,8 @@ for target in $target_list; do done if test "$tcg" = "enabled"; then -echo "TCG_TESTS_TARGETS=$tcg_tests_targets" >> config-host.mak +echo "TCG_TESTS_TARGETS=$tcg_tests_targets" >> $config_host_mak fi -) if test "$skip_meson" = no; then cross="config-meson.cross.new" -- 2.43.0
[PULL 01/46] configure: use a native non-cross compiler for linux-user
Commit c2118e9e1ab ("configure: don't try a "native" cross for linux-user", 2023-11-23) sought to avoid issues with using the native compiler with a cross-endian or cross-bitness setup. However, in doing so it ended up requiring a cross compiler setup (and most likely a slow compiler setup) even when building TCG tests that are native to the host architecture. Always allow the host compiler in that case. Cc: qemu-sta...@nongnu.org Fixes: c2118e9e1ab ("configure: don't try a "native" cross for linux-user", 2023-11-23) Signed-off-by: Paolo Bonzini --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index bdda912f362..d7e0926ff19 100755 --- a/configure +++ b/configure @@ -1387,8 +1387,8 @@ probe_target_compiler() { done try=cross - # For softmmu/roms we might be able to use the host compiler - if [ "${1%softmmu}" != "$1" ]; then + # For softmmu/roms also look for a bi-endian or multilib-enabled host compiler + if [ "${1%softmmu}" != "$1" ] || test "$target_arch" = "$cpu"; then case "$target_arch:$cpu" in aarch64_be:aarch64 | \ armeb:arm | \ -- 2.43.0
[PULL 16/46] target/i386: do not use s->tmp4 for push
Just create a temporary for the occasion. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index b79c312465b..afe0fa6c65f 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2580,7 +2580,7 @@ static void gen_push_v(DisasContext *s, TCGv val) if (!CODE64(s)) { if (ADDSEG(s)) { -new_esp = s->tmp4; +new_esp = tcg_temp_new(); tcg_gen_mov_tl(new_esp, s->A0); } gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1); -- 2.43.0
[PULL 24/46] esp: check for NULL result from scsi_device_find()
From: Alexandra Diupina Add a 'current_lun' check for a null value to avoid null pointer dereferencing and recover host if NULL return Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 4eb8606560 (esp: store lun coming from the MESSAGE OUT phase) Signed-off-by: Alexandra Diupina Message-ID: <20231229152647.19699-1-adiup...@astralinux.ru> Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 9 + 1 file changed, 9 insertions(+) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 9b11d8c5738..d2cae79194c 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -292,6 +292,15 @@ static void do_command_phase(ESPState *s) esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen); current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun); +if (!current_lun) { +/* No such drive */ +s->rregs[ESP_RSTAT] = 0; +s->rregs[ESP_RINTR] = INTR_DC; +s->rregs[ESP_RSEQ] = SEQ_0; +esp_raise_irq(s); +return; +} + s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s); datalen = scsi_req_enqueue(s->current_req); s->ti_size = datalen; -- 2.43.0
[PULL 27/46] meson: use version_compare() to compare version
While a simple lexicographic comparison usually works, it is less robust than a more specific algorithm designed to compare versions. Signed-off-by: Paolo Bonzini --- qga/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qga/meson.build b/qga/meson.build index ff7a8496e48..a6af614891a 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -140,7 +140,7 @@ if targetos == 'windows' qemu_ga_msi_vss = ['-D', 'InstallVss'] deps += qga_vss endif -if glib.version() < '2.73.2' +if glib.version().version_compare('<2.73.2') libpcre = 'libpcre1' else libpcre = 'libpcre2' -- 2.43.0
[PULL 03/46] target/i386: speedup JO/SETO after MUL or IMUL
OF is equal to the carry flag, so use the same CCPrepare. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 8fb80011a22..a16eb8d4008 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1020,6 +1020,9 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg) case CC_OP_CLR: case CC_OP_POPCNT: return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 }; +case CC_OP_MULB ... CC_OP_MULQ: +return (CCPrepare) { .cond = TCG_COND_NE, + .reg = cpu_cc_src, .mask = -1 }; default: gen_compute_eflags(s); return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src, -- 2.43.0
[PULL 42/46] meson: remove config_targetos
config_targetos is now empty and can be removed; its use in sourcesets that do not involve target-specific files can be replaced with an empty dictionary. In fact, at this point *all* sourcesets that do not involve target-specific files are just glorified mutable arrays. Enforce that they never test for symbols in "when:" by computing the set of files without "strict: false". Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- chardev/meson.build| 2 +- gdbstub/meson.build| 4 ++-- meson.build| 24 ++-- qga/meson.build| 2 +- storage-daemon/meson.build | 2 +- tcg/meson.build| 2 +- tests/qtest/meson.build| 2 +- 7 files changed, 17 insertions(+), 21 deletions(-) diff --git a/chardev/meson.build b/chardev/meson.build index 9564ace868b..db6840b71af 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -28,7 +28,7 @@ else endif endif -chardev_ss = chardev_ss.apply(config_targetos, strict: false) +chardev_ss = chardev_ss.apply({}) system_ss.add(files( 'char-hmp-cmds.c', diff --git a/gdbstub/meson.build b/gdbstub/meson.build index e5bccba34e5..da5721d8452 100644 --- a/gdbstub/meson.build +++ b/gdbstub/meson.build @@ -14,8 +14,8 @@ gdb_system_ss = ss.source_set() gdb_user_ss.add(files('gdbstub.c', 'user.c')) gdb_system_ss.add(files('gdbstub.c', 'system.c')) -gdb_user_ss = gdb_user_ss.apply(config_targetos, strict: false) -gdb_system_ss = gdb_system_ss.apply(config_targetos, strict: false) +gdb_user_ss = gdb_user_ss.apply({}) +gdb_system_ss = gdb_system_ss.apply({}) libgdb_user = static_library('gdb_user', gdb_user_ss.sources() + genh, diff --git a/meson.build b/meson.build index e37ab286c23..7aa06dc7c1b 100644 --- a/meson.build +++ b/meson.build @@ -2885,7 +2885,6 @@ endif minikconf = find_program('scripts/minikconf.py') -config_targetos = {} config_all = {} config_all_devices = {} @@ -3084,7 +3083,6 @@ target_dirs = actual_target_dirs # pseudo symbol replaces it. config_all += config_all_devices -config_all += config_targetos config_all += config_all_disas config_all += { 'CONFIG_XEN': xen.found(), @@ -3413,7 +3411,7 @@ if enable_modules modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO') endif -qom_ss = qom_ss.apply(config_targetos, strict: false) +qom_ss = qom_ss.apply({}) libqom = static_library('qom', qom_ss.sources() + genh, dependencies: [qom_ss.dependencies()], name_suffix: 'fa', @@ -3428,10 +3426,10 @@ event_loop_base = static_library('event-loop-base', event_loop_base = declare_dependency(link_whole: event_loop_base, dependencies: [qom]) -stub_ss = stub_ss.apply(config_all, strict: false) +stub_ss = stub_ss.apply({}) util_ss.add_all(trace_ss) -util_ss = util_ss.apply(config_all, strict: false) +util_ss = util_ss.apply({}) libqemuutil = static_library('qemuutil', build_by_default: false, sources: util_ss.sources() + stub_ss.sources() + genh, @@ -3594,7 +3592,6 @@ foreach d, list : target_modules foreach target : target_dirs if target.endswith('-softmmu') config_target = config_target_mak[target] - config_target += config_targetos target_inc = [include_directories('target' / config_target['TARGET_BASE_ARCH'])] c_args = ['-DNEED_CPU_H', '-DCONFIG_TARGET="@0@-config-target.h"'.format(target), @@ -3655,7 +3652,7 @@ qemu_syms = custom_target('qemu.syms', output: 'qemu.syms', capture: true, command: [undefsym, nm, '@INPUT@']) -authz_ss = authz_ss.apply(config_targetos, strict: false) +authz_ss = authz_ss.apply({}) libauthz = static_library('authz', authz_ss.sources() + genh, dependencies: [authz_ss.dependencies()], name_suffix: 'fa', @@ -3664,7 +3661,7 @@ libauthz = static_library('authz', authz_ss.sources() + genh, authz = declare_dependency(link_whole: libauthz, dependencies: qom) -crypto_ss = crypto_ss.apply(config_targetos, strict: false) +crypto_ss = crypto_ss.apply({}) libcrypto = static_library('crypto', crypto_ss.sources() + genh, dependencies: [crypto_ss.dependencies()], name_suffix: 'fa', @@ -3673,7 +3670,7 @@ libcrypto = static_library('crypto', crypto_ss.sources() + genh, crypto = declare_dependency(link_whole: libcrypto, dependencies: [authz, qom]) -io_ss = io_ss.apply(config_targetos, strict: false) +io_ss = io_ss.apply({}) libio = static_library('io', io_ss.sources() + genh, dependencies: [io_ss.dependencies()], link_with: l
[PULL 45/46] configure, meson: rename targetos to host_os
This variable is about the host OS, not the target. It is used a lot more since the Meson conversion, but the original sin dates back to 2003. Time to fix it. Signed-off-by: Paolo Bonzini --- accel/tcg/meson.build| 2 +- backends/meson.build | 4 +- block/meson.build| 4 +- bsd-user/meson.build | 2 +- chardev/meson.build | 4 +- configure| 58 contrib/ivshmem-client/meson.build | 2 +- contrib/ivshmem-server/meson.build | 2 +- contrib/vhost-user-blk/meson.build | 2 +- contrib/vhost-user-input/meson.build | 2 +- contrib/vhost-user-scsi/meson.build | 2 +- docs/devel/kconfig.rst | 2 +- fsdev/meson.build| 2 +- hw/9pfs/meson.build | 4 +- hw/display/meson.build | 2 +- hw/ppc/meson.build | 2 +- hw/usb/meson.build | 4 +- meson.build | 206 +-- net/can/meson.build | 2 +- net/meson.build | 8 +- plugins/meson.build | 4 +- qga/meson.build | 16 +-- scsi/meson.build | 2 +- system/meson.build | 4 +- tests/fp/meson.build | 2 +- tests/meson.build| 2 +- tests/plugin/meson.build | 2 +- tests/qemu-iotests/meson.build | 2 +- tests/qtest/meson.build | 10 +- tests/unit/meson.build | 8 +- ui/dbus-display1.xml | 10 +- ui/meson.build | 8 +- util/meson.build | 8 +- 33 files changed, 197 insertions(+), 197 deletions(-) diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build index 1dad6bbbfbd..d25638d6c15 100644 --- a/accel/tcg/meson.build +++ b/accel/tcg/meson.build @@ -17,7 +17,7 @@ if get_option('plugins') tcg_ss.add(files('plugin-gen.c')) endif tcg_ss.add(when: libdw, if_true: files('debuginfo.c')) -if targetos == 'linux' +if host_os == 'linux' tcg_ss.add(files('perf.c')) endif specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss) diff --git a/backends/meson.build b/backends/meson.build index 6dee4e9203b..8b2b111497f 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -10,11 +10,11 @@ system_ss.add([files( 'confidential-guest-support.c', ), numa]) -if targetos != 'windows' +if host_os != 'windows' system_ss.add(files('rng-random.c')) system_ss.add(files('hostmem-file.c')) endif -if targetos == 'linux' +if host_os == 'linux' system_ss.add(files('hostmem-memfd.c')) endif if keyutils.found() diff --git a/block/meson.build b/block/meson.build index ddea1e40070..e1f03fd773e 100644 --- a/block/meson.build +++ b/block/meson.build @@ -88,13 +88,13 @@ if get_option('parallels').allowed() block_ss.add(files('parallels.c', 'parallels-ext.c')) endif -if targetos == 'windows' +if host_os == 'windows' block_ss.add(files('file-win32.c', 'win32-aio.c')) else block_ss.add(files('file-posix.c'), coref, iokit) endif block_ss.add(when: libiscsi, if_true: files('iscsi-opts.c')) -if targetos == 'linux' +if host_os == 'linux' block_ss.add(files('nvme.c')) endif if get_option('replication').allowed() diff --git a/bsd-user/meson.build b/bsd-user/meson.build index c6bfd3b2b53..39bad0ae33e 100644 --- a/bsd-user/meson.build +++ b/bsd-user/meson.build @@ -24,6 +24,6 @@ kvm = cc.find_library('kvm', required: true) bsd_user_ss.add(elf, procstat, kvm) # Pull in the OS-specific build glue, if any -subdir(targetos) +subdir(host_os) specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss) diff --git a/chardev/meson.build b/chardev/meson.build index db6840b71af..c80337d15fa 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -12,7 +12,7 @@ chardev_ss.add(files( 'char-udp.c', 'char.c', )) -if targetos == 'windows' +if host_os == 'windows' chardev_ss.add(files( 'char-console.c', 'char-win-stdio.c', @@ -23,7 +23,7 @@ else 'char-fd.c', 'char-pty.c', ), util) - if targetos in ['linux', 'gnu/kfreebsd', 'freebsd', 'dragonfly'] + if host_os in ['linux', 'gnu/kfreebsd', 'freebsd', 'dragonfly'] chardev_ss.add(files('char-parallel.c')) endif endif diff --git a/configure b/configure index 0128fd30ea8..21ab9a64e98 100755 --- a/configure +++ b/configure @@ -334,30 +334,30 @@ EOF } if check_define __linux__ ; then - targetos=linux + host_os=linux elif check_define _WIN32 ; then - targetos=windows + host_os=windows elif check_define __OpenBSD__ ; then - targetos=openbsd + host_os=openbsd elif check_define __sun__ ; then - targetos=sunos + host_os=sunos elif check_define __HAIKU__ ; then - targetos=haiku + host_os=haiku elif check_define __FreeBSD__ ; then - targetos=freebsd + host_os=freebsd elif check_define
[PULL 25/46] meson: fix type of "relocatable" option
Since the option is of boolean type, the default value should be a boolean rather than a string. Signed-off-by: Paolo Bonzini --- meson_options.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_options.txt b/meson_options.txt index c9baeda6395..0a99a059ec8 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -101,7 +101,7 @@ option('cfi_debug', type: 'boolean', value: false, description: 'Verbose errors in case of CFI violation') option('multiprocess', type: 'feature', value: 'auto', description: 'Out of process device emulation support') -option('relocatable', type : 'boolean', value : 'true', +option('relocatable', type : 'boolean', value : true, description: 'toggle relocatable install') option('vfio_user_server', type: 'feature', value: 'disabled', description: 'vfio-user server support') -- 2.43.0
[PULL 12/46] target/i386: do not decode string source/destination into decode->mem
decode->mem is only used if one operand has has_ea == true. String operations will not use decode->mem and will load A0 on their own, because they are the only case of two memory operands in a single instruction. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 20 ++-- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index d7a86d96c0c..99d18d2871e 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -1212,6 +1212,8 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, case X86_TYPE_None: /* Implicit or absent */ case X86_TYPE_A: /* Implicit */ case X86_TYPE_F: /* EFLAGS/RFLAGS */ +case X86_TYPE_X: /* string source */ +case X86_TYPE_Y: /* string destination */ break; case X86_TYPE_B: /* VEX. selects a GPR */ @@ -1346,24 +1348,6 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, op->n = insn_get(env, s, op->ot) >> 4; break; -case X86_TYPE_X: /* string source */ -op->n = -1; -decode->mem = (AddressParts) { -.def_seg = R_DS, -.base = R_ESI, -.index = -1, -}; -break; - -case X86_TYPE_Y: /* string destination */ -op->n = -1; -decode->mem = (AddressParts) { -.def_seg = R_ES, -.base = R_EDI, -.index = -1, -}; -break; - case X86_TYPE_2op: *op = decode->op[0]; break; -- 2.43.0
[PULL 17/46] target/i386: do not use s->tmp0 for jumps on ECX ==/!= 0
Create a new temporary, to ease the register allocator's work. Creation of the temporary is pushed into gen_ext_tl, which also allows NULL as the first parameter now. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index afe0fa6c65f..e5f71170967 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -720,6 +720,9 @@ static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign) if (size == MO_TL) { return src; } +if (!dst) { +dst = tcg_temp_new(); +} tcg_gen_ext_tl(dst, src, size | (sign ? MO_SIGN : 0)); return dst; } @@ -736,9 +739,9 @@ static void gen_exts(MemOp ot, TCGv reg) static void gen_op_j_ecx(DisasContext *s, TCGCond cond, TCGLabel *label1) { -tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]); -gen_extu(s->aflag, s->tmp0); -tcg_gen_brcondi_tl(cond, s->tmp0, 0, label1); +TCGv tmp = gen_ext_tl(NULL, cpu_regs[R_ECX], s->aflag, false); + +tcg_gen_brcondi_tl(cond, tmp, 0, label1); } static inline void gen_op_jz_ecx(DisasContext *s, TCGLabel *label1) -- 2.43.0
[PULL 34/46] meson: move accelerator dependency checks together
Signed-off-by: Paolo Bonzini --- meson.build | 175 +++- 1 file changed, 91 insertions(+), 84 deletions(-) diff --git a/meson.build b/meson.build index 2c6f09352c9..1867e0428b1 100644 --- a/meson.build +++ b/meson.build @@ -602,7 +602,10 @@ if sparse.found() '-Wno-non-pointer-null']) endif -# Target-specific libraries and flags +# +# Host-specific libraries and flags # +# + libm = cc.find_library('m', required: false) threads = dependency('threads') util = cc.find_library('util', required: false) @@ -612,8 +615,6 @@ version_res = [] coref = [] iokit = [] emulator_link_args = [] -nvmm =not_found -hvf = not_found midl = not_found widl = not_found pathcch = not_found @@ -649,7 +650,10 @@ elif targetos == 'openbsd' endif endif -# Target-specific configuration of accelerators +### +# Host-specific configuration of accelerators # +### + accelerators = [] if get_option('kvm').allowed() and targetos == 'linux' accelerators += 'CONFIG_KVM' @@ -662,6 +666,8 @@ if get_option('whpx').allowed() and targetos == 'windows' accelerators += 'CONFIG_WHPX' endif endif + +hvf = not_found if get_option('hvf').allowed() hvf = dependency('appleframeworks', modules: 'Hypervisor', required: get_option('hvf')) @@ -669,6 +675,8 @@ if get_option('hvf').allowed() accelerators += 'CONFIG_HVF' endif endif + +nvmm = not_found if targetos == 'netbsd' nvmm = cc.find_library('nvmm', required: get_option('nvmm')) if nvmm.found() @@ -716,6 +724,85 @@ if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled() error('WHPX not available on this platform') endif +xen = not_found +if get_option('xen').enabled() or (get_option('xen').auto() and have_system) + xencontrol = dependency('xencontrol', required: false, + method: 'pkg-config') + if xencontrol.found() +xen_pc = declare_dependency(version: xencontrol.version(), + dependencies: [ +xencontrol, +# disabler: true makes xen_pc.found() return false if any is not found +dependency('xenstore', required: false, + method: 'pkg-config', + disabler: true), +dependency('xenforeignmemory', required: false, + method: 'pkg-config', + disabler: true), +dependency('xengnttab', required: false, + method: 'pkg-config', + disabler: true), +dependency('xenevtchn', required: false, + method: 'pkg-config', + disabler: true), +dependency('xendevicemodel', required: false, + method: 'pkg-config', + disabler: true), +# optional, no "disabler: true" +dependency('xentoolcore', required: false, + method: 'pkg-config')]) +if xen_pc.found() + xen = xen_pc +endif + endif + if not xen.found() +xen_tests = [ '4.11.0', '4.10.0', '4.9.0', '4.8.0', '4.7.1' ] +xen_libs = { + '4.11.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ], + '4.10.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn', 'xentoolcore' ], + '4.9.0': [ 'xenstore', 'xenctrl', 'xendevicemodel', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ], + '4.8.0': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ], + '4.7.1': [ 'xenstore', 'xenctrl', 'xenforeignmemory', 'xengnttab', 'xenevtchn' ], +} +xen_deps = {} +foreach ver: xen_tests + # cache the various library tests to avoid polluting the logs + xen_test_deps = [] + foreach l: xen_libs[ver] +if l not in xen_deps + xen_deps += { l: cc.find_library(l, required: false) } +endif +xen_test_deps += xen_deps[l] + endforeach + + # Use -D to pick just one of the test programs in scripts/xen-detect.c + xen_version = ver.split('.') + xen_ctrl_version = xen_version[0] + \ +('0' + xen_version[1]).substring(-2) + \ +('0' + xen_version[2]).substring(-2) + if cc.links(files('scripts/xen-detect.c'), + args: '-DCONFIG_XEN_CTRL_INTERFACE_VERSION=' + xen_ctrl_version, + dependencies: xen_test_deps) +xen = declare_dependency(version: ver, dependencies: xen_test_deps) +break + endif +endforeach + endif + if xen.found() +accelerators += 'CONFIG_XEN' + elif get_option('xen').enabled() +error('could not compile and link Xen test program') + endif +endif +have_xen_pci_passthrough = get_option('xen_pci_passthrough') \ + .require(xen.found(), + error_message: 'Xen PCI passthro
[PULL 04/46] target/i386: remove unnecessary arguments from raise_interrupt
is_int is always 1, and error_code is always zero. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/excp_helper.c | 7 +++ target/i386/tcg/helper-tcg.h | 3 +-- target/i386/tcg/misc_helper.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c index 7c3c8dc7fe8..65e37ae2a0c 100644 --- a/target/i386/tcg/excp_helper.c +++ b/target/i386/tcg/excp_helper.c @@ -28,7 +28,7 @@ G_NORETURN void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend) { -raise_interrupt(env, intno, 1, 0, next_eip_addend); +raise_interrupt(env, intno, next_eip_addend); } G_NORETURN void helper_raise_exception(CPUX86State *env, int exception_index) @@ -112,10 +112,9 @@ void raise_interrupt2(CPUX86State *env, int intno, /* shortcuts to generate exceptions */ -G_NORETURN void raise_interrupt(CPUX86State *env, int intno, int is_int, -int error_code, int next_eip_addend) +G_NORETURN void raise_interrupt(CPUX86State *env, int intno, int next_eip_addend) { -raise_interrupt2(env, intno, is_int, error_code, next_eip_addend, 0); +raise_interrupt2(env, intno, 1, 0, next_eip_addend, 0); } G_NORETURN void raise_exception_err(CPUX86State *env, int exception_index, diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index cd1723389ad..ce34b737bb0 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -65,8 +65,7 @@ G_NORETURN void raise_exception_err(CPUX86State *env, int exception_index, int error_code); G_NORETURN void raise_exception_err_ra(CPUX86State *env, int exception_index, int error_code, uintptr_t retaddr); -G_NORETURN void raise_interrupt(CPUX86State *nenv, int intno, int is_int, -int error_code, int next_eip_addend); +G_NORETURN void raise_interrupt(CPUX86State *nenv, int intno, int next_eip_addend); G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr, MMUAccessType access_type, uintptr_t retaddr); diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c index babff061864..66b332a83c1 100644 --- a/target/i386/tcg/misc_helper.c +++ b/target/i386/tcg/misc_helper.c @@ -43,7 +43,7 @@ void helper_into(CPUX86State *env, int next_eip_addend) eflags = cpu_cc_compute_all(env, CC_OP); if (eflags & CC_O) { -raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend); +raise_interrupt(env, EXCP04_INTO, next_eip_addend); } } -- 2.43.0
[PULL 14/46] target/i386: do not clobber T0 on string operations
The new decoder would rather have the operand in T0 when expanding SCAS, rather than use R_EAX directly as gen_scas currently does. This makes SCAS more similar to CMP and SUB, in that CC_DST = T0 - T1. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 45 - 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index efef4e74d4c..00ed0cc9a31 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -522,9 +522,9 @@ void gen_op_add_reg_im(DisasContext *s, MemOp size, int reg, int32_t val) gen_op_mov_reg_v(s, size, reg, s->tmp0); } -static inline void gen_op_add_reg_T0(DisasContext *s, MemOp size, int reg) +static inline void gen_op_add_reg(DisasContext *s, MemOp size, int reg, TCGv val) { -tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0); +tcg_gen_add_tl(s->tmp0, cpu_regs[reg], val); gen_op_mov_reg_v(s, size, reg, s->tmp0); } @@ -707,10 +707,12 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s) gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1); } -static inline void gen_op_movl_T0_Dshift(DisasContext *s, MemOp ot) +static inline TCGv gen_compute_Dshift(DisasContext *s, MemOp ot) { -tcg_gen_ld32s_tl(s->T0, tcg_env, offsetof(CPUX86State, df)); -tcg_gen_shli_tl(s->T0, s->T0, ot); +TCGv dshift = tcg_temp_new(); +tcg_gen_ld32s_tl(dshift, tcg_env, offsetof(CPUX86State, df)); +tcg_gen_shli_tl(dshift, dshift, ot); +return dshift; }; static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign) @@ -818,13 +820,16 @@ static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port, static void gen_movs(DisasContext *s, MemOp ot) { +TCGv dshift; + gen_string_movl_A0_ESI(s); gen_op_ld_v(s, ot, s->T0, s->A0); gen_string_movl_A0_EDI(s); gen_op_st_v(s, ot, s->T0, s->A0); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_ESI); -gen_op_add_reg_T0(s, s->aflag, R_EDI); + +dshift = gen_compute_Dshift(s, ot); +gen_op_add_reg(s, s->aflag, R_ESI, dshift); +gen_op_add_reg(s, s->aflag, R_EDI, dshift); } static void gen_op_update1_cc(DisasContext *s) @@ -1249,8 +1254,7 @@ static void gen_stos(DisasContext *s, MemOp ot) gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); gen_string_movl_A0_EDI(s); gen_op_st_v(s, ot, s->T0, s->A0); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_EDI); +gen_op_add_reg(s, s->aflag, R_EDI, gen_compute_Dshift(s, ot)); } static void gen_lods(DisasContext *s, MemOp ot) @@ -1258,8 +1262,7 @@ static void gen_lods(DisasContext *s, MemOp ot) gen_string_movl_A0_ESI(s); gen_op_ld_v(s, ot, s->T0, s->A0); gen_op_mov_reg_v(s, ot, R_EAX, s->T0); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_ESI); +gen_op_add_reg(s, s->aflag, R_ESI, gen_compute_Dshift(s, ot)); } static void gen_scas(DisasContext *s, MemOp ot) @@ -1267,19 +1270,21 @@ static void gen_scas(DisasContext *s, MemOp ot) gen_string_movl_A0_EDI(s); gen_op_ld_v(s, ot, s->T1, s->A0); gen_op(s, OP_CMPL, ot, R_EAX); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_EDI); +gen_op_add_reg(s, s->aflag, R_EDI, gen_compute_Dshift(s, ot)); } static void gen_cmps(DisasContext *s, MemOp ot) { +TCGv dshift; + gen_string_movl_A0_EDI(s); gen_op_ld_v(s, ot, s->T1, s->A0); gen_string_movl_A0_ESI(s); gen_op(s, OP_CMPL, ot, OR_TMP0); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_ESI); -gen_op_add_reg_T0(s, s->aflag, R_EDI); + +dshift = gen_compute_Dshift(s, ot); +gen_op_add_reg(s, s->aflag, R_ESI, dshift); +gen_op_add_reg(s, s->aflag, R_EDI, dshift); } static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot) @@ -1307,8 +1312,7 @@ static void gen_ins(DisasContext *s, MemOp ot) tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0x); gen_helper_in_func(ot, s->T0, s->tmp2_i32); gen_op_st_v(s, ot, s->T0, s->A0); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_EDI); +gen_op_add_reg(s, s->aflag, R_EDI, gen_compute_Dshift(s, ot)); gen_bpt_io(s, s->tmp2_i32, ot); } @@ -1321,8 +1325,7 @@ static void gen_outs(DisasContext *s, MemOp ot) tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0x); tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0); gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); -gen_op_movl_T0_Dshift(s, ot); -gen_op_add_reg_T0(s, s->aflag, R_ESI); +gen_op_add_reg(s, s->aflag, R_ESI, gen_compute_Dshift(s, ot)); gen_bpt_io(s, s->tmp2_i32, ot); } -- 2.43.0
[PULL 20/46] target/i386: adjust decoding of J operand
gen_jcc() has been changed to accept a relative offset since the new decoder was written. Adjust the J operand, which is meant to be used with jump instructions such as gen_jcc(), to not include the program counter and to not truncate the result, as both operations are now performed by common code. The result is that J is now the same as the I operand. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 10 -- 1 file changed, 10 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 99d18d2871e..f30889dbc0a 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -1329,19 +1329,9 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, } case X86_TYPE_I: /* Immediate */ -op->unit = X86_OP_IMM; -decode->immediate = insn_get_signed(env, s, op->ot); -break; - case X86_TYPE_J: /* Relative offset for a jump */ op->unit = X86_OP_IMM; decode->immediate = insn_get_signed(env, s, op->ot); -decode->immediate += s->pc - s->cs_base; -if (s->dflag == MO_16) { -decode->immediate &= 0x; -} else if (!CODE64(s)) { -decode->immediate &= 0xu; -} break; case X86_TYPE_L: /* The upper 4 bits of the immediate select a 128-bit register */ -- 2.43.0
[PULL 11/46] target/i386: add X86_SPECIALs for MOVSX and MOVZX
Usually the registers are just moved into s->T0 without much care for their operand size. However, in some cases we can get more efficient code if the operand fetching logic syncs with the emission function on what is nicer. All the current uses are mostly demonstrative and only reduce the code in the emission functions, because the instructions do not support memory operands. However the logic is generic and applies to several more instructions such as MOVSXD (aka movslq), one-byte shift instructions, multiplications, XLAT, and indirect calls/jumps. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 18 ++ target/i386/tcg/decode-new.h | 4 +++ target/i386/tcg/emit.c.inc | 42 +--- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 00fdb243857..d7a86d96c0c 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -156,6 +156,8 @@ #define op0_Rd .special = X86_SPECIAL_Op0_Rd, #define op2_Ry .special = X86_SPECIAL_Op2_Ry, #define avx_movx .special = X86_SPECIAL_AVXExtMov, +#define sextT0 .special = X86_SPECIAL_SExtT0, +#define zextT0 .special = X86_SPECIAL_ZExtT0, #define vex1 .vex_class = 1, #define vex1_rep3 .vex_class = 1, .vex_special = X86_VEX_REPScalar, @@ -571,8 +573,8 @@ static const X86OpEntry opcodes_0F38_F0toFF[16][5] = { [5] = { X86_OP_ENTRY3(BZHI, G,y, E,y, B,y, vex13 cpuid(BMI1)), {}, -X86_OP_ENTRY3(PEXT, G,y, B,y, E,y, vex13 cpuid(BMI2)), -X86_OP_ENTRY3(PDEP, G,y, B,y, E,y, vex13 cpuid(BMI2)), +X86_OP_ENTRY3(PEXT, G,y, B,y, E,y, vex13 zextT0 cpuid(BMI2)), +X86_OP_ENTRY3(PDEP, G,y, B,y, E,y, vex13 zextT0 cpuid(BMI2)), {}, }, [6] = { @@ -583,10 +585,10 @@ static const X86OpEntry opcodes_0F38_F0toFF[16][5] = { {}, }, [7] = { -X86_OP_ENTRY3(BEXTR, G,y, E,y, B,y, vex13 cpuid(BMI1)), +X86_OP_ENTRY3(BEXTR, G,y, E,y, B,y, vex13 zextT0 cpuid(BMI1)), X86_OP_ENTRY3(SHLX, G,y, E,y, B,y, vex13 cpuid(BMI1)), -X86_OP_ENTRY3(SARX, G,y, E,y, B,y, vex13 cpuid(BMI1)), -X86_OP_ENTRY3(SHRX, G,y, E,y, B,y, vex13 cpuid(BMI1)), +X86_OP_ENTRY3(SARX, G,y, E,y, B,y, vex13 sextT0 cpuid(BMI1)), +X86_OP_ENTRY3(SHRX, G,y, E,y, B,y, vex13 zextT0 cpuid(BMI1)), {}, }, }; @@ -1905,6 +1907,12 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) } break; +case X86_SPECIAL_SExtT0: +case X86_SPECIAL_ZExtT0: +/* Handled in gen_load. */ +assert(decode.op[1].unit == X86_OP_INT); +break; + default: break; } diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index b253f7457ae..70b6717227f 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -191,6 +191,10 @@ typedef enum X86InsnSpecial { * become P/P/Q/N, and size "x" becomes "q". */ X86_SPECIAL_MMX, + +/* When loaded into s->T0, register operand 1 is zero/sign extended. */ +X86_SPECIAL_SExtT0, +X86_SPECIAL_ZExtT0, } X86InsnSpecial; /* diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index f5e44117eab..4c2006fdd09 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -232,9 +232,30 @@ static void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v) break; case X86_OP_INT: if (op->has_ea) { -gen_op_ld_v(s, op->ot, v, s->A0); +if (v == s->T0 && decode->e.special == X86_SPECIAL_SExtT0) { +gen_op_ld_v(s, op->ot | MO_SIGN, v, s->A0); +} else { +gen_op_ld_v(s, op->ot, v, s->A0); +} + +} else if (op->ot == MO_8 && byte_reg_is_xH(s, op->n)) { +if (v == s->T0 && decode->e.special == X86_SPECIAL_SExtT0) { +tcg_gen_sextract_tl(v, cpu_regs[op->n - 4], 8, 8); +} else { +tcg_gen_extract_tl(v, cpu_regs[op->n - 4], 8, 8); +} + +} else if (op->ot < MO_TL && v == s->T0 && + (decode->e.special == X86_SPECIAL_SExtT0 || +decode->e.special == X86_SPECIAL_ZExtT0)) { +if (decode->e.special == X86_SPECIAL_SExtT0) { +tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot | MO_SIGN); +} else { +tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot); +} + } else { -gen_op_mov_v_reg(s, op->ot, v, op->n); +tcg_gen_mov_tl(v, cpu_regs[op->n]); } break; case X86_OP_IMM: @@ -1084,9 +1105,6 @@ static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) * Shifts larger than operand size get zeros. */ tcg_gen_ext8u_tl(s->A0, s->T1); -if (TARGET_LONG_
[PULL 18/46] target/i386: prepare for implementation of STOS/SCAS in new decoder
Do not use gen_op, and pull the load from the accumulator into disas_insn. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index e5f71170967..ecbd80a19ad 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1264,7 +1264,6 @@ static TCGLabel *gen_jz_ecx_string(DisasContext *s) static void gen_stos(DisasContext *s, MemOp ot) { -gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); gen_string_movl_A0_EDI(s); gen_op_st_v(s, ot, s->T0, s->A0); gen_op_add_reg(s, s->aflag, R_EDI, gen_compute_Dshift(s, ot)); @@ -1282,7 +1281,11 @@ static void gen_scas(DisasContext *s, MemOp ot) { gen_string_movl_A0_EDI(s); gen_op_ld_v(s, ot, s->T1, s->A0); -gen_op(s, OP_CMPL, ot, R_EAX); +tcg_gen_mov_tl(cpu_cc_src, s->T1); +tcg_gen_mov_tl(s->cc_srcT, s->T0); +tcg_gen_sub_tl(cpu_cc_dst, s->T0, s->T1); +set_cc_op(s, CC_OP_SUBB + ot); + gen_op_add_reg(s, s->aflag, R_EDI, gen_compute_Dshift(s, ot)); } @@ -4952,6 +4955,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) case 0xaa: /* stosS */ case 0xab: ot = mo_b_d(b, dflag); +gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_stos(s, ot); } else { @@ -4970,6 +4974,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) case 0xae: /* scasS */ case 0xaf: ot = mo_b_d(b, dflag); +gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); if (prefixes & PREFIX_REPNZ) { gen_repz_scas(s, ot, 1); } else if (prefixes & PREFIX_REPZ) { -- 2.43.0
[PULL 02/46] target/i386: optimize computation of JL and JLE from flags
Take advantage of the fact that there can be no 1 bits between SF and OF. If they were adjacent, you could sum SF and get a carry only if SF was already set. Then the value of OF in the sum is the XOR of OF itself, the carry (which is SF) and 0 (the value of the OF bit in the addend): this is OF^SF exactly. Because OF and SF are not adjacent, just place more 1 bits to the left so that the carry propagates, which means summing CC_O - CC_S. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 037bc47e7c2..8fb80011a22 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1126,10 +1126,9 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) if (reg == cpu_cc_src) { reg = s->tmp0; } -tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */ -tcg_gen_xor_tl(reg, reg, cpu_cc_src); +tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg, - .mask = CC_S }; + .mask = CC_O }; break; default: case JCC_LE: @@ -1137,10 +1136,9 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) if (reg == cpu_cc_src) { reg = s->tmp0; } -tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */ -tcg_gen_xor_tl(reg, reg, cpu_cc_src); +tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S); cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg, - .mask = CC_S | CC_Z }; + .mask = CC_O | CC_Z }; break; } break; -- 2.43.0
[PULL 10/46] target/i386: rename zext0/zext2 and make them closer to the manual
X86_SPECIAL_ZExtOp0 and X86_SPECIAL_ZExtOp2 are poorly named; they are a hack that is needed by scalar insertion and extraction instructions, and not really related to zero extension: for PEXTR the zero extension is done by the generation functions, for PINSR the high bits are not used at all and in fact are *not* filled with zeroes when loaded into s->T1. Rename the values to match the effect described in the manual, and explain better in the comments. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 16 target/i386/tcg/decode-new.h | 17 + 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 5eb2e9d0224..00fdb243857 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -153,8 +153,8 @@ #define xchg .special = X86_SPECIAL_Locked, #define lock .special = X86_SPECIAL_HasLock, #define mmx .special = X86_SPECIAL_MMX, -#define zext0 .special = X86_SPECIAL_ZExtOp0, -#define zext2 .special = X86_SPECIAL_ZExtOp2, +#define op0_Rd .special = X86_SPECIAL_Op0_Rd, +#define op2_Ry .special = X86_SPECIAL_Op2_Ry, #define avx_movx .special = X86_SPECIAL_AVXExtMov, #define vex1 .vex_class = 1, @@ -632,13 +632,13 @@ static const X86OpEntry opcodes_0F3A[256] = { [0x05] = X86_OP_ENTRY3(VPERMILPD_i, V,x, W,x, I,b, vex6 chk(W0) cpuid(AVX) p_66), [0x06] = X86_OP_ENTRY4(VPERM2x128, V,qq, H,qq, W,qq, vex6 chk(W0) cpuid(AVX) p_66), -[0x14] = X86_OP_ENTRY3(PEXTRB, E,b, V,dq, I,b, vex5 cpuid(SSE41) zext0 p_66), -[0x15] = X86_OP_ENTRY3(PEXTRW, E,w, V,dq, I,b, vex5 cpuid(SSE41) zext0 p_66), +[0x14] = X86_OP_ENTRY3(PEXTRB, E,b, V,dq, I,b, vex5 cpuid(SSE41) op0_Rd p_66), +[0x15] = X86_OP_ENTRY3(PEXTRW, E,w, V,dq, I,b, vex5 cpuid(SSE41) op0_Rd p_66), [0x16] = X86_OP_ENTRY3(PEXTR, E,y, V,dq, I,b, vex5 cpuid(SSE41) p_66), [0x17] = X86_OP_ENTRY3(VEXTRACTPS, E,d, V,dq, I,b, vex5 cpuid(SSE41) p_66), [0x1d] = X86_OP_ENTRY3(VCVTPS2PH, W,xh, V,x, I,b, vex11 chk(W0) cpuid(F16C) p_66), -[0x20] = X86_OP_ENTRY4(PINSRB, V,dq, H,dq, E,b, vex5 cpuid(SSE41) zext2 p_66), +[0x20] = X86_OP_ENTRY4(PINSRB, V,dq, H,dq, E,b, vex5 cpuid(SSE41) op2_Ry p_66), [0x21] = X86_OP_GROUP0(VINSERTPS), [0x22] = X86_OP_ENTRY4(PINSR, V,dq, H,dq, E,y, vex5 cpuid(SSE41) p_66), @@ -1883,17 +1883,17 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) case X86_SPECIAL_HasLock: break; -case X86_SPECIAL_ZExtOp0: +case X86_SPECIAL_Op0_Rd: assert(decode.op[0].unit == X86_OP_INT); if (!decode.op[0].has_ea) { decode.op[0].ot = MO_32; } break; -case X86_SPECIAL_ZExtOp2: +case X86_SPECIAL_Op2_Ry: assert(decode.op[2].unit == X86_OP_INT); if (!decode.op[2].has_ea) { -decode.op[2].ot = MO_32; +decode.op[2].ot = s->dflag == MO_16 ? MO_32 : s->dflag; } break; diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index 611bfddd957..b253f7457ae 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -165,11 +165,20 @@ typedef enum X86InsnSpecial { X86_SPECIAL_Locked, /* - * Register operand 0/2 is zero extended to 32 bits. Rd/Mb or Rd/Mw - * in the manual. + * Rd/Mb or Rd/Mw in the manual: register operand 0 is treated as 32 bits + * (and writeback zero-extends it to 64 bits if applicable). PREFIX_DATA + * does not trigger 16-bit writeback and, as a side effect, high-byte + * registers are never used. */ -X86_SPECIAL_ZExtOp0, -X86_SPECIAL_ZExtOp2, +X86_SPECIAL_Op0_Rd, + +/* + * Ry/Mb in the manual (PINSRB). However, the high bits are never used by + * the instruction in either the register or memory cases; the *real* effect + * of this modifier is that high-byte registers are never used, even without + * a REX prefix. Therefore, PINSRW does not need it despite having Ry/Mw. + */ +X86_SPECIAL_Op2_Ry, /* * Register operand 2 is extended to full width, while a memory operand -- 2.43.0
[PULL 15/46] target/i386: split eflags computation out of gen_compute_eflags
The new x86 decoder wants the gen_* functions to compute EFLAGS before writeback, which can be an issue for instructions with a memory destination such as ARPL or shifts. Extract code to compute the EFLAGS without clobbering CC_SRC, in case the memory write causes a fault. The flags writeback mechanism will take care of copying the result to CC_SRC. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 28 +++- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 00ed0cc9a31..b79c312465b 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -862,22 +862,22 @@ static void gen_op_update_neg_cc(DisasContext *s) tcg_gen_movi_tl(s->cc_srcT, 0); } -/* compute all eflags to cc_src */ -static void gen_compute_eflags(DisasContext *s) +/* compute all eflags to reg */ +static void gen_mov_eflags(DisasContext *s, TCGv reg) { -TCGv zero, dst, src1, src2; +TCGv dst, src1, src2; +TCGv_i32 cc_op; int live, dead; if (s->cc_op == CC_OP_EFLAGS) { +tcg_gen_mov_tl(reg, cpu_cc_src); return; } if (s->cc_op == CC_OP_CLR) { -tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P); -set_cc_op(s, CC_OP_EFLAGS); +tcg_gen_movi_tl(reg, CC_Z | CC_P); return; } -zero = NULL; dst = cpu_cc_dst; src1 = cpu_cc_src; src2 = cpu_cc_src2; @@ -886,7 +886,7 @@ static void gen_compute_eflags(DisasContext *s) live = cc_op_live[s->cc_op] & ~USES_CC_SRCT; dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2); if (dead) { -zero = tcg_constant_tl(0); +TCGv zero = tcg_constant_tl(0); if (dead & USES_CC_DST) { dst = zero; } @@ -898,8 +898,18 @@ static void gen_compute_eflags(DisasContext *s) } } -gen_update_cc_op(s); -gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op); +if (s->cc_op != CC_OP_DYNAMIC) { +cc_op = tcg_constant_i32(s->cc_op); +} else { +cc_op = cpu_cc_op; +} +gen_helper_cc_compute_all(reg, dst, src1, src2, cc_op); +} + +/* compute all eflags to cc_src */ +static void gen_compute_eflags(DisasContext *s) +{ +gen_mov_eflags(s, cpu_cc_src); set_cc_op(s, CC_OP_EFLAGS); } -- 2.43.0
[PULL 13/46] target/i386: do not clobber A0 in POP translation
The new decoder likes to compute the address in A0 very early, so the gen_lea_v_seg in gen_pop_T0 would clobber the address of the memory operand. Instead use T0 since it is already available and will be overwritten immediately after. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 34 -- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 73b83e07e23..efef4e74d4c 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -635,17 +635,17 @@ static TCGv eip_cur_tl(DisasContext *s) } } -/* Compute SEG:REG into A0. SEG is selected from the override segment +/* Compute SEG:REG into DEST. SEG is selected from the override segment (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to indicate no override. */ -static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0, - int def_seg, int ovr_seg) +static void gen_lea_v_seg_dest(DisasContext *s, MemOp aflag, TCGv dest, TCGv a0, + int def_seg, int ovr_seg) { switch (aflag) { #ifdef TARGET_X86_64 case MO_64: if (ovr_seg < 0) { -tcg_gen_mov_tl(s->A0, a0); +tcg_gen_mov_tl(dest, a0); return; } break; @@ -656,14 +656,14 @@ static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0, ovr_seg = def_seg; } if (ovr_seg < 0) { -tcg_gen_ext32u_tl(s->A0, a0); +tcg_gen_ext32u_tl(dest, a0); return; } break; case MO_16: /* 16 bit address */ -tcg_gen_ext16u_tl(s->A0, a0); -a0 = s->A0; +tcg_gen_ext16u_tl(dest, a0); +a0 = dest; if (ovr_seg < 0) { if (ADDSEG(s)) { ovr_seg = def_seg; @@ -680,17 +680,23 @@ static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0, TCGv seg = cpu_seg_base[ovr_seg]; if (aflag == MO_64) { -tcg_gen_add_tl(s->A0, a0, seg); +tcg_gen_add_tl(dest, a0, seg); } else if (CODE64(s)) { -tcg_gen_ext32u_tl(s->A0, a0); -tcg_gen_add_tl(s->A0, s->A0, seg); +tcg_gen_ext32u_tl(dest, a0); +tcg_gen_add_tl(dest, dest, seg); } else { -tcg_gen_add_tl(s->A0, a0, seg); -tcg_gen_ext32u_tl(s->A0, s->A0); +tcg_gen_add_tl(dest, a0, seg); +tcg_gen_ext32u_tl(dest, dest); } } } +static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0, + int def_seg, int ovr_seg) +{ +gen_lea_v_seg_dest(s, aflag, s->A0, a0, def_seg, ovr_seg); +} + static inline void gen_string_movl_A0_ESI(DisasContext *s) { gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override); @@ -2576,8 +2582,8 @@ static MemOp gen_pop_T0(DisasContext *s) { MemOp d_ot = mo_pushpop(s, s->dflag); -gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1); -gen_op_ld_v(s, d_ot, s->T0, s->A0); +gen_lea_v_seg_dest(s, mo_stacksize(s), s->T0, cpu_regs[R_ESP], R_SS, -1); +gen_op_ld_v(s, d_ot, s->T0, s->T0); return d_ot; } -- 2.43.0
[PULL 00/46] (mostly) target/i386 and meson changes for 2023-12-31
The following changes since commit 191710c221f65b1542f6ea7fa4d30dde6e134fd7: Merge tag 'pull-request-2023-12-20' of https://gitlab.com/thuth/qemu into staging (2023-12-20 09:40:16 -0500) are available in the Git repository at: https://gitlab.com/bonzini/qemu.git tags/for-upstream for you to fetch changes up to f705c1f25d9a075534f8279048082af4ce2066bf: meson.build: report graphics backends separately (2023-12-31 09:11:29 +0100) * configure: use a native non-cross compiler for linux-user * meson: cleanups * target/i386: miscellaneous cleanups and optimizations * target/i386: implement CMPccXADD * target/i386: the sgx_epc_get_section stub is reachable * esp: check for NULL result from scsi_device_find() Alex Bennée (1): meson.build: report graphics backends separately Alexandra Diupina (1): esp: check for NULL result from scsi_device_find() Paolo Bonzini (44): configure: use a native non-cross compiler for linux-user target/i386: optimize computation of JL and JLE from flags target/i386: speedup JO/SETO after MUL or IMUL target/i386: remove unnecessary arguments from raise_interrupt target/i386: remove unnecessary truncations target/i386: clean up cpu_cc_compute_all target/i386: document more deviations from the manual target/i386: reimplement check for validity of LOCK prefix target/i386: avoid trunc and ext for MULX and RORX target/i386: rename zext0/zext2 and make them closer to the manual target/i386: add X86_SPECIALs for MOVSX and MOVZX target/i386: do not decode string source/destination into decode->mem target/i386: do not clobber A0 in POP translation target/i386: do not clobber T0 on string operations target/i386: split eflags computation out of gen_compute_eflags target/i386: do not use s->tmp4 for push target/i386: do not use s->tmp0 for jumps on ECX ==/!= 0 target/i386: prepare for implementation of STOS/SCAS in new decoder target/i386: move operand load and writeback out of gen_cmovcc1 target/i386: adjust decoding of J operand target/i386: introduce flags writeback mechanism target/i386: implement CMPccXADD target/i386: the sgx_epc_get_section stub is reachable meson: fix type of "relocatable" option meson: remove unused variable meson: use version_compare() to compare version Makefile: clean qemu-iotests output configure: remove unnecessary subshell configure: unify again the case arms in probe_target_compiler meson: add more sections to main meson.build meson: move program checks together meson: move option validation together meson: move accelerator dependency checks together meson: keep subprojects together meson: move CFI detection code with other compiler flags meson: move config-host.h definitions together meson: move subdirs to "Collect sources" section meson: always probe u2f and canokey if the option is enabled meson: remove OS definitions from config_targetos meson: remove CONFIG_POSIX and CONFIG_WIN32 from config_targetos meson: remove config_targetos meson: remove CONFIG_ALL meson: rename config_all configure, meson: rename targetos to host_os Makefile | 1 + accel/tcg/meson.build| 4 +- backends/meson.build | 10 +- block/meson.build| 11 +- bsd-user/meson.build | 2 +- chardev/meson.build | 28 +- configure| 159 +++--- contrib/ivshmem-client/meson.build | 2 +- contrib/ivshmem-server/meson.build | 2 +- contrib/vhost-user-blk/meson.build | 2 +- contrib/vhost-user-input/meson.build | 2 +- contrib/vhost-user-scsi/meson.build | 2 +- docs/devel/build-system.rst | 15 - docs/devel/kconfig.rst | 2 +- fsdev/meson.build| 6 +- gdbstub/meson.build | 4 +- hw/9pfs/meson.build | 7 +- hw/acpi/meson.build | 5 - hw/cxl/meson.build | 2 - hw/display/meson.build | 8 +- hw/i386/sgx-stub.c | 2 +- hw/mem/meson.build | 1 - hw/mips/meson.build | 2 +- hw/net/meson.build | 2 - hw/pci-bridge/meson.build| 2 - hw/pci/meson.build | 1 - hw/ppc/meson.build | 8 +- hw/remote/meson.build| 1 - hw/scsi/esp.c| 9 + hw/smbios/meson.build| 5 - hw/usb/meson.build | 8 +- hw/virtio/meson.build| 2 - meson.build | 943 +++
[PULL 09/46] target/i386: avoid trunc and ext for MULX and RORX
Use _tl operations for 32-bit operands on 32-bit targets, and only go through trunc and extu ops for 64-bit targets. While the trunc/ext ops should be pretty much free after optimization, the optimizer also does not like having the same temporary used in multiple EBBs. Therefore it is nicer to not use tmpN* unless necessary. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 37 + 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 98c4c9569ef..f5e44117eab 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1348,7 +1348,8 @@ static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) /* low part of result in VEX., high in MODRM */ switch (ot) { -default: +case MO_32: +#ifdef TARGET_X86_64 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32, @@ -1356,13 +1357,15 @@ static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32); tcg_gen_extu_i32_tl(s->T0, s->tmp3_i32); break; -#ifdef TARGET_X86_64 -case MO_64: -tcg_gen_mulu2_i64(cpu_regs[s->vex_v], s->T0, s->T0, s->T1); -break; -#endif -} +case MO_64: +#endif +tcg_gen_mulu2_tl(cpu_regs[s->vex_v], s->T0, s->T0, s->T1); +break; + +default: +g_assert_not_reached(); +} } static void gen_PALIGNR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) @@ -1765,14 +1768,24 @@ static void gen_PSLLDQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { MemOp ot = decode->op[0].ot; -int b = decode->immediate; +int mask = ot == MO_64 ? 63 : 31; +int b = decode->immediate & mask; -if (ot == MO_64) { -tcg_gen_rotri_tl(s->T0, s->T0, b & 63); -} else { +switch (ot) { +case MO_32: +#ifdef TARGET_X86_64 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); -tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31); +tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b); tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); +break; + +case MO_64: +#endif +tcg_gen_rotri_tl(s->T0, s->T0, b); +break; + +default: +g_assert_not_reached(); } } -- 2.43.0
[PULL 08/46] target/i386: reimplement check for validity of LOCK prefix
The previous check erroneously allowed CMP to be modified with LOCK. Instead, tag explicitly the instructions that do support LOCK. Acked-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 17 ++--- target/i386/tcg/decode-new.h | 3 +++ target/i386/tcg/emit.c.inc | 5 - 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 232c6a45c96..5eb2e9d0224 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -151,6 +151,7 @@ #define cpuid(feat) .cpuid = X86_FEAT_##feat, #define xchg .special = X86_SPECIAL_Locked, +#define lock .special = X86_SPECIAL_HasLock, #define mmx .special = X86_SPECIAL_MMX, #define zext0 .special = X86_SPECIAL_ZExtOp0, #define zext2 .special = X86_SPECIAL_ZExtOp2, @@ -1103,10 +1104,6 @@ static int decode_modrm(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod { int modrm = get_modrm(s, env); if ((modrm >> 6) == 3) { -if (s->prefix & PREFIX_LOCK) { -decode->e.gen = gen_illegal; -return 0xff; -} op->n = (modrm & 7); if (type != X86_TYPE_Q && type != X86_TYPE_N) { op->n |= REX_B(s); @@ -1881,6 +1878,9 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) if (decode.op[0].has_ea) { s->prefix |= PREFIX_LOCK; } +decode.e.special = X86_SPECIAL_HasLock; +/* fallthrough */ +case X86_SPECIAL_HasLock: break; case X86_SPECIAL_ZExtOp0: @@ -1909,6 +1909,12 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) break; } +if (s->prefix & PREFIX_LOCK) { +if (decode.e.special != X86_SPECIAL_HasLock || !decode.op[0].has_ea) { +goto illegal_op; +} +} + if (!validate_vex(s, &decode)) { return; } @@ -1952,9 +1958,6 @@ static void disas_insn_new(DisasContext *s, CPUState *cpu, int b) gen_load_ea(s, &decode.mem, decode.e.vex_class == 12); } if (s->prefix & PREFIX_LOCK) { -if (decode.op[0].unit != X86_OP_INT || !decode.op[0].has_ea) { -goto illegal_op; -} gen_load(s, &decode, 2, s->T1); decode.e.gen(s, env, &decode); } else { diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h index e6c904a3192..611bfddd957 100644 --- a/target/i386/tcg/decode-new.h +++ b/target/i386/tcg/decode-new.h @@ -158,6 +158,9 @@ typedef enum X86InsnCheck { typedef enum X86InsnSpecial { X86_SPECIAL_None, +/* Accepts LOCK prefix; LOCKed operations do not load or writeback operand 0 */ +X86_SPECIAL_HasLock, + /* Always locked if it has a memory operand (XCHG) */ X86_SPECIAL_Locked, diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index d444d83e534..98c4c9569ef 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -55,11 +55,6 @@ static void gen_NM_exception(DisasContext *s) gen_exception(s, EXCP07_PREX); } -static void gen_illegal(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) -{ -gen_illegal_opcode(s); -} - static void gen_load_ea(DisasContext *s, AddressParts *mem, bool is_vsib) { TCGv ea = gen_lea_modrm_1(s, *mem, is_vsib); -- 2.43.0
[PULL 07/46] target/i386: document more deviations from the manual
Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/decode-new.c.inc | 12 1 file changed, 12 insertions(+) diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc index 2bdbb1bba0f..232c6a45c96 100644 --- a/target/i386/tcg/decode-new.c.inc +++ b/target/i386/tcg/decode-new.c.inc @@ -26,6 +26,13 @@ * size (X86_SIZE_*) codes used in the manual. There are a few differences * though. * + * Operand sizes + * - + * + * The manual lists d64 ("cannot encode 32-bit size in 64-bit mode") and f64 + * ("cannot encode 16-bit or 32-bit size in 64-bit mode") as modifiers of the + * "v" or "z" sizes. The decoder simply makes them separate operand sizes. + * * Vector operands * --- * @@ -44,6 +51,11 @@ * if the difference is expressed via prefixes. Individual instructions * are separated by prefix in the generator functions. * + * There is a custom size "xh" used to address half of a SSE/AVX operand. + * This points to a 64-bit operand for SSE operations, 128-bit operand + * for 256-bit AVX operands, etc. It is used for conversion operations + * such as VCVTPH2PS or VCVTSS2SD. + * * There are a couple cases in which instructions (e.g. MOVD) write the * whole XMM or MM register but are established incorrectly in the manual * as "d" or "q". These have to be fixed for the decoder to work correctly. -- 2.43.0
[PULL 05/46] target/i386: remove unnecessary truncations
gen_lea_v_seg (called by gen_add_A0_ds_seg) already zeroes any bits of s->A0 beyond s->aflag. It does so before summing the segment base and, if not in 64-bit mode, also after summing it. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/emit.c.inc | 4 +--- target/i386/tcg/translate.c | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 82da5488d47..d444d83e534 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1242,9 +1242,7 @@ static void gen_LDMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod static void gen_MASKMOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) { -tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]); -gen_extu(s->aflag, s->A0); -gen_add_A0_ds_seg(s); +gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_DS, s->override); if (s->prefix & PREFIX_DATA) { gen_helper_maskmov_xmm(tcg_env, OP_PTR1, OP_PTR2, s->A0); diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index a16eb8d4008..73b83e07e23 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -4183,7 +4183,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]); tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]); tcg_gen_add_tl(s->A0, s->A0, s->T0); -gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); gen_op_ld_v(s, MO_8, s->T0, s->A0); gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0); @@ -5835,7 +5834,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu) gen_update_cc_op(s); gen_update_eip_cur(s); tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]); -gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); gen_helper_monitor(tcg_env, s->A0); break; -- 2.43.0