[QEMU-devel][RFC PATCH 1/1] backends/hostmem: qapi/qom: Add an ObjectOption for memory-backend-* called HostMemType and its arg 'cxlram'

2023-12-31 Thread Ho-Ren (Jack) Chuang
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

2023-12-31 Thread Richard Henderson

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

2023-12-31 Thread Richard Henderson

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

2023-12-31 Thread Richard Henderson

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

2023-12-31 Thread Bryan Zhang
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

2023-12-31 Thread Bryan Zhang
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

2023-12-31 Thread Bryan Zhang
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

2023-12-31 Thread Bryan Zhang
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.

2023-12-31 Thread Bryan Zhang
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

2023-12-31 Thread BALATON Zoltan

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

2023-12-31 Thread BALATON Zoltan

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

2023-12-31 Thread BALATON Zoltan

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

2023-12-31 Thread Heinrich Schuchardt

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

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Avihai Horon
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()

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Avihai Horon
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()

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Avihai Horon
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()

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Avihai Horon
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()

2023-12-31 Thread Avihai Horon
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()

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Avihai Horon
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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()

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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

2023-12-31 Thread Paolo Bonzini
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