[PULL 12/27] s390x: select correct components for no-board build

2024-05-12 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
Reviewed-by: Thomas Huth 
Message-ID: <20240509170044.190795-5-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 .gitlab-ci.d/buildtest.yml | 4 ++--
 target/s390x/Kconfig   | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 786c8f92090..8ca3e0586c7 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
 # Check our reduced build configurations
 # requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
 #   mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, s390x, x86_64
+# does not build without boards: i386, x86_64
 build-without-defaults:
   extends: .native_build_job_template
   needs:
@@ -666,7 +666,7 @@ build-without-defaults:
   --disable-strip
 TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
   mips-softmmu mips64-softmmu mipsel-softmmu
-  sh4-softmmu sh4eb-softmmu sparc-softmmu
+  s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
   sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
   hexagon-linux-user i386-linux-user s390x-linux-user
 MAKE_CHECK_ARGS: check
diff --git a/target/s390x/Kconfig b/target/s390x/Kconfig
index 72da48136c6..d886be48b47 100644
--- a/target/s390x/Kconfig
+++ b/target/s390x/Kconfig
@@ -1,2 +1,4 @@
 config S390X
 bool
+select PCI
+select S390_FLIC
-- 
2.45.0




[PULL 16/27] i386: correctly select code in hw/i386 that depends on other components

2024-05-12 Thread Paolo Bonzini
fw_cfg.c and vapic.c are currently included unconditionally but
depend on other components.  vapic.c depends on the local APIC,
while fw_cfg.c includes a piece of AML builder code that depends
on CONFIG_ACPI.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Zhao Liu 
Message-ID: <20240509170044.190795-9-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 hw/i386/fw_cfg.c| 2 ++
 hw/i386/meson.build | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index d802d2787f0..6e0d9945d07 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -203,6 +203,7 @@ void fw_cfg_build_feature_control(MachineState *ms, 
FWCfgState *fw_cfg)
 fw_cfg_add_file(fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
 }
 
+#ifdef CONFIG_ACPI
 void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
 {
 /*
@@ -229,3 +230,4 @@ void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
 aml_append(dev, aml_name_decl("_CRS", crs));
 aml_append(scope, dev);
 }
+#endif
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index d8b70ef3e9c..d9da676038c 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -1,12 +1,12 @@
 i386_ss = ss.source_set()
 i386_ss.add(files(
   'fw_cfg.c',
-  'vapic.c',
   'e820_memory_layout.c',
   'multiboot.c',
   'x86.c',
 ))
 
+i386_ss.add(when: 'CONFIG_APIC', if_true: files('vapic.c'))
 i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
   if_false: files('x86-iommu-stub.c'))
 i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'),
-- 
2.45.0




[PULL 22/27] meson: pick libfdt from common_ss when building target-specific files

2024-05-12 Thread Paolo Bonzini
Avoid having to list dependencies such as libfdt twice, both on common_ss
and specific_ss.  Instead, just take all the dependencies in common_ss
and allow the target-specific libqemu-*.fa library to use them.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 meson.build  | 14 +++---
 hw/arm/meson.build   |  2 +-
 hw/loongarch/meson.build |  2 +-
 hw/mips/meson.build  |  2 +-
 hw/openrisc/meson.build  |  4 ++--
 hw/ppc/meson.build   |  4 +---
 hw/riscv/meson.build |  2 +-
 7 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/meson.build b/meson.build
index 83ae4347c7f..ab1f44b25c2 100644
--- a/meson.build
+++ b/meson.build
@@ -3867,15 +3867,23 @@ foreach target : target_dirs
 
   target_common = common_ss.apply(config_target, strict: false)
   objects = common_all.extract_objects(target_common.sources())
-  deps = target_common.dependencies()
+  arch_deps += target_common.dependencies()
 
   target_specific = specific_ss.apply(config_target, strict: false)
   arch_srcs += target_specific.sources()
   arch_deps += target_specific.dependencies()
 
+  # allow using headers from the dependencies but do not include the sources,
+  # because this emulator only needs those in "objects".  For external
+  # dependencies, the full dependency is included below in the executable.
+  lib_deps = []
+  foreach dep : arch_deps
+lib_deps += dep.partial_dependency(compile_args: true, includes: true)
+  endforeach
+
   lib = static_library('qemu-' + target,
  sources: arch_srcs + genh,
- dependencies: arch_deps,
+ dependencies: lib_deps,
  objects: objects,
  include_directories: target_inc,
  c_args: c_args,
@@ -3923,7 +3931,7 @@ foreach target : target_dirs
 emulator = executable(exe_name, exe['sources'],
install: true,
c_args: c_args,
-   dependencies: arch_deps + deps + exe['dependencies'],
+   dependencies: arch_deps + exe['dependencies'],
objects: lib.extract_all_objects(recursive: true),
link_depends: [block_syms, qemu_syms],
link_args: link_args,
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 6808135c1f7..aefde0c69a3 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -1,5 +1,5 @@
 arm_ss = ss.source_set()
-arm_ss.add(files('boot.c'), fdt)
+arm_ss.add(files('boot.c'))
 arm_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c'))
 arm_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
 arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c'))
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index d306d82c2ee..bce7ebac97e 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -3,7 +3,7 @@ loongarch_ss.add(files(
 'fw_cfg.c',
 'boot.c',
 ))
-loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('virt.c'), 
fdt])
+loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('virt.c'))
 loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
 
 hw_arch += {'loongarch': loongarch_ss}
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index f06d88f3430..ca37c42d900 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -9,7 +9,7 @@ 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'))
-mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: [files('boston.c'), fdt])
+mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: files('boston.c'))
 endif
 
 hw_arch += {'mips': mips_ss}
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index 2dbc6365bb7..82f1f0ef1cc 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,7 +1,7 @@
 openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(files('boot.c'))
-openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
-openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: files('openrisc_sim.c'))
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: files('virt.c'))
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index d096636ee7f..3ebbf329bcc 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -3,9 +3,7 @@ ppc_ss.add(files(
   'ppc.c',
   'ppc_booke.c',
 ))
-ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: [files(
-  'fdt.c',
-), fdt])
+ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: files('fdt.c'))
 ppc_ss.add(when: 'CONFIG_FW_CFG_PPC', if_true: files('fw_cfg.c'))
 
 # IBM pSeries (sPAPR)
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 2f7ee81be3c..f872674093a 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/m

[PULL 09/27] s390x: move s390_cpu_addr2state to target/s390x/sigp.c

2024-05-12 Thread Paolo Bonzini
This function has no dependency on the virtio-ccw machine type, though it
assumes that the CPU address corresponds to the core_id and the index.

If there is any need of something different or more fancy (unlikely)
S390 can include a MachineClass subclass and implement it there.  For
now, move it to sigp.c for simplicity.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Thomas Huth 
Message-ID: <20240509170044.190795-2-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 hw/s390x/s390-virtio-ccw.c | 16 
 target/s390x/sigp.c| 17 +
 2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 2afaf45ce60..42628fc45d2 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -50,22 +50,6 @@
 
 static Error *pv_mig_blocker;
 
-S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
-{
-static MachineState *ms;
-
-if (!ms) {
-ms = MACHINE(qdev_get_machine());
-g_assert(ms->possible_cpus);
-}
-
-/* CPU address corresponds to the core_id and the index */
-if (cpu_addr >= ms->possible_cpus->len) {
-return NULL;
-}
-return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
-}
-
 static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
   Error **errp)
 {
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index 9dd977349ab..ad0ad61177d 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "s390x-internal.h"
+#include "hw/boards.h"
 #include "sysemu/hw_accel.h"
 #include "sysemu/runstate.h"
 #include "exec/address-spaces.h"
@@ -435,6 +436,22 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t 
param,
 return SIGP_CC_STATUS_STORED;
 }
 
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
+{
+static MachineState *ms;
+
+if (!ms) {
+ms = MACHINE(qdev_get_machine());
+g_assert(ms->possible_cpus);
+}
+
+/* CPU address corresponds to the core_id and the index */
+if (cpu_addr >= ms->possible_cpus->len) {
+return NULL;
+}
+return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
+}
+
 int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
 {
 uint64_t *status_reg = >regs[r1];
-- 
2.45.0




[PULL 25/27] kconfig: express dependency of individual boards on libfdt

2024-05-12 Thread Paolo Bonzini
Now that boards are enabled by default and the "CONFIG_FOO=y"
entries are gone from configs/devices/, there cannot be any more
a conflicts between the default contents of configs/devices/
and a failed "depends on" clause.

With this change, each individual board or target can express
whether it needs FDT.  It can then include the common code in the
build via "select DEVICE_TREE", which will also as tell meson to link
with libfdt.

This allows building non-microvm x86 emulators without having
libfdt available.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 Kconfig.host  |  1 -
 hw/arm/Kconfig|  5 +
 hw/i386/Kconfig   |  3 ++-
 hw/loongarch/Kconfig  |  3 ++-
 hw/mips/Kconfig   |  3 ++-
 hw/openrisc/Kconfig   |  2 ++
 hw/ppc/Kconfig| 15 ---
 hw/riscv/Kconfig  |  4 
 hw/rx/Kconfig |  3 ++-
 hw/xtensa/Kconfig |  1 +
 target/arm/Kconfig|  2 ++
 target/microblaze/Kconfig |  1 +
 target/openrisc/Kconfig   |  1 +
 target/riscv/Kconfig  |  2 ++
 14 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/Kconfig.host b/Kconfig.host
index a0d4a52131e..17f405004b3 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -25,7 +25,6 @@ config TPM
 
 config FDT
 bool
-select DEVICE_TREE
 
 config VHOST_USER
 bool
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 98c264ed219..8b97683a45e 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -15,6 +15,7 @@ config ARM_VIRT
 select ACPI
 select ARM_SMMUV3
 select GPIO_KEY
+select DEVICE_TREE
 select FW_CFG_DMA
 select PCI_EXPRESS
 select PCI_EXPRESS_GENERIC_BRIDGE
@@ -265,6 +266,7 @@ config SBSA_REF
 default y
 depends on TCG && AARCH64
 imply PCI_DEVICES
+select DEVICE_TREE
 select AHCI
 select ARM_SMMUV3
 select GPIO_KEY
@@ -347,6 +349,7 @@ config VEXPRESS
 bool
 default y
 depends on TCG && ARM
+select DEVICE_TREE
 select A9MPCORE
 select A15MPCORE
 select ARM_MPTIMER
@@ -492,6 +495,7 @@ config XLNX_ZYNQMP_ARM
 select CPU_CLUSTER
 select DDC
 select DPCD
+select DEVICE_TREE
 select SDHCI
 select SSI
 select SSI_M25P80
@@ -509,6 +513,7 @@ config XLNX_VERSAL
 depends on TCG && AARCH64
 select ARM_GIC
 select CPU_CLUSTER
+select DEVICE_TREE
 select PL011
 select CADENCE
 select VIRTIO_MMIO
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index 40b1e445808..f4a33b6c082 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -115,7 +115,8 @@ config Q35
 config MICROVM
 bool
 default y
-depends on I386
+depends on I386 && FDT
+select DEVICE_TREE
 select SERIAL_ISA # for serial_hds_isa_init()
 select ISA_BUS
 select APIC
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index ad77502445a..90a0dba9d59 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -1,7 +1,8 @@
 config LOONGARCH_VIRT
 bool
 default y
-depends on LOONGARCH64
+depends on LOONGARCH64 && FDT
+select DEVICE_TREE
 select PCI
 select PCI_EXPRESS_GENERIC_BRIDGE
 imply VIRTIO_VGA
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 9bccb363eb9..a7f26edebe8 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -80,9 +80,10 @@ config MIPS_CPS
 config MIPS_BOSTON
 bool
 default y
-depends on MIPS64 && !TARGET_BIG_ENDIAN
+depends on MIPS64 && !TARGET_BIG_ENDIAN && FDT
 imply PCI_DEVICES
 imply TEST_DEVICES
+select DEVICE_TREE
 select FITLOADER
 select MIPS_CPS
 select PCI_EXPRESS_XILINX
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 9c9015e0a5d..76b953c62c2 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -2,6 +2,7 @@ config OR1K_SIM
 bool
 default y
 depends on OPENRISC
+select DEVICE_TREE
 select SERIAL
 select OPENCORES_ETH
 select OMPIC
@@ -14,6 +15,7 @@ config OR1K_VIRT
 imply PCI_DEVICES
 imply VIRTIO_VGA
 imply TEST_DEVICES
+select DEVICE_TREE
 select PCI
 select PCI_EXPRESS_GENERIC_BRIDGE
 select GOLDFISH_RTC
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index 78f83e78ce5..347212f4dba 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -1,7 +1,7 @@
 config PSERIES
 bool
 default y
-depends on PPC64
+depends on PPC64 && FDT
 imply USB_OHCI_PCI
 imply PCI_DEVICES
 imply TEST_DEVICES
@@ -26,7 +26,7 @@ config SPAPR_RNG
 config POWERNV
 bool
 default y
-depends on PPC64
+depends on PPC64 && FDT
 imply PCI_DEVICES
 imply TEST_DEVICES
 select ISA_IPMI_BT
@@ -52,7 +52,7 @@ config PPC405
 config PPC440
 bool
 default y
-depends on PPC
+depends on PPC && FDT
 imply PCI_DEVICES
 imply TEST_DEVICES
 imply E1000_PCI
@@ -71,7 +71,7

[PULL 18/27] hw/i386: split x86.c in multiple parts

2024-05-12 Thread Paolo Bonzini
Keep the basic X86MachineState definition in x86.c.  Move out functions that
are only needed by other files: x86-common.c for the pc and microvm machines,
x86-cpu.c for those used by accelerator code.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Zhao Liu 
Message-ID: <20240509170044.190795-11-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 include/hw/i386/x86.h |6 +-
 hw/i386/x86-common.c  | 1007 +++
 hw/i386/x86-cpu.c |   97 
 hw/i386/x86.c | 1052 +
 hw/i386/meson.build   |4 +-
 5 files changed, 1113 insertions(+), 1053 deletions(-)
 create mode 100644 hw/i386/x86-common.c
 create mode 100644 hw/i386/x86-cpu.c

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index c2062db13f5..b006f16b8d3 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -21,6 +21,7 @@
 #include "exec/memory.h"
 
 #include "hw/boards.h"
+#include "hw/i386/topology.h"
 #include "hw/intc/ioapic.h"
 #include "hw/isa/isa.h"
 #include "qom/object.h"
@@ -109,12 +110,11 @@ struct X86MachineState {
 #define TYPE_X86_MACHINE   MACHINE_TYPE_NAME("x86")
 OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE)
 
-uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
+void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
+uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
 unsigned int cpu_index);
 
-void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
 void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
-CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
 void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
 void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
   DeviceState *dev, Error **errp);
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
new file mode 100644
index 000..67b03c913a5
--- /dev/null
+++ b/hw/i386/x86-common.c
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2019, 2024 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/cutils.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+#include "qapi/error.h"
+#include "sysemu/numa.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/xen.h"
+#include "trace.h"
+
+#include "hw/i386/x86.h"
+#include "target/i386/cpu.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "target/i386/sev.h"
+
+#include "hw/acpi/cpu_hotplug.h"
+#include "hw/irq.h"
+#include "hw/loader.h"
+#include "multiboot.h"
+#include "elf.h"
+#include "standard-headers/asm-x86/bootparam.h"
+#include CONFIG_DEVICES
+#include "kvm/kvm_i386.h"
+
+#ifdef CONFIG_XEN_EMU
+#include "hw/xen/xen.h"
+#include "hw/i386/kvm/xen_evtchn.h"
+#endif
+
+/* Physical Address of PVH entry point read from kernel ELF NOTE */
+static size_t pvh_start_addr;
+
+static void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
+{
+Object *cpu = object_new(MACHINE(x86ms)->cpu_type);
+
+if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) {
+goto out;
+}
+qdev_realize(DEVICE(cpu), NULL, errp);
+
+out:
+object_unref(cpu);
+}
+
+void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
+{
+int i;
+const CPUArchIdList *possible_cpus;
+MachineState *ms = MACHINE(x86ms);
+MachineClass *mc = MACHINE_GET_CLASS(x86ms);
+
+x86_cpu_set_default_version(default

[PULL 23/27] meson: move libfdt together with other dependencies

2024-05-12 Thread Paolo Bonzini
Move the libfdt detection code together with other dependencies instead
of keeping it with subprojects.  This has the disadvantage of performing
the detection even if no target requires libfdt; but it has the advantage
that Kconfig will be able to observe the availability of the library.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 meson.build | 79 ++---
 1 file changed, 38 insertions(+), 41 deletions(-)

diff --git a/meson.build b/meson.build
index ab1f44b25c2..dd4a28f8f8f 100644
--- a/meson.build
+++ b/meson.build
@@ -1858,6 +1858,34 @@ if numa.found() and not cc.links('''
   endif
 endif
 
+fdt = not_found
+fdt_opt = get_option('fdt')
+if fdt_opt == 'enabled' and get_option('wrap_mode') == 'nodownload'
+  fdt_opt = 'system'
+endif
+if fdt_opt in ['enabled', 'system'] or (fdt_opt == 'auto' and have_system)
+  fdt = cc.find_library('fdt', required: fdt_opt == 'system')
+  if fdt.found() and cc.links('''
+ #include 
+ #include 
+ int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
+   dependencies: fdt)
+fdt_opt = 'system'
+  elif fdt_opt != 'system'
+fdt_opt = get_option('wrap_mode') == 'nodownload' ? 'disabled' : 'internal'
+fdt = not_found
+  else
+error('system libfdt is too old (1.5.1 or newer required)')
+  endif
+endif
+if fdt_opt == 'internal'
+  assert(not fdt.found())
+  libfdt_proj = subproject('dtc', required: true,
+   default_options: ['tools=false',  'yaml=disabled',
+ 'python=disabled', 
'default_library=static'])
+  fdt = libfdt_proj.get_variable('libfdt_dep')
+endif
+
 rdma = not_found
 if not get_option('rdma').auto() or have_system
   libumad = cc.find_library('ibumad', required: get_option('rdma'))
@@ -2199,6 +2227,7 @@ config_host_data.set('CONFIG_BSD', host_os 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', host_os == 'darwin')
+config_host_data.set('CONFIG_FDT', fdt.found())
 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
@@ -3024,14 +3053,16 @@ foreach target : target_dirs
 error('No accelerator available for target @0@'.format(target))
   endif
 
-  actual_target_dirs += target
   config_target += keyval.load('configs/targets' / target + '.mak')
   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
 
-  if 'TARGET_NEED_FDT' in config_target
+  if 'TARGET_NEED_FDT' in config_target and not fdt.found()
 fdt_required += target
+continue
   endif
 
+  actual_target_dirs += target
+
   # Add default keys
   if 'TARGET_BASE_ARCH' not in config_target
 config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
@@ -3119,6 +3150,10 @@ genh += custom_target('config-poison.h',
   command: [find_program('scripts/make-config-poison.sh'),
 target_configs_h])
 
+if fdt_required.length() > 0
+  error('fdt disabled but required by targets ' + ', '.join(fdt_required))
+endif
+
 ###
 # Subprojects #
 ###
@@ -3129,44 +3164,6 @@ if have_system and vfio_user_server_allowed
   libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
 endif
 
-fdt = not_found
-fdt_opt = get_option('fdt')
-if fdt_required.length() > 0 or fdt_opt == 'enabled'
-  if fdt_opt == 'disabled'
-error('fdt disabled but required by targets ' + ', '.join(fdt_required))
-  endif
-
-  if fdt_opt in ['enabled', 'auto', 'system']
-if get_option('wrap_mode') == 'nodownload'
-  fdt_opt = 'system'
-endif
-fdt = cc.find_library('fdt', required: fdt_opt == 'system')
-if fdt.found() and cc.links('''
-   #include 
-   #include 
-   int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
- dependencies: fdt)
-  fdt_opt = 'system'
-elif fdt_opt == 'system'
-   error('system libfdt requested, but it is too old (1.5.1 or newer 
required)')
-else
-  fdt_opt = 'internal'
-  fdt = not_found
-endif
-  endif
-  if not fdt.found()
-assert(fdt_opt == 'internal')
-libfdt_proj = subproject('dtc', required: true,
- default_options: ['tools=false',  'yaml=disabled',
-   'python=disabled', 
'default_library=static'])
-fdt = libfdt_proj.get_variable('libfdt_dep')
-  endif
-else
-  fdt_opt = 'disabled'
-endif
-
-config_host_data.set('CONFIG_FDT', fdt.found())
-
 vhost_user = not_found
 if host_os == 'linux' and have_vhost_user
   libvhost_user = subproject('libvhost-user')
@@ -4417,7 +4414,7 @@ summary_info += {'Linux AIO support': libaio}
 summary_info += {'Linux io_uring support': linux_io_uring}
 summary_info += {'ATTR

[PULL 07/27] configure: quote -D options that are passed through to meson

2024-05-12 Thread Paolo Bonzini
Ensure that they go through unmodified, instead of removing one layer
of quoting.

-D is a pretty specialized option and most options that can have spaces
do not need it (for example, c_args is covered by --extra-cflags).
Therefore it's unlikely that this causes actual trouble.  However,
a somewhat realistic failure case would be with -Dpkg_config_path
and a pkg-config directory that contains spaces.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Thomas Huth 
Signed-off-by: Paolo Bonzini 
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 1dca3d94c04..330664786dc 100755
--- a/configure
+++ b/configure
@@ -762,7 +762,7 @@ for opt do
   --*) meson_option_parse "$opt" "$optarg"
   ;;
   # Pass through -D options to meson
-  -D*) meson_options="$meson_options $opt"
+  -D*) meson_option_add "$opt"
   ;;
   esac
 done
-- 
2.45.0




[PULL 14/27] xen: initialize legacy backends from xen_bus_init()

2024-05-12 Thread Paolo Bonzini
Prepare for moving the calls to xen_be_register() under the
control of xen_bus_init(), using the normal xen_backend_init()
method that is used by the "modern" backends.

This requires the xenstore global variable to be initialized,
which is done by xen_be_init().  To ensure that everything is
ready at the time the xen_backend_init() functions are called,
remove the xen_be_init() function from all the boards and
place it directly in xen_bus_init().

Signed-off-by: Paolo Bonzini 
Reviewed-by: Philippe Mathieu-Daudé 
Message-ID: <20240509170044.190795-7-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 hw/i386/pc.c  | 1 -
 hw/xen/xen-bus.c  | 4 
 hw/xen/xen-hvm-common.c   | 2 --
 hw/xenpv/xen_machine_pv.c | 5 +
 4 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 505ea750f4d..19f21953b4a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1250,7 +1250,6 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 pci_create_simple(pcms->pcibus, -1, "xen-platform");
 }
 xen_bus_init();
-xen_be_init();
 }
 #endif
 
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index fb82cc33e48..95b207ac8b4 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -13,6 +13,7 @@
 #include "hw/sysbus.h"
 #include "hw/xen/xen.h"
 #include "hw/xen/xen-backend.h"
+#include "hw/xen/xen-legacy-backend.h" /* xen_be_init() */
 #include "hw/xen/xen-bus.h"
 #include "hw/xen/xen-bus-helper.h"
 #include "monitor/monitor.h"
@@ -329,6 +330,9 @@ static void xen_bus_realize(BusState *bus, Error **errp)
 goto fail;
 }
 
+/* Initialize legacy backend core & drivers */
+xen_be_init();
+
 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
   "domid", NULL, "%u", ) == 1) {
 xenbus->backend_id = domid;
diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index 1627da73982..2d1b0321214 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -872,8 +872,6 @@ void xen_register_ioreq(XenIOState *state, unsigned int 
max_cpus,
 
 xen_bus_init();
 
-xen_be_init();
-
 return;
 
 err:
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 1130d1a1479..b500ce09891 100644
--- a/hw/xenpv/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c
@@ -34,8 +34,7 @@ static void xen_init_pv(MachineState *machine)
 {
 setup_xen_backend_ops();
 
-/* Initialize backend core & drivers */
-xen_be_init();
+xen_bus_init();
 
 switch (xen_mode) {
 case XEN_ATTACH:
@@ -60,8 +59,6 @@ static void xen_init_pv(MachineState *machine)
 vga_interface_created = true;
 }
 
-xen_bus_init();
-
 /* config cleanup hook */
 atexit(xen_config_cleanup);
 }
-- 
2.45.0




[PULL 17/27] i386: pc: remove unnecessary MachineClass overrides

2024-05-12 Thread Paolo Bonzini
There is no need to override these fields of MachineClass because they are
already set to the right value in the superclass.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Zhao Liu 
Message-ID: <20240509170044.190795-10-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 include/hw/i386/x86.h | 4 
 hw/i386/pc.c  | 3 ---
 hw/i386/x86.c | 6 +++---
 3 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index d7b7d3f3ce0..c2062db13f5 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -114,10 +114,6 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
 
 void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
 void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
-CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
- unsigned cpu_index);
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx);
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);
 CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
 void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
 void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 19f21953b4a..bfb46e9b548 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1826,9 +1826,6 @@ static void pc_machine_class_init(ObjectClass *oc, void 
*data)
 assert(!mc->get_hotplug_handler);
 mc->get_hotplug_handler = pc_get_hotplug_handler;
 mc->hotplug_allowed = pc_hotplug_allowed;
-mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
-mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
-mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
 mc->auto_enable_numa_with_memhp = true;
 mc->auto_enable_numa_with_memdev = true;
 mc->has_hotpluggable_cpus = true;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index c61f4ebfa6a..fcef652c1e3 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -443,7 +443,7 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
 numa_cpu_pre_plug(cpu_slot, dev, errp);
 }
 
-CpuInstanceProperties
+static CpuInstanceProperties
 x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
 {
 MachineClass *mc = MACHINE_GET_CLASS(ms);
@@ -453,7 +453,7 @@ x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
 return possible_cpus->cpus[cpu_index].props;
 }
 
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
+static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
 {
X86CPUTopoIDs topo_ids;
X86MachineState *x86ms = X86_MACHINE(ms);
@@ -467,7 +467,7 @@ int64_t x86_get_default_cpu_node_id(const MachineState *ms, 
int idx)
return topo_ids.pkg_id % ms->numa_state->num_nodes;
 }
 
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
+static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
 {
 X86MachineState *x86ms = X86_MACHINE(ms);
 unsigned int max_cpus = ms->smp.max_cpus;
-- 
2.45.0




[PULL 11/27] s390: move css_migration_enabled from machine to css.c

2024-05-12 Thread Paolo Bonzini
The CSS subsystem uses global variables, just face the truth and use
a variable also for whether the CSS vmstate is in use; remove the
indirection of fetching it from the machine type, which makes the
TCG code depend unnecessarily on the virtio-ccw machine.

Signed-off-by: Paolo Bonzini 
Message-ID: <20240509170044.190795-4-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 include/hw/s390x/css.h |  6 ++
 include/hw/s390x/s390-virtio-ccw.h |  7 ---
 hw/s390x/css.c | 10 +++---
 hw/s390x/s390-virtio-ccw.c | 15 +++
 4 files changed, 16 insertions(+), 22 deletions(-)

diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index ba72ee3dd20..8289e458370 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -333,4 +333,10 @@ static inline int ccw_dstream_read_buf(CcwDataStream *cds, 
void *buff, int len)
 #define ccw_dstream_read(cds, v) ccw_dstream_read_buf((cds), &(v), sizeof(v))
 #define ccw_dstream_write(cds, v) ccw_dstream_write_buf((cds), &(v), sizeof(v))
 
+/**
+ * true if (vmstate based) migration of the channel subsystem
+ * is enabled, false if it is disabled.
+ */
+extern bool css_migration_enabled;
+
 #endif
diff --git a/include/hw/s390x/s390-virtio-ccw.h 
b/include/hw/s390x/s390-virtio-ccw.h
index 7605d06bff1..996864a34e2 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -46,7 +46,6 @@ struct S390CcwMachineClass {
 /*< public >*/
 bool ri_allowed;
 bool cpu_model_allowed;
-bool css_migration_enabled;
 bool hpage_1m_allowed;
 int max_threads;
 };
@@ -58,10 +57,4 @@ bool cpu_model_allowed(void);
 /* 1M huge page mappings allowed by the machine */
 bool hpage_1m_allowed(void);
 
-/**
- * Returns true if (vmstate based) migration of the channel subsystem
- * is enabled, false if it is disabled.
- */
-bool css_migration_enabled(void);
-
 #endif
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 295530963a6..b2d5327dbf4 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -23,6 +23,8 @@
 #include "hw/s390x/s390-virtio-ccw.h"
 #include "hw/s390x/s390-ccw.h"
 
+bool css_migration_enabled = true;
+
 typedef struct CrwContainer {
 CRW crw;
 QTAILQ_ENTRY(CrwContainer) sibling;
@@ -180,7 +182,7 @@ static const VMStateDescription vmstate_orb = {
 
 static bool vmstate_schdev_orb_needed(void *opaque)
 {
-return css_migration_enabled();
+return css_migration_enabled;
 }
 
 static const VMStateDescription vmstate_schdev_orb = {
@@ -388,7 +390,7 @@ static int subch_dev_post_load(void *opaque, int version_id)
 css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
 }
 
-if (css_migration_enabled()) {
+if (css_migration_enabled) {
 /* No compat voodoo to do ;) */
 return 0;
 }
@@ -412,7 +414,9 @@ static int subch_dev_post_load(void *opaque, int version_id)
 
 void css_register_vmstate(void)
 {
-vmstate_register(NULL, 0, _css, _subsys);
+if (css_migration_enabled) {
+vmstate_register(NULL, 0, _css, _subsys);
+}
 }
 
 IndAddr *get_indicator(hwaddr ind_addr, int len)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 756b4f40aed..3d0bc3e7f2e 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -283,11 +283,9 @@ static void ccw_init(MachineState *machine)
 s390_enable_css_support(s390_cpu_addr2state(0));
 
 ret = css_create_css_image(VIRTUAL_CSSID, true);
-
 assert(ret == 0);
-if (css_migration_enabled()) {
-css_register_vmstate();
-}
+
+css_register_vmstate();
 
 /* Create VirtIO network adapters */
 s390_create_virtio_net(BUS(css_bus), mc->default_nic);
@@ -749,7 +747,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void 
*data)
 
 s390mc->ri_allowed = true;
 s390mc->cpu_model_allowed = true;
-s390mc->css_migration_enabled = true;
 s390mc->hpage_1m_allowed = true;
 s390mc->max_threads = 1;
 mc->init = ccw_init;
@@ -819,11 +816,6 @@ static const TypeInfo ccw_machine_info = {
 },
 };
 
-bool css_migration_enabled(void)
-{
-return get_machine_class()->css_migration_enabled;
-}
-
 #define DEFINE_CCW_MACHINE(suffix, verstr, latest)\
 static void ccw_machine_##suffix##_class_init(ObjectClass *oc,\
   void *data) \
@@ -1179,7 +1171,6 @@ static void ccw_machine_2_9_instance_options(MachineState 
*machine)
 
 static void ccw_machine_2_9_class_options(MachineClass *mc)
 {
-S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
 static GlobalProperty compat[] = {
 { TYPE_S390_STATTRIB, "migration-enabled", "off", },
 { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
@@ -1188,7 +1179,7 @@ static void ccw_machine_

[PULL 13/27] tests/qtest: s390x: fix operation in a build without any boards or devices

2024-05-12 Thread Paolo Bonzini
Do the bare minimum to ensure that at least a vanilla
--without-default-devices build works for all targets except i386,
x86_64 and ppc64.  In particular this fixes s390x-softmmu; i386 and
x86_64 have about a dozen failing tests that do not pass -M and therefore
require a default machine type; ppc64 has the same issue, though only
with numa-test.

If we can for now ignore the cases where boards and devices are picked
by hand, drive_del-test however can be fixed easily; almost all tests
check for the virtio-blk or virtio-scsi device that they use, and are
already skipped.  Only one didn't get the memo; plus another one does
not need a machine at all and can be run with -M none.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Thomas Huth 
Message-ID: <20240509170044.190795-6-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 tests/qtest/drive_del-test.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/drive_del-test.c b/tests/qtest/drive_del-test.c
index 8a6f3ac963d..7b67a4bbee4 100644
--- a/tests/qtest/drive_del-test.c
+++ b/tests/qtest/drive_del-test.c
@@ -173,7 +173,7 @@ static void test_drive_without_dev(void)
 QTestState *qts;
 
 /* Start with an empty drive */
-qts = qtest_init("-drive if=none,id=drive0");
+qts = qtest_init("-drive if=none,id=drive0 -M none");
 
 /* Delete the drive */
 drive_del(qts);
@@ -192,6 +192,11 @@ static void test_after_failed_device_add(void)
 QDict *response;
 QTestState *qts;
 
+if (!has_device_builtin("virtio-blk")) {
+g_test_skip("Device virtio-blk is not available");
+return;
+}
+
 snprintf(driver, sizeof(driver), "virtio-blk-%s",
  qvirtio_get_dev_type());
 
-- 
2.45.0




[PULL 19/27] hw/i386: move rtc-reset-reinjection command out of hw/rtc

2024-05-12 Thread Paolo Bonzini
The rtc-reset-reinjection QMP command is specific to x86, other boards do not
have the ACK tracking functionality that is needed for RTC interrupt
reinjection.  Therefore the QMP command is only included in x86, but
qmp_rtc_reset_reinjection() is implemented by hw/rtc/mc146818rtc.c
and requires tracking of all created RTC devices.  Move the implementation
to hw/i386, so that 1) it is available even if no RTC device exist
2) the only RTC that exists is easily found in x86ms->rtc.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Zhao Liu 
Message-ID: <20240509170044.190795-12-pbonz...@redhat.com>
Signed-off-by: Paolo Bonzini 
---
 include/hw/rtc/mc146818rtc.h |  2 +-
 hw/i386/monitor.c| 46 
 hw/rtc/mc146818rtc.c | 12 ++
 hw/i386/meson.build  |  1 +
 4 files changed, 50 insertions(+), 11 deletions(-)
 create mode 100644 hw/i386/monitor.c

diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 97cec0b3e84..64893be1515 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -55,6 +55,6 @@ MC146818RtcState *mc146818_rtc_init(ISABus *bus, int 
base_year,
 qemu_irq intercept_irq);
 void mc146818rtc_set_cmos_data(MC146818RtcState *s, int addr, int val);
 int mc146818rtc_get_cmos_data(MC146818RtcState *s, int addr);
-void qmp_rtc_reset_reinjection(Error **errp);
+void rtc_reset_reinjection(MC146818RtcState *rtc);
 
 #endif /* HW_RTC_MC146818RTC_H */
diff --git a/hw/i386/monitor.c b/hw/i386/monitor.c
new file mode 100644
index 000..1ebd3564bf2
--- /dev/null
+++ b/hw/i386/monitor.c
@@ -0,0 +1,46 @@
+/*
+ * QEMU monitor
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "hw/i386/x86.h"
+#include "hw/rtc/mc146818rtc.h"
+
+#include CONFIG_DEVICES
+
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+X86MachineState *x86ms = X86_MACHINE(qdev_get_machine());
+
+#ifdef CONFIG_MC146818RTC
+if (x86ms->rtc) {
+rtc_reset_reinjection(MC146818_RTC(x86ms->rtc));
+}
+#else
+assert(!x86ms->rtc);
+#endif
+}
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index 3379f92748b..8ccee9a385d 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -104,16 +104,9 @@ static void rtc_coalesced_timer_update(MC146818RtcState *s)
 }
 }
 
-static QLIST_HEAD(, MC146818RtcState) rtc_devices =
-QLIST_HEAD_INITIALIZER(rtc_devices);
-
-void qmp_rtc_reset_reinjection(Error **errp)
+void rtc_reset_reinjection(MC146818RtcState *rtc)
 {
-MC146818RtcState *s;
-
-QLIST_FOREACH(s, _devices, link) {
-s->irq_coalesced = 0;
-}
+rtc->irq_coalesced = 0;
 }
 
 static bool rtc_policy_slew_deliver_irq(MC146818RtcState *s)
@@ -941,7 +934,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
 object_property_add_tm(OBJECT(s), "date", rtc_get_date);
 
 qdev_init_gpio_out(dev, >irq, 1);
-QLIST_INSERT_HEAD(_devices, s, link);
 }
 
 MC146818RtcState *mc146818_rtc_init(ISABus *bus, int base_year,
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 3437da0aad1..03aad10df7a 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -2,6 +2,7 @@ i386_ss = ss.source_set()
 i386_ss.add(files(
   'fw_cfg.c',
   'e820_memory_layout.c',
+  'monitor.c',
   'multiboot.c',
   'x86.c',
   'x86-cpu.c',
-- 
2.45.0




[PULL 04/27] target/i386: move prefetch and multi-byte UD/NOP to new decoder

2024-05-12 Thread Paolo Bonzini
These are trivial to add, and moving them to the new decoder fixes some
corner cases: raising #UD instead of an instruction fetch page fault for
the undefined opcodes, and incorrectly rejecting 0F 18 prefetches with
register operands (which are treated as reserved NOPs).

Reviewed-by: Richard Henderson 
Reviewed-by: Zhao Liu 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |  1 +
 target/i386/tcg/translate.c  | 30 --
 target/i386/tcg/decode-new.c.inc | 24 +---
 target/i386/tcg/emit.c.inc   |  5 +
 4 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 2ea06b44787..51ef0e621b9 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -50,6 +50,7 @@ typedef enum X86OpType {
 X86_TYPE_EM, /* modrm byte selects an ALU memory operand */
 X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
 X86_TYPE_I_unsigned, /* Immediate, zero-extended */
+X86_TYPE_nop, /* modrm operand decoded but not loaded into s->T{0,1} */
 X86_TYPE_2op, /* 2-operand RMW instruction */
 X86_TYPE_LoBits, /* encoded in bits 0-2 of the operand + REX.B */
 X86_TYPE_0, /* Hard-coded GPRs (RAX..RDI) */
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3da4fdf64cc..de87775016b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4019,25 +4019,6 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 set_cc_op(s, CC_OP_EFLAGS);
 }
 break;
-case 0x118:
-modrm = x86_ldub_code(env, s);
-mod = (modrm >> 6) & 3;
-op = (modrm >> 3) & 7;
-switch(op) {
-case 0: /* prefetchnta */
-case 1: /* prefetchnt0 */
-case 2: /* prefetchnt0 */
-case 3: /* prefetchnt0 */
-if (mod == 3)
-goto illegal_op;
-gen_nop_modrm(env, s, modrm);
-/* nothing more to do */
-break;
-default: /* nop (multi byte) */
-gen_nop_modrm(env, s, modrm);
-break;
-}
-break;
 case 0x11a:
 modrm = x86_ldub_code(env, s);
 if (s->flags & HF_MPX_EN_MASK) {
@@ -4229,10 +4210,6 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 }
 gen_nop_modrm(env, s, modrm);
 break;
-case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
-modrm = x86_ldub_code(env, s);
-gen_nop_modrm(env, s, modrm);
-break;
 
 case 0x120: /* mov reg, crN */
 case 0x122: /* mov crN, reg */
@@ -4506,13 +4483,6 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 }
 break;
 
-case 0x10d: /* 3DNow! prefetch(w) */
-modrm = x86_ldub_code(env, s);
-mod = (modrm >> 6) & 3;
-if (mod == 3)
-goto illegal_op;
-gen_nop_modrm(env, s, modrm);
-break;
 case 0x1aa: /* rsm */
 gen_svm_check_intercept(s, SVM_EXIT_RSM);
 if (!(s->flags & HF_SMM_MASK))
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 0e1811399f8..141ab2bc560 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -55,6 +55,10 @@
  * mask could be applied (and the original sign-extended value would be
  * optimized away by TCG) in the emitter function.
  *
+ * Finally, a "nop" operand type is used for multi-byte NOPs.  It accepts
+ * any value of mod including 11b (unlike M) but it does not try to
+ * interpret the operand (like M).
+ *
  * Vector operands
  * ---
  *
@@ -1056,6 +1060,16 @@ static const X86OpEntry opcodes_0F[256] = {
 [0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
 [0xa1] = X86_OP_ENTRYw(POP, FS, w),
 
+[0x0b] = X86_OP_ENTRY0(UD),   /* UD2 */
+[0x0d] = X86_OP_ENTRY1(NOP,  M,v),/* 3DNow! prefetch */
+
+[0x18] = X86_OP_ENTRY1(NOP,  nop,v),  /* prefetch/reserved NOP */
+[0x19] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1c] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1d] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1e] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1f] = X86_OP_ENTRY1(NOP,  nop,v),  /* NOP/reserved NOP */
+
 [0x28] = X86_OP_ENTRY3(MOVDQ,  V,x,  None,None, W,x, vex1 p_00_66), /* 
MOVAPS */
 [0x29] = X86_OP_ENTRY3(MOVDQ,  W,x,  None,None, V,x, vex1 p_00_66), /* 
MOVAPS */
 [0x2A] = X86_OP_GROUP0(0F2A),
@@ -1135,6 +1149,8 @@ static const X86OpEntry opcodes_0F[256] = {
 [0xb6] = X86_OP_ENTRY3(MOV,G,v, E,b, None, None, zextT0), /* MOVZX */
 [0xb7] = X86_OP_ENTRY3(MOV,G,v, E,w, None, None, zextT0), /* MOVZX */
 
+/* decoded as modrm, which is visible as a difference between page fault 
and #UD */
+[0xb9] = X8

Re: [PATCH 03/13] s390: move css_migration_enabled from machine to css.c

2024-05-10 Thread Paolo Bonzini
On Fri, May 10, 2024 at 7:38 AM Thomas Huth  wrote:
> I think this is wrong: By adding this to ccw_machine_2_9_class_options the
> variable now always gets set to false, even for newer machines, since the
> *class_options functions are part of the "class_init" which is always
done.
> You have to add it to ccw_machine_2_9_instance_options() instead to make
it
> work as expected.

Indeed, this has to be squashed in:

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index aa90703d518..b7ddd36b8ba 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -1159,6 +1159,7 @@ static void
ccw_machine_2_9_instance_options(MachineState *machine)
 s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI);
 s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION);
 s390_cpudef_featoff_greater(12, 1,
S390_FEAT_ADAPTER_EVENT_NOTIFICATION);
+css_migration_enabled = false;
 }

 static void ccw_machine_2_9_class_options(MachineClass *mc)
@@ -1171,7 +1172,6 @@ static void
ccw_machine_2_9_class_options(MachineClass *mc)
 ccw_machine_2_10_class_options(mc);
 compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
 compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
-css_migration_enabled = false;
 }
 DEFINE_CCW_MACHINE(2_9, "2.9", false);


[PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices

2024-05-09 Thread Paolo Bonzini
ARM/aarch64 are easy to fix because they already have to pass a machine
type by hand.  Just guard the tests with a check that the machine actually
exists.

Signed-off-by: Paolo Bonzini 
---
 tests/qtest/arm-cpu-features.c | 4 
 tests/qtest/migration-test.c   | 6 ++
 tests/qtest/numa-test.c| 4 
 3 files changed, 14 insertions(+)

diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index 9d6e6190d55..966c65d5c3e 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -632,6 +632,10 @@ int main(int argc, char **argv)
 {
 g_test_init(, , NULL);
 
+if (!qtest_has_machine("virt")) {
+goto out;
+}
+
 if (qtest_has_accel("tcg")) {
 qtest_add_data_func("/arm/query-cpu-model-expansion",
 NULL, test_query_cpu_model_expansion);
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 5d6d8cd6343..31045b69fa7 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -813,6 +813,12 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 kvm_opts = ",dirty-ring-size=4096";
 }
 
+if (!qtest_has_machine(machine_alias)) {
+g_autofree char *msg = g_strdup_printf("machine %s not supported", 
machine_alias);
+g_test_skip(msg);
+return -1;
+}
+
 machine = resolve_machine_version(machine_alias, QEMU_ENV_SRC,
   QEMU_ENV_DST);
 
diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
index 4f4404a4b14..7aa262dbb99 100644
--- a/tests/qtest/numa-test.c
+++ b/tests/qtest/numa-test.c
@@ -558,6 +558,9 @@ int main(int argc, char **argv)
 }
 
 if (g_str_equal(arch, "aarch64")) {
+if (!qtest_has_machine("virt")) {
+goto out;
+}
 g_string_append(args, " -machine virt");
 }
 
@@ -590,5 +593,6 @@ int main(int argc, char **argv)
 aarch64_numa_cpu);
 }
 
+out:
 return g_test_run();
 }
-- 
2.45.0




[PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c

2024-05-09 Thread Paolo Bonzini
This function has no dependency on the virtio-ccw machine type, though it
assumes that the CPU address corresponds to the core_id and the index.

If there is any need of something different or more fancy (unlikely)
S390 can include a MachineClass subclass and implement it there.  For
now, move it to sigp.c for simplicity.

Signed-off-by: Paolo Bonzini 
---
 hw/s390x/s390-virtio-ccw.c | 16 
 target/s390x/sigp.c| 17 +
 2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4dcc2138200..feabc173eb3 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -50,22 +50,6 @@
 
 static Error *pv_mig_blocker;
 
-S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
-{
-static MachineState *ms;
-
-if (!ms) {
-ms = MACHINE(qdev_get_machine());
-g_assert(ms->possible_cpus);
-}
-
-/* CPU address corresponds to the core_id and the index */
-if (cpu_addr >= ms->possible_cpus->len) {
-return NULL;
-}
-return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
-}
-
 static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
   Error **errp)
 {
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index 9dd977349ab..ad0ad61177d 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "s390x-internal.h"
+#include "hw/boards.h"
 #include "sysemu/hw_accel.h"
 #include "sysemu/runstate.h"
 #include "exec/address-spaces.h"
@@ -435,6 +436,22 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t 
param,
 return SIGP_CC_STATUS_STORED;
 }
 
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
+{
+static MachineState *ms;
+
+if (!ms) {
+ms = MACHINE(qdev_get_machine());
+g_assert(ms->possible_cpus);
+}
+
+/* CPU address corresponds to the core_id and the index */
+if (cpu_addr >= ms->possible_cpus->len) {
+return NULL;
+}
+return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
+}
+
 int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
 {
 uint64_t *status_reg = >regs[r1];
-- 
2.45.0




[PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components

2024-05-09 Thread Paolo Bonzini
fw_cfg.c and vapic.c are currently included unconditionally but
depend on other components.  vapic.c depends on the local APIC,
while fw_cfg.c includes a piece of AML builder code that depends
on CONFIG_ACPI.

Signed-off-by: Paolo Bonzini 
---
 hw/i386/fw_cfg.c| 2 ++
 hw/i386/meson.build | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index d802d2787f0..6e0d9945d07 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -203,6 +203,7 @@ void fw_cfg_build_feature_control(MachineState *ms, 
FWCfgState *fw_cfg)
 fw_cfg_add_file(fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
 }
 
+#ifdef CONFIG_ACPI
 void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
 {
 /*
@@ -229,3 +230,4 @@ void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
 aml_append(dev, aml_name_decl("_CRS", crs));
 aml_append(scope, dev);
 }
+#endif
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index d8b70ef3e9c..d9da676038c 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -1,12 +1,12 @@
 i386_ss = ss.source_set()
 i386_ss.add(files(
   'fw_cfg.c',
-  'vapic.c',
   'e820_memory_layout.c',
   'multiboot.c',
   'x86.c',
 ))
 
+i386_ss.add(when: 'CONFIG_APIC', if_true: files('vapic.c'))
 i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
   if_false: files('x86-iommu-stub.c'))
 i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'),
-- 
2.45.0




[PATCH 12/13] i386: select correct components for no-board build

2024-05-09 Thread Paolo Bonzini
The local APIC is a part of the CPU and has callbacks that are invoked
from multiple accelerators.

The IOAPIC on the other hand is optional, but ioapic_eoi_broadcast is
used by common x86 code to implement the IOAPIC's implicit EOI mode.
Add a stub in case the IOAPIC device is not included but the APIC is.

Signed-off-by: Paolo Bonzini 
---
 hw/intc/ioapic-stub.c  | 29 +
 .gitlab-ci.d/buildtest.yml |  2 +-
 hw/intc/meson.build|  2 +-
 target/i386/Kconfig|  1 +
 4 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 hw/intc/ioapic-stub.c

diff --git a/hw/intc/ioapic-stub.c b/hw/intc/ioapic-stub.c
new file mode 100644
index 000..4dcd86248da
--- /dev/null
+++ b/hw/intc/ioapic-stub.c
@@ -0,0 +1,29 @@
+/*
+ *  ioapic.c IOAPIC emulation logic
+ *
+ *  Copyright (c) 2004-2005 Fabrice Bellard
+ *
+ *  Split the ioapic logic from apic.c
+ *  Xiantao Zhang 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/intc/ioapic.h"
+
+void ioapic_eoi_broadcast(int vector)
+{
+}
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index f8502905203..62616157206 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
 # Check our reduced build configurations
 # requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
 #   mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, x86_64
+# fails qtest without boards: i386, x86_64
 build-without-defaults:
   extends: .native_build_job_template
   needs:
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index f4b540e6a8b..0d1b7d0a432 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -20,7 +20,7 @@ system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: 
files('goldfish_pic.c'))
 system_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
 system_ss.add(when: 'CONFIG_I8259', if_true: files('i8259_common.c', 
'i8259.c'))
 system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_avic.c', 'imx_gpcv2.c'))
-system_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic_common.c'))
+system_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic_common.c'), 
if_false: files('ioapic-stub.c'))
 system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c'))
 system_ss.add(when: 'CONFIG_OPENPIC', if_true: files('openpic.c'))
 system_ss.add(when: 'CONFIG_PL190', if_true: files('pl190.c'))
diff --git a/target/i386/Kconfig b/target/i386/Kconfig
index ad9291d3b8f..6b0feef0299 100644
--- a/target/i386/Kconfig
+++ b/target/i386/Kconfig
@@ -1,5 +1,6 @@
 config I386
 bool
+select APIC
 # kvm_arch_fixup_msi_route() needs to access PCIDevice
 select PCI if KVM
 
-- 
2.45.0




[PATCH 07/13] xen: register legacy backends via xen_backend_init

2024-05-09 Thread Paolo Bonzini
It is okay to register legacy backends in the middle of xen_bus_init().
All that the registration does is record the existence of the backend
in xenstore.

This makes it possible to remove them from the build without introducing
undefined symbols in xen_be_init().  It also removes the need for the
backend_register callback, whose only purpose is to avoid registering
nonfunctional backends.

Signed-off-by: Paolo Bonzini 
---
 include/hw/xen/xen-legacy-backend.h | 14 ++
 include/hw/xen/xen_pvdev.h  |  1 -
 hw/9pfs/xen-9p-backend.c|  8 +++-
 hw/display/xenfb.c  |  8 +++-
 hw/usb/xen-usb.c| 14 --
 hw/xen/xen-legacy-backend.c | 16 
 6 files changed, 20 insertions(+), 41 deletions(-)

diff --git a/include/hw/xen/xen-legacy-backend.h 
b/include/hw/xen/xen-legacy-backend.h
index 2cca1747786..979c4ea04c5 100644
--- a/include/hw/xen/xen-legacy-backend.h
+++ b/include/hw/xen/xen-legacy-backend.h
@@ -66,18 +66,8 @@ static inline void xen_be_unmap_grant_ref(struct 
XenLegacyDevice *xendev,
 return xen_be_unmap_grant_refs(xendev, ptr, , 1);
 }
 
-/* actual backend drivers */
-extern struct XenDevOps xen_console_ops;  /* xen_console.c */
-extern struct XenDevOps xen_kbdmouse_ops; /* xen_framebuffer.c */
-extern struct XenDevOps xen_framebuffer_ops;  /* xen_framebuffer.c */
-extern struct XenDevOps xen_blkdev_ops;   /* xen_disk.c*/
-#ifdef CONFIG_VIRTFS
-extern struct XenDevOps xen_9pfs_ops;   /* xen-9p-backend.c*/
-#endif
-extern struct XenDevOps xen_netdev_ops;   /* xen_nic.c */
-#ifdef CONFIG_USB_LIBUSB
-extern struct XenDevOps xen_usb_ops;  /* xen-usb.c */
-#endif
+/* backend drivers not included in all machines */
+extern struct XenDevOps xen_framebuffer_ops;  /* xenfb.c */
 
 /* configuration (aka xenbus setup) */
 void xen_config_cleanup(void);
diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h
index ddad4b9f36a..fdf84f47af1 100644
--- a/include/hw/xen/xen_pvdev.h
+++ b/include/hw/xen/xen_pvdev.h
@@ -29,7 +29,6 @@ struct XenDevOps {
  const char *node);
 void  (*frontend_changed)(struct XenLegacyDevice *xendev,
   const char *node);
-int   (*backend_register)(void);
 };
 
 struct XenLegacyDevice {
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index 4aa9c8c736d..a3ac53f989e 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -513,7 +513,7 @@ static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
 xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
 }
 
-struct XenDevOps xen_9pfs_ops = {
+static struct XenDevOps xen_9pfs_ops = {
 .size   = sizeof(Xen9pfsDev),
 .flags  = DEVOPS_FLAG_NEED_GNTDEV,
 .alloc  = xen_9pfs_alloc,
@@ -522,3 +522,9 @@ struct XenDevOps xen_9pfs_ops = {
 .disconnect = xen_9pfs_disconnect,
 .free   = xen_9pfs_free,
 };
+
+static void xen_9pfs_register_backend(void)
+{
+xen_be_register("9pfs", _9pfs_ops);
+}
+xen_backend_init(xen_9pfs_register_backend);
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index b2130a0d700..27536bfce0c 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -972,7 +972,7 @@ static void fb_event(struct XenLegacyDevice *xendev)
 
 /*  */
 
-struct XenDevOps xen_kbdmouse_ops = {
+static struct XenDevOps xen_kbdmouse_ops = {
 .size   = sizeof(struct XenInput),
 .init   = input_init,
 .initialise = input_initialise,
@@ -995,3 +995,9 @@ static const GraphicHwOps xenfb_ops = {
 .gfx_update  = xenfb_update,
 .ui_info = xenfb_ui_info,
 };
+
+static void xen_vkbd_register_backend(void)
+{
+xen_be_register("vkbd", _kbdmouse_ops);
+}
+xen_backend_init(xen_vkbd_register_backend);
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index 09ec326aeae..416623f956a 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -1083,7 +1083,7 @@ static void usbback_event(struct XenLegacyDevice *xendev)
 qemu_bh_schedule(usbif->bh);
 }
 
-struct XenDevOps xen_usb_ops = {
+static struct XenDevOps xen_usb_ops = {
 .size= sizeof(struct usbback_info),
 .flags   = DEVOPS_FLAG_NEED_GNTDEV,
 .init= usbback_init,
@@ -1095,15 +1095,9 @@ struct XenDevOps xen_usb_ops = {
 .event   = usbback_event,
 };
 
-#else /* USBIF_SHORT_NOT_OK */
-
-static int usbback_not_supported(void)
+static void xen_usb_register_backend(void)
 {
-return -EINVAL;
+xen_be_register("qusb", _usb_ops);
 }
-
-struct XenDevOps xen_usb_ops = {
-.backend_register = usbback_not_supported,
-};
-
+xen_backend_init(xen_usb_register_backend);
 #endif
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 124dd5f3d68.

[PATCH 02/13] s390_flic: add migration-enabled property

2024-05-09 Thread Paolo Bonzini
Instead of mucking with css_migration_enabled(), add a property specific to
the FLIC device, similar to what is done for TYPE_S390_STATTRIB.

Signed-off-by: Paolo Bonzini 
---
 include/hw/s390x/s390_flic.h | 1 +
 hw/intc/s390_flic.c  | 6 +-
 hw/s390x/s390-virtio-ccw.c   | 1 +
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 3907a13d076..bcb081def58 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -47,6 +47,7 @@ struct S390FLICState {
 /* to limit AdapterRoutes.num_routes for compat */
 uint32_t adapter_routes_max_batch;
 bool ais_supported;
+bool migration_enabled;
 };
 
 
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index f4a848460b8..7f930800877 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -405,6 +405,8 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void 
*data)
 static Property s390_flic_common_properties[] = {
 DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState,
adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI),
+DEFINE_PROP_BOOL("migration-enabled", S390FLICState,
+ migration_enabled, true),
 DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -457,7 +459,9 @@ type_init(qemu_s390_flic_register_types)
 
 static bool adapter_info_so_needed(void *opaque)
 {
-return css_migration_enabled();
+S390FLICState *fs = S390_FLIC_COMMON(opaque);
+
+return fs->migration_enabled;
 }
 
 const VMStateDescription vmstate_adapter_info_so = {
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index feabc173eb3..1383e47eeb5 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -1174,6 +1174,7 @@ static void ccw_machine_2_9_class_options(MachineClass 
*mc)
 S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
 static GlobalProperty compat[] = {
 { TYPE_S390_STATTRIB, "migration-enabled", "off", },
+{ TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
 };
 
 ccw_machine_2_10_class_options(mc);
-- 
2.45.0




[PATCH 03/13] s390: move css_migration_enabled from machine to css.c

2024-05-09 Thread Paolo Bonzini
The CSS subsystem uses global variables, just face the truth and use
a variable also for whether the CSS vmstate is in use; remove the
indirection of fetching it from the machine type, which makes the
TCG code depend unnecessarily on the virtio-ccw machine.

Signed-off-by: Paolo Bonzini 
---
 include/hw/s390x/css.h |  6 ++
 include/hw/s390x/s390-virtio-ccw.h |  7 ---
 hw/s390x/css.c | 10 +++---
 hw/s390x/s390-virtio-ccw.c | 15 +++
 4 files changed, 16 insertions(+), 22 deletions(-)

diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index ba72ee3dd20..8289e458370 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -333,4 +333,10 @@ static inline int ccw_dstream_read_buf(CcwDataStream *cds, 
void *buff, int len)
 #define ccw_dstream_read(cds, v) ccw_dstream_read_buf((cds), &(v), sizeof(v))
 #define ccw_dstream_write(cds, v) ccw_dstream_write_buf((cds), &(v), sizeof(v))
 
+/**
+ * true if (vmstate based) migration of the channel subsystem
+ * is enabled, false if it is disabled.
+ */
+extern bool css_migration_enabled;
+
 #endif
diff --git a/include/hw/s390x/s390-virtio-ccw.h 
b/include/hw/s390x/s390-virtio-ccw.h
index c1d46e78af8..c0494e511cb 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -43,7 +43,6 @@ struct S390CcwMachineClass {
 /*< public >*/
 bool ri_allowed;
 bool cpu_model_allowed;
-bool css_migration_enabled;
 bool hpage_1m_allowed;
 int max_threads;
 };
@@ -55,10 +54,4 @@ bool cpu_model_allowed(void);
 /* 1M huge page mappings allowed by the machine */
 bool hpage_1m_allowed(void);
 
-/**
- * Returns true if (vmstate based) migration of the channel subsystem
- * is enabled, false if it is disabled.
- */
-bool css_migration_enabled(void);
-
 #endif
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 295530963a6..b2d5327dbf4 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -23,6 +23,8 @@
 #include "hw/s390x/s390-virtio-ccw.h"
 #include "hw/s390x/s390-ccw.h"
 
+bool css_migration_enabled = true;
+
 typedef struct CrwContainer {
 CRW crw;
 QTAILQ_ENTRY(CrwContainer) sibling;
@@ -180,7 +182,7 @@ static const VMStateDescription vmstate_orb = {
 
 static bool vmstate_schdev_orb_needed(void *opaque)
 {
-return css_migration_enabled();
+return css_migration_enabled;
 }
 
 static const VMStateDescription vmstate_schdev_orb = {
@@ -388,7 +390,7 @@ static int subch_dev_post_load(void *opaque, int version_id)
 css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
 }
 
-if (css_migration_enabled()) {
+if (css_migration_enabled) {
 /* No compat voodoo to do ;) */
 return 0;
 }
@@ -412,7 +414,9 @@ static int subch_dev_post_load(void *opaque, int version_id)
 
 void css_register_vmstate(void)
 {
-vmstate_register(NULL, 0, _css, _subsys);
+if (css_migration_enabled) {
+vmstate_register(NULL, 0, _css, _subsys);
+}
 }
 
 IndAddr *get_indicator(hwaddr ind_addr, int len)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1383e47eeb5..aa90703d518 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -275,11 +275,9 @@ static void ccw_init(MachineState *machine)
 s390_enable_css_support(s390_cpu_addr2state(0));
 
 ret = css_create_css_image(VIRTUAL_CSSID, true);
-
 assert(ret == 0);
-if (css_migration_enabled()) {
-css_register_vmstate();
-}
+
+css_register_vmstate();
 
 /* Create VirtIO network adapters */
 s390_create_virtio_net(BUS(css_bus), mc->default_nic);
@@ -741,7 +739,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void 
*data)
 
 s390mc->ri_allowed = true;
 s390mc->cpu_model_allowed = true;
-s390mc->css_migration_enabled = true;
 s390mc->hpage_1m_allowed = true;
 s390mc->max_threads = 1;
 mc->init = ccw_init;
@@ -811,11 +808,6 @@ static const TypeInfo ccw_machine_info = {
 },
 };
 
-bool css_migration_enabled(void)
-{
-return get_machine_class()->css_migration_enabled;
-}
-
 #define DEFINE_CCW_MACHINE(suffix, verstr, latest)\
 static void ccw_machine_##suffix##_class_init(ObjectClass *oc,\
   void *data) \
@@ -1171,7 +1163,6 @@ static void ccw_machine_2_9_instance_options(MachineState 
*machine)
 
 static void ccw_machine_2_9_class_options(MachineClass *mc)
 {
-S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
 static GlobalProperty compat[] = {
 { TYPE_S390_STATTRIB, "migration-enabled", "off", },
 { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
@@ -1180,7 +1171,7 @@ static void ccw_machine_2_9_class_options(MachineClass 
*mc)
 ccw_machine_2_10_class_options(mc);
 compat_props_add(mc-

[PATCH 06/13] xen: initialize legacy backends from xen_bus_init()

2024-05-09 Thread Paolo Bonzini
Prepare for moving the calls to xen_be_register() under the
control of xen_bus_init(), using the normal xen_backend_init()
method that is used by the "modern" backends.

This requires the xenstore global variable to be initialized,
which is done by xen_be_init().  To ensure that everything is
ready at the time the xen_backend_init() functions are called,
remove the xen_be_init() function from all the boards and
place it directly in xen_bus_init().

Signed-off-by: Paolo Bonzini 
---
 hw/i386/pc.c  | 1 -
 hw/xen/xen-bus.c  | 4 
 hw/xen/xen-hvm-common.c   | 2 --
 hw/xenpv/xen_machine_pv.c | 5 +
 4 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 505ea750f4d..19f21953b4a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1250,7 +1250,6 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 pci_create_simple(pcms->pcibus, -1, "xen-platform");
 }
 xen_bus_init();
-xen_be_init();
 }
 #endif
 
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index fb82cc33e48..95b207ac8b4 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -13,6 +13,7 @@
 #include "hw/sysbus.h"
 #include "hw/xen/xen.h"
 #include "hw/xen/xen-backend.h"
+#include "hw/xen/xen-legacy-backend.h" /* xen_be_init() */
 #include "hw/xen/xen-bus.h"
 #include "hw/xen/xen-bus-helper.h"
 #include "monitor/monitor.h"
@@ -329,6 +330,9 @@ static void xen_bus_realize(BusState *bus, Error **errp)
 goto fail;
 }
 
+/* Initialize legacy backend core & drivers */
+xen_be_init();
+
 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
   "domid", NULL, "%u", ) == 1) {
 xenbus->backend_id = domid;
diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index 1627da73982..2d1b0321214 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -872,8 +872,6 @@ void xen_register_ioreq(XenIOState *state, unsigned int 
max_cpus,
 
 xen_bus_init();
 
-xen_be_init();
-
 return;
 
 err:
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 1130d1a1479..b500ce09891 100644
--- a/hw/xenpv/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c
@@ -34,8 +34,7 @@ static void xen_init_pv(MachineState *machine)
 {
 setup_xen_backend_ops();
 
-/* Initialize backend core & drivers */
-xen_be_init();
+xen_bus_init();
 
 switch (xen_mode) {
 case XEN_ATTACH:
@@ -60,8 +59,6 @@ static void xen_init_pv(MachineState *machine)
 vga_interface_created = true;
 }
 
-xen_bus_init();
-
 /* config cleanup hook */
 atexit(xen_config_cleanup);
 }
-- 
2.45.0




[PATCH 00/13] fix --without-default-devices build and (mostly) tests

2024-05-09 Thread Paolo Bonzini
The recent change to make boards "default y" made them go away from
a --without-default-devices build, because the boards are not anymore
enabled explicitly in configs/devices/.

This is a problem for some targets that were not fully ready for this
and have generic target code that needs symbols from boards or devices.
The more complicated ones are s390x and i386.  In some cases some
components simply have to be required by target/ARCH/, but often
it is better to move some code around, associating it with boards
instead of targets or vice versa.

--without-default-devices builds in practice will always use a
custom config, but let's keep things tidy.  This series does
this for s390x (patches 1 to 5) and x86 (patches 6 to 12).  As a
small addendum, patch 13 fixes qtest for ARM (32- and 64-bit) on a
--without-default-devices build.

The series seems huge, but it's mostly code movement.  Patch 10
in particular moves board building code, which is unrelated to the
X86MachineState superclass and has many dependencies on NUMA or
hw/i386/pc-sysfw.c.

I suspect that there are more issues, for example when building
a CONFIG_MICROVM-only binary.  Fixing builds without boards on vanilla
upstream configs is the more pressing problem, though.

Patches 6 and 7 were tested with the Avocado Xen-on-KVM tests.

Paolo


Paolo Bonzini (13):
  s390x: move s390_cpu_addr2state to target/s390x/sigp.c
  s390_flic: add migration-enabled property
  s390: move css_migration_enabled from machine to css.c
  s390x: select correct components for no-board build
  tests/qtest: s390x: fix operation in a build without any boards or
devices
  xen: initialize legacy backends from xen_bus_init()
  xen: register legacy backends via xen_backend_init
  i386: correctly select code in hw/i386 that depends on other
components
  i386: pc: remove unnecessary MachineClass overrides
  hw/i386: split x86.c in multiple parts
  hw/i386: move rtc-reset-reinjection command out of hw/rtc
  i386: select correct components for no-board build
  tests/qtest: arm: fix operation in a build without any boards or
devices

 include/hw/i386/x86.h   |   10 +-
 include/hw/rtc/mc146818rtc.h|2 +-
 include/hw/s390x/css.h  |6 +
 include/hw/s390x/s390-virtio-ccw.h  |7 -
 include/hw/s390x/s390_flic.h|1 +
 include/hw/xen/xen-legacy-backend.h |   14 +-
 include/hw/xen/xen_pvdev.h  |1 -
 hw/9pfs/xen-9p-backend.c|8 +-
 hw/display/xenfb.c  |8 +-
 hw/i386/fw_cfg.c|2 +
 hw/i386/monitor.c   |   46 ++
 hw/i386/pc.c|4 -
 hw/i386/x86-common.c| 1007 +
 hw/i386/x86-cpu.c   |   97 +++
 hw/i386/x86.c   | 1058 +--
 hw/intc/ioapic-stub.c   |   29 +
 hw/intc/s390_flic.c |6 +-
 hw/rtc/mc146818rtc.c|   12 +-
 hw/s390x/css.c  |   10 +-
 hw/s390x/s390-virtio-ccw.c  |   32 +-
 hw/usb/xen-usb.c|   14 +-
 hw/xen/xen-bus.c|4 +
 hw/xen/xen-hvm-common.c |2 -
 hw/xen/xen-legacy-backend.c |   16 -
 hw/xenpv/xen_machine_pv.c   |5 +-
 target/s390x/sigp.c |   17 +
 tests/qtest/arm-cpu-features.c  |4 +
 tests/qtest/drive_del-test.c|7 +-
 tests/qtest/migration-test.c|6 +
 tests/qtest/numa-test.c |4 +
 .gitlab-ci.d/buildtest.yml  |4 +-
 hw/i386/meson.build |7 +-
 hw/intc/meson.build |2 +-
 target/i386/Kconfig |1 +
 target/s390x/Kconfig|2 +
 35 files changed, 1289 insertions(+), 1166 deletions(-)
 create mode 100644 hw/i386/monitor.c
 create mode 100644 hw/i386/x86-common.c
 create mode 100644 hw/i386/x86-cpu.c
 create mode 100644 hw/intc/ioapic-stub.c

-- 
2.45.0




[PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices

2024-05-09 Thread Paolo Bonzini
Do the bare minimum to ensure that at least a vanilla
--without-default-devices build works for all targets except i386,
x86_64 and ppc64.  In particular this fixes s390x-softmmu; i386 and
x86_64 have about a dozen failing tests that do not pass -M and therefore
require a default machine type; ppc64 has the same issue, though only
with numa-test.

If we can for now ignore the cases where boards and devices are picked
by hand, drive_del-test however can be fixed easily; almost all tests
check for the virtio-blk or virtio-scsi device that they use, and are
already skipped.  Only one didn't get the memo; plus another one does
not need a machine at all and can be run with -M none.

Signed-off-by: Paolo Bonzini 
---
 tests/qtest/drive_del-test.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/drive_del-test.c b/tests/qtest/drive_del-test.c
index 8a6f3ac963d..7b67a4bbee4 100644
--- a/tests/qtest/drive_del-test.c
+++ b/tests/qtest/drive_del-test.c
@@ -173,7 +173,7 @@ static void test_drive_without_dev(void)
 QTestState *qts;
 
 /* Start with an empty drive */
-qts = qtest_init("-drive if=none,id=drive0");
+qts = qtest_init("-drive if=none,id=drive0 -M none");
 
 /* Delete the drive */
 drive_del(qts);
@@ -192,6 +192,11 @@ static void test_after_failed_device_add(void)
 QDict *response;
 QTestState *qts;
 
+if (!has_device_builtin("virtio-blk")) {
+g_test_skip("Device virtio-blk is not available");
+return;
+}
+
 snprintf(driver, sizeof(driver), "virtio-blk-%s",
  qvirtio_get_dev_type());
 
-- 
2.45.0




[PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc

2024-05-09 Thread Paolo Bonzini
The rtc-reset-reinjection QMP command is specific to x86, other boards do not
have the ACK tracking functionality that is needed for RTC interrupt
reinjection.  Therefore the QMP command is only included in x86, but
qmp_rtc_reset_reinjection() is implemented by hw/rtc/mc146818rtc.c
and requires tracking of all created RTC devices.  Move the implementation
to hw/i386, so that 1) it is available even if no RTC device exist
2) the only RTC that exists is easily found in x86ms->rtc.

Signed-off-by: Paolo Bonzini 
---
 include/hw/rtc/mc146818rtc.h |  2 +-
 hw/i386/monitor.c| 46 
 hw/rtc/mc146818rtc.c | 12 ++
 hw/i386/meson.build  |  1 +
 4 files changed, 50 insertions(+), 11 deletions(-)
 create mode 100644 hw/i386/monitor.c

diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 97cec0b3e84..64893be1515 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -55,6 +55,6 @@ MC146818RtcState *mc146818_rtc_init(ISABus *bus, int 
base_year,
 qemu_irq intercept_irq);
 void mc146818rtc_set_cmos_data(MC146818RtcState *s, int addr, int val);
 int mc146818rtc_get_cmos_data(MC146818RtcState *s, int addr);
-void qmp_rtc_reset_reinjection(Error **errp);
+void rtc_reset_reinjection(MC146818RtcState *rtc);
 
 #endif /* HW_RTC_MC146818RTC_H */
diff --git a/hw/i386/monitor.c b/hw/i386/monitor.c
new file mode 100644
index 000..1ebd3564bf2
--- /dev/null
+++ b/hw/i386/monitor.c
@@ -0,0 +1,46 @@
+/*
+ * QEMU monitor
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "hw/i386/x86.h"
+#include "hw/rtc/mc146818rtc.h"
+
+#include CONFIG_DEVICES
+
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+X86MachineState *x86ms = X86_MACHINE(qdev_get_machine());
+
+#ifdef CONFIG_MC146818RTC
+if (x86ms->rtc) {
+rtc_reset_reinjection(MC146818_RTC(x86ms->rtc));
+}
+#else
+assert(!x86ms->rtc);
+#endif
+}
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index 3379f92748b..8ccee9a385d 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -104,16 +104,9 @@ static void rtc_coalesced_timer_update(MC146818RtcState *s)
 }
 }
 
-static QLIST_HEAD(, MC146818RtcState) rtc_devices =
-QLIST_HEAD_INITIALIZER(rtc_devices);
-
-void qmp_rtc_reset_reinjection(Error **errp)
+void rtc_reset_reinjection(MC146818RtcState *rtc)
 {
-MC146818RtcState *s;
-
-QLIST_FOREACH(s, _devices, link) {
-s->irq_coalesced = 0;
-}
+rtc->irq_coalesced = 0;
 }
 
 static bool rtc_policy_slew_deliver_irq(MC146818RtcState *s)
@@ -941,7 +934,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
 object_property_add_tm(OBJECT(s), "date", rtc_get_date);
 
 qdev_init_gpio_out(dev, >irq, 1);
-QLIST_INSERT_HEAD(_devices, s, link);
 }
 
 MC146818RtcState *mc146818_rtc_init(ISABus *bus, int base_year,
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 3437da0aad1..03aad10df7a 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -2,6 +2,7 @@ i386_ss = ss.source_set()
 i386_ss.add(files(
   'fw_cfg.c',
   'e820_memory_layout.c',
+  'monitor.c',
   'multiboot.c',
   'x86.c',
   'x86-cpu.c',
-- 
2.45.0




[PATCH 10/13] hw/i386: split x86.c in multiple parts

2024-05-09 Thread Paolo Bonzini
Keep the basic X86MachineState definition in x86.c.  Move out functions that
are only needed by other files: x86-common.c for the pc and microvm machines,
x86-cpu.c for those used by accelerator code.

Signed-off-by: Paolo Bonzini 
---
 include/hw/i386/x86.h |6 +-
 hw/i386/x86-common.c  | 1007 +++
 hw/i386/x86-cpu.c |   97 
 hw/i386/x86.c | 1052 +
 hw/i386/meson.build   |4 +-
 5 files changed, 1113 insertions(+), 1053 deletions(-)
 create mode 100644 hw/i386/x86-common.c
 create mode 100644 hw/i386/x86-cpu.c

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index c2062db13f5..b006f16b8d3 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -21,6 +21,7 @@
 #include "exec/memory.h"
 
 #include "hw/boards.h"
+#include "hw/i386/topology.h"
 #include "hw/intc/ioapic.h"
 #include "hw/isa/isa.h"
 #include "qom/object.h"
@@ -109,12 +110,11 @@ struct X86MachineState {
 #define TYPE_X86_MACHINE   MACHINE_TYPE_NAME("x86")
 OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE)
 
-uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
+void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
+uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
 unsigned int cpu_index);
 
-void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
 void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
-CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
 void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
 void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
   DeviceState *dev, Error **errp);
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
new file mode 100644
index 000..67b03c913a5
--- /dev/null
+++ b/hw/i386/x86-common.c
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2019, 2024 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/cutils.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+#include "qapi/error.h"
+#include "sysemu/numa.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/xen.h"
+#include "trace.h"
+
+#include "hw/i386/x86.h"
+#include "target/i386/cpu.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "target/i386/sev.h"
+
+#include "hw/acpi/cpu_hotplug.h"
+#include "hw/irq.h"
+#include "hw/loader.h"
+#include "multiboot.h"
+#include "elf.h"
+#include "standard-headers/asm-x86/bootparam.h"
+#include CONFIG_DEVICES
+#include "kvm/kvm_i386.h"
+
+#ifdef CONFIG_XEN_EMU
+#include "hw/xen/xen.h"
+#include "hw/i386/kvm/xen_evtchn.h"
+#endif
+
+/* Physical Address of PVH entry point read from kernel ELF NOTE */
+static size_t pvh_start_addr;
+
+static void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
+{
+Object *cpu = object_new(MACHINE(x86ms)->cpu_type);
+
+if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) {
+goto out;
+}
+qdev_realize(DEVICE(cpu), NULL, errp);
+
+out:
+object_unref(cpu);
+}
+
+void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
+{
+int i;
+const CPUArchIdList *possible_cpus;
+MachineState *ms = MACHINE(x86ms);
+MachineClass *mc = MACHINE_GET_CLASS(x86ms);
+
+x86_cpu_set_default_version(default_cpu_version);
+
+/*
+ * Calculates the limit to CPU APIC ID values
+ *
+ * Limit for the APIC ID value, so that all
+ * CPU APIC IDs ar

[PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides

2024-05-09 Thread Paolo Bonzini
There is no need to override these fields of MachineClass because they are
already set to the right value in the superclass.

Signed-off-by: Paolo Bonzini 
---
 include/hw/i386/x86.h | 4 
 hw/i386/pc.c  | 3 ---
 hw/i386/x86.c | 6 +++---
 3 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index d7b7d3f3ce0..c2062db13f5 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -114,10 +114,6 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
 
 void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
 void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
-CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
- unsigned cpu_index);
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx);
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);
 CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
 void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
 void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 19f21953b4a..bfb46e9b548 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1826,9 +1826,6 @@ static void pc_machine_class_init(ObjectClass *oc, void 
*data)
 assert(!mc->get_hotplug_handler);
 mc->get_hotplug_handler = pc_get_hotplug_handler;
 mc->hotplug_allowed = pc_hotplug_allowed;
-mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
-mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
-mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
 mc->auto_enable_numa_with_memhp = true;
 mc->auto_enable_numa_with_memdev = true;
 mc->has_hotpluggable_cpus = true;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index c61f4ebfa6a..fcef652c1e3 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -443,7 +443,7 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
 numa_cpu_pre_plug(cpu_slot, dev, errp);
 }
 
-CpuInstanceProperties
+static CpuInstanceProperties
 x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
 {
 MachineClass *mc = MACHINE_GET_CLASS(ms);
@@ -453,7 +453,7 @@ x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
 return possible_cpus->cpus[cpu_index].props;
 }
 
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
+static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
 {
X86CPUTopoIDs topo_ids;
X86MachineState *x86ms = X86_MACHINE(ms);
@@ -467,7 +467,7 @@ int64_t x86_get_default_cpu_node_id(const MachineState *ms, 
int idx)
return topo_ids.pkg_id % ms->numa_state->num_nodes;
 }
 
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
+static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
 {
 X86MachineState *x86ms = X86_MACHINE(ms);
 unsigned int max_cpus = ms->smp.max_cpus;
-- 
2.45.0




[PATCH 04/13] s390x: select correct components for no-board build

2024-05-09 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 .gitlab-ci.d/buildtest.yml | 4 ++--
 target/s390x/Kconfig   | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 13afd0df1f0..f8502905203 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
 # Check our reduced build configurations
 # requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
 #   mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, s390x, x86_64
+# does not build without boards: i386, x86_64
 build-without-defaults:
   extends: .native_build_job_template
   needs:
@@ -666,7 +666,7 @@ build-without-defaults:
   --disable-strip
 TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
   mips-softmmu mips64-softmmu mipsel-softmmu
-  sh4-softmmu sh4eb-softmmu sparc-softmmu
+  s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
   sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
   hexagon-linux-user i386-linux-user s390x-linux-user
 MAKE_CHECK_ARGS: check
diff --git a/target/s390x/Kconfig b/target/s390x/Kconfig
index 72da48136c6..d886be48b47 100644
--- a/target/s390x/Kconfig
+++ b/target/s390x/Kconfig
@@ -1,2 +1,4 @@
 config S390X
 bool
+select PCI
+select S390_FLIC
-- 
2.45.0




[PATCH] target/i386: add feature dependency for XSAVE

2024-05-09 Thread Paolo Bonzini
The XSAVEOPT, XSAVEC, XGETBV1, XSAVES features make no sense if you
cannot enable XSAVE in the first place.

Signed-off-by: Paolo Bonzini 
---
 target/i386/cpu.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f2ea6899e39..6f5ff71c6ee 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1550,6 +1550,10 @@ static FeatureDep feature_dependencies[] = {
 .from = { FEAT_8000_0001_ECX,   CPUID_EXT3_SVM },
 .to = { FEAT_SVM,   ~0ull },
 },
+{
+.from = { FEAT_1_ECX,   CPUID_EXT_XSAVE },
+.to = { FEAT_XSAVE, ~0ull },
+},
 {
 .from = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
 .to = { FEAT_VMX_SECONDARY_CTLS,
VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
-- 
2.45.0




[PATCH] target/i386: fix feature dependency for WAITPKG

2024-05-09 Thread Paolo Bonzini
The VMX feature bit depends on general availability of WAITPKG,
not the other way round.

Fixes: 33cc88261c3 ("target/i386: add support for 
VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE", 2023-08-28)
Cc: qemu-sta...@nongnu.org
Signed-off-by: Paolo Bonzini 
---
 target/i386/cpu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1058b6803fd..f2ea6899e39 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1551,8 +1551,8 @@ static FeatureDep feature_dependencies[] = {
 .to = { FEAT_SVM,   ~0ull },
 },
 {
-.from = { FEAT_VMX_SECONDARY_CTLS,  
VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
-.to = { FEAT_7_0_ECX,   CPUID_7_0_ECX_WAITPKG },
+.from = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
+.to = { FEAT_VMX_SECONDARY_CTLS,
VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
 },
 };
 
-- 
2.45.0




[PATCH] target/i386: move prefetch and multi-byte UD/NOP to new decoder

2024-05-09 Thread Paolo Bonzini
These are trivial to add, and moving them to the new decoder fixes some
corner cases: raising #UD instead of an instruction fetch page fault for
the undefined opcodes, and incorrectly rejecting 0F 18 prefetches with
register operands (which are treated as reserved NOPs).

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |  1 +
 target/i386/tcg/translate.c  | 30 --
 target/i386/tcg/decode-new.c.inc | 24 +---
 target/i386/tcg/emit.c.inc   |  5 +
 4 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 2ea06b44787..51ef0e621b9 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -50,6 +50,7 @@ typedef enum X86OpType {
 X86_TYPE_EM, /* modrm byte selects an ALU memory operand */
 X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
 X86_TYPE_I_unsigned, /* Immediate, zero-extended */
+X86_TYPE_nop, /* modrm operand decoded but not loaded into s->T{0,1} */
 X86_TYPE_2op, /* 2-operand RMW instruction */
 X86_TYPE_LoBits, /* encoded in bits 0-2 of the operand + REX.B */
 X86_TYPE_0, /* Hard-coded GPRs (RAX..RDI) */
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3da4fdf64cc..de87775016b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4019,25 +4019,6 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 set_cc_op(s, CC_OP_EFLAGS);
 }
 break;
-case 0x118:
-modrm = x86_ldub_code(env, s);
-mod = (modrm >> 6) & 3;
-op = (modrm >> 3) & 7;
-switch(op) {
-case 0: /* prefetchnta */
-case 1: /* prefetchnt0 */
-case 2: /* prefetchnt0 */
-case 3: /* prefetchnt0 */
-if (mod == 3)
-goto illegal_op;
-gen_nop_modrm(env, s, modrm);
-/* nothing more to do */
-break;
-default: /* nop (multi byte) */
-gen_nop_modrm(env, s, modrm);
-break;
-}
-break;
 case 0x11a:
 modrm = x86_ldub_code(env, s);
 if (s->flags & HF_MPX_EN_MASK) {
@@ -4229,10 +4210,6 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 }
 gen_nop_modrm(env, s, modrm);
 break;
-case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
-modrm = x86_ldub_code(env, s);
-gen_nop_modrm(env, s, modrm);
-break;
 
 case 0x120: /* mov reg, crN */
 case 0x122: /* mov crN, reg */
@@ -4506,13 +4483,6 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 }
 break;
 
-case 0x10d: /* 3DNow! prefetch(w) */
-modrm = x86_ldub_code(env, s);
-mod = (modrm >> 6) & 3;
-if (mod == 3)
-goto illegal_op;
-gen_nop_modrm(env, s, modrm);
-break;
 case 0x1aa: /* rsm */
 gen_svm_check_intercept(s, SVM_EXIT_RSM);
 if (!(s->flags & HF_SMM_MASK))
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 0e1811399f8..4baf7672158 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -55,6 +55,10 @@
  * mask could be applied (and the original sign-extended value would be
  * optimized away by TCG) in the emitter function.
  *
+ * Finally, a "nop" operand type is used for multi-byte NOPs.  It accepts
+ * any value of mod including 11b (unlike M) but it does not try to
+ * interpret the operand (like M).
+ *
  * Vector operands
  * ---
  *
@@ -1056,6 +1060,16 @@ static const X86OpEntry opcodes_0F[256] = {
 [0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
 [0xa1] = X86_OP_ENTRYw(POP, FS, w),
 
+[0x0b] = X86_OP_ENTRY0(UD),   /* UD2 */
+[0x0d] = X86_OP_ENTRY1(NOP,  M,v),/* 3DNow! prefetch */
+
+[0x18] = X86_OP_ENTRY1(NOP,  nop,v),  /* prefetch/reserved NOP */
+[0x19] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1c] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1d] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1e] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+[0x1f] = X86_OP_ENTRY1(NOP,  nop,v),  /* reserved NOP */
+
 [0x28] = X86_OP_ENTRY3(MOVDQ,  V,x,  None,None, W,x, vex1 p_00_66), /* 
MOVAPS */
 [0x29] = X86_OP_ENTRY3(MOVDQ,  W,x,  None,None, V,x, vex1 p_00_66), /* 
MOVAPS */
 [0x2A] = X86_OP_GROUP0(0F2A),
@@ -1135,6 +1149,8 @@ static const X86OpEntry opcodes_0F[256] = {
 [0xb6] = X86_OP_ENTRY3(MOV,G,v, E,b, None, None, zextT0), /* MOVZX */
 [0xb7] = X86_OP_ENTRY3(MOV,G,v, E,w, None, None, zextT0), /* MOVZX */
 
+/* decoded as modrm, which is visible as a difference between page fault 
and #UD */
+[0xb9] = X86_OP_ENTRYr(UD, nop,v),/* UD1 */

[PATCH] target/i386: fix operand size for DATA16 REX.W POPCNT

2024-05-09 Thread Paolo Bonzini
According to the manual, 32-bit vs 64-bit is governed by REX.W
and REX ignores the 0x66 prefix.  This can be confirmed with this
program:

#include 
int main()
{
   int x = 0x1234;
   int y;
   asm("popcntl %1, %0" : "=r" (y) : "r" (x)); printf("%x\n", y);
   asm("mov $-1, %0; .byte 0x66; popcntl %1, %0" : "+r" (y) : "r" (x)); 
printf("%x\n", y);
   asm("mov $-1, %0; .byte 0x66; popcntq %q1, %q0" : "+r" (y) : "r" (x)); 
printf("%x\n", y);
}

which prints 5//5 on real hardware and 5//
on QEMU.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 17 +
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 7d9f6b5c55b..5366dc32dd3 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -411,16 +411,6 @@ static inline MemOp mo_stacksize(DisasContext *s)
 return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
 }
 
-/* Select only size 64 else 32.  Used for SSE operand sizes.  */
-static inline MemOp mo_64_32(MemOp ot)
-{
-#ifdef TARGET_X86_64
-return ot == MO_64 ? MO_64 : MO_32;
-#else
-return MO_32;
-#endif
-}
-
 /* Select size 8 if lsb of B is clear, else OT.  Used for decoding
byte vs word opcodes.  */
 static inline MemOp mo_b_d(int b, MemOp ot)
@@ -4545,12 +4535,7 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 modrm = x86_ldub_code(env, s);
 reg = ((modrm >> 3) & 7) | REX_R(s);
 
-if (s->prefix & PREFIX_DATA) {
-ot = MO_16;
-} else {
-ot = mo_64_32(dflag);
-}
-
+ot = dflag;
 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
 gen_extu(ot, s->T0);
 tcg_gen_mov_tl(cpu_cc_src, s->T0);
-- 
2.45.0




[PATCH] tests/tcg: cover lzcnt/tzcnt/popcnt

2024-05-09 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 tests/tcg/i386/test-i386.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
index 864c4e620d5..ce3bf74b5a8 100644
--- a/tests/tcg/i386/test-i386.c
+++ b/tests/tcg/i386/test-i386.c
@@ -715,6 +715,30 @@ void test_mul(void)
 printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
 }
 
+void test_xcnt(void)
+{
+TEST_BSX(tzcntw, "w", 0);
+TEST_BSX(tzcntw, "w", 0x12340128);
+TEST_BSX(lzcntw, "w", 0);
+TEST_BSX(lzcntw, "w", 0x12340128);
+TEST_BSX(popcntw, "w", 0);
+TEST_BSX(popcntw, "w", 0x12340128);
+TEST_BSX(tzcntl, "k", 0);
+TEST_BSX(tzcntl, "k", 0x00340128);
+TEST_BSX(lzcntl, "k", 0);
+TEST_BSX(lzcntl, "k", 0x00340128);
+TEST_BSX(popcntl, "k", 0);
+TEST_BSX(popcntl, "k", 0x00340128);
+#if defined(__x86_64__)
+TEST_BSX(tzcntq, "", 0);
+TEST_BSX(tzcntq, "", 0x003401281234);
+TEST_BSX(lzcntq, "", 0);
+TEST_BSX(lzcntq, "", 0x003401281234);
+TEST_BSX(popcntq, "", 0);
+TEST_BSX(popcntq, "", 0x003401281234);
+#endif
+}
+
 void test_bsx(void)
 {
 TEST_BSX(bsrw, "w", 0);
@@ -2162,6 +2186,7 @@ int main(int argc, char **argv)
 func();
 }
 test_bsx();
+test_xcnt();
 test_mul();
 test_jcc();
 test_loop();
-- 
2.45.0




[PATCH] target/i386: rdpkru/wrpkru are no-prefix instructions

2024-05-09 Thread Paolo Bonzini
Reject 0x66/0xf3/0xf2 in front of them.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5366dc32dd3..3da4fdf64cc 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3907,7 +3907,8 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
 break;
 case 0xee: /* rdpkru */
-if (prefixes & PREFIX_LOCK) {
+if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
+ | PREFIX_REPZ | PREFIX_REPNZ)) {
 goto illegal_op;
 }
 tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
@@ -3915,7 +3916,8 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
 break;
 case 0xef: /* wrpkru */
-if (prefixes & PREFIX_LOCK) {
+if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
+ | PREFIX_REPZ | PREFIX_REPNZ)) {
 goto illegal_op;
 }
 tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
-- 
2.45.0




Re: [PATCH v2 6/6] hw/i386/pc_sysfw: Alias rather than copy isa-bios region

2024-05-08 Thread Paolo Bonzini
On Tue, Apr 30, 2024 at 5:39 PM Philippe Mathieu-Daudé
 wrote:
> I'm still not convinced we need a migration back compat for this...

It's absolutely needed,

memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
   _fatal);

will register a RAM region for migration, and when the destination
receives data from an older source, it will not find it it will fail.
On the other hand, if migrating backwards isa-bios will not be
populated and the guest may fail after reboot.

Paolo

> > diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
> > index 82d37cb376..ac88ad4eb9 100644
> > --- a/hw/i386/pc_sysfw.c
> > +++ b/hw/i386/pc_sysfw.c
> > @@ -135,6 +135,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
> >   MemoryRegion *rom_memory)
> >   {
> >   X86MachineState *x86ms = X86_MACHINE(pcms);
> > +PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> >   hwaddr total_size = 0;
> >   int i;
> >   BlockBackend *blk;
> > @@ -184,7 +185,12 @@ static void pc_system_flash_map(PCMachineState *pcms,
> >
> >   if (i == 0) {
> >   flash_mem = pflash_cfi01_get_memory(system_flash);
> > -pc_isa_bios_init(>isa_bios, rom_memory, flash_mem);
> > +if (pcmc->isa_bios_alias) {
> > +x86_isa_bios_init(>isa_bios, rom_memory, flash_mem,
> > +  true);
> > +} else {
> > +pc_isa_bios_init(>isa_bios, rom_memory, flash_mem);
> > +}
> >
> >   /* Encrypt the pflash boot ROM */
> >   if (sev_enabled()) {
>




[PATCH] target/i386: remove PCOMMIT from TCG, deprecate property

2024-05-08 Thread Paolo Bonzini
The PCOMMIT instruction was never included in any physical processor.
TCG implements it as a no-op instruction, but its utility is debatable
to say the least.  Drop it from the decoder since it is only available
with "-cpu max", which does not guarantee migration compatibility
across versions, and deprecate the property just in case someone is
using it as "pcommit=off".

Signed-off-by: Paolo Bonzini 
---
 docs/about/deprecated.rst   |  8 
 target/i386/cpu.h   |  2 --
 target/i386/cpu.c   |  2 +-
 target/i386/tcg/translate.c | 12 +---
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 03f8b1b655e..b87fe70be47 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -418,6 +418,14 @@ Backend ``memory`` (since 9.0)
 CPU device properties
 '
 
+``pcommit`` on x86 (since 9.1)
+^^
+
+The PCOMMIT instruction was never included in any physical processor.
+It was implemented as a no-op instruction in TCG up to QEMU 9.0, but
+only with ``-cpu max`` (which does not guarantee migration compatibility
+across versions).
+
 ``pmu-num=n`` on RISC-V CPUs (since 8.2)
 
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 1e0d2c915f5..b62fc35 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -816,8 +816,6 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
 #define CPUID_7_0_EBX_SMAP  (1U << 20)
 /* AVX-512 Integer Fused Multiply Add */
 #define CPUID_7_0_EBX_AVX512IFMA(1U << 21)
-/* Persistent Commit */
-#define CPUID_7_0_EBX_PCOMMIT   (1U << 22)
 /* Flush a Cache Line Optimized */
 #define CPUID_7_0_EBX_CLFLUSHOPT(1U << 23)
 /* Cache Line Write Back */
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1058b6803fd..79372de8c5a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -713,7 +713,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
 #endif
 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
   CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
-  CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT |\
+  CPUID_7_0_EBX_CLFLUSHOPT |\
   CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \
   CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_RDSEED | \
   CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_KERNEL_FEATURES)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3842b294842..7d9f6b5c55b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4487,17 +4487,7 @@ static void disas_insn_old(DisasContext *s, CPUState 
*cpu, int b)
 }
 goto unknown_op;
 
-case 0xf8: /* sfence / pcommit */
-if (prefixes & PREFIX_DATA) {
-/* pcommit */
-if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
-|| (prefixes & PREFIX_LOCK)) {
-goto illegal_op;
-}
-break;
-}
-/* fallthru */
-case 0xf9 ... 0xff: /* sfence */
+case 0xf8 ... 0xff: /* sfence */
 if (!(s->cpuid_features & CPUID_SSE)
 || (prefixes & PREFIX_LOCK)) {
 goto illegal_op;
-- 
2.45.0




Re: Hermetic virtio-vsock in QEMU

2024-05-08 Thread Paolo Bonzini
On Wed, May 8, 2024 at 2:51 PM Daniel P. Berrangé  wrote:
> Designwise, a native VSOCK backend in QEMU really should implement the
> same approach defined by firecracker, so that we have interoperability
> with systemd, firecracker and cloud-hypervisor. See
>
>   https://gitlab.com/qemu-project/qemu/-/issues/2095
>   
> https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md#firecracker-virtio-vsock-design
>
> This involves multiple UNIX sockets on the host
>
>   1 * /some/path   - QEMU listens on this, and accepts connections
>  from other host processes. The client sends
>  "PORT " to indicate that guest port it
>  is connecting to
>
>   n * /some/path_$PORT - QEMU connect to this for outgoing connections
>  from the guest. Other host processes need
>  to listen on whatever path_$PORT need to be
>  serviced

The former is quite horrible, but okay. Out of curiosity, which
clients are using that convention?

> IOW, from a CLI pov, QEMU should need nothing more than
>
> -object vsock-forward,prefix=/some/path

I would call this a "vsock-namespace" object with a matching namespace
property on the virtio-vsock device.  The id on the vsock-namespace
object would also allow 1) adding vsock-forward objects hanging from
the namespace 2) omitting the prefix to only allow specifying
connections via vsock-forward.

I agree that allowing interoperability with existing implementations
is nice to have, at least as a principle.

Paolo




Re: Hermetic virtio-vsock in QEMU

2024-05-08 Thread Paolo Bonzini

On 5/8/24 11:38, Stefano Garzarella wrote:

On Wed, May 08, 2024 at 01:13:09PM GMT, Marc-André Lureau wrote:

Hi

On Wed, May 8, 2024 at 11:50 AM Stefano Garzarella 
 wrote:


Hi Roman,

On Tue, May 07, 2024 at 11:20:50PM GMT, Roman Kiryanov wrote:
>Hi Stefano,
>
>On Tue, May 7, 2024 at 1:10 AM Stefano Garzarella 
 wrote:
>> I have no experience with Windows, but what we need for vhost-user 
is:

>>
>> - AF_UNIX and be able to send file descriptors using ancillary data
>>    (i.e. SCM_RIGHTS)
>
>As far as I understand, Windows does NOT support SCM_RIGHTS over 
AF_UNIX.


Thank you for the information. This is unfortunate and does not allow
us to use vhost-user as it is on Windows.



fwiw, Windows has other mechanisms to share resources between processes.

To share/pass sockets, you can use WSADuplicateSocket. For shared
memory and other resources, DuplicateHandle API.


Cool, thanks for sharing that. So it could be done, but I think we need
to extend the vhost-user protocol to work with Windows.


It would be possible to implement the memfd backend for Windows, using 
the CreateFileMapping() API.


However, the vhost-user protocol's VHOST_USER_SET_MEM_TABLE requests do 
not have any padding that can be used to pass the handle to the target. 
An extended version would be necessary.


One difference between Unix and Windows is that, if the vhost-server 
messes up the handling of messages from the socket, and therefore it 
does not close the handle, it is leaked forever.  This is not a huge 
deal per se, but I think it means that QEMU is not allowed to "open" a 
privileged vhost-user server process with PROCESS_DUP_HANDLE rights 
(translation: QEMU cannot provide duplicate handles to a privileged 
vhost-user server process).


Also I'm not sure what the cost of DuplicateHandle() is, and whether 
it's a good idea to do it for every region on every 
VHOST_USER_SET_MEM_TABLE request.  But VHOST_USER_SET_MEM_TABLE is not a 
fast path, so perhaps it's okay.


I think a virtio-vsock implementation in QEMU would be easier, lacking 
another usecase for vhost-user on Windows.


The main design question is whether multiple virtio-vsock devices for 
the same guest should share the CID space or not (I think it should, but 
I'm not 100% sure).  To connect host<->guest you could have a QOM 
object, here I am naming it vsock-forward as an example:


  -object vsock-forward,socket=SocketAddress,port=uint32,mode=connect

 takes the address of a listening socket on the host, and all
 connections to the given vsock port would be forwarded to the
 socket.

  -object vsock-forward,socket=SocketAddress,port=uint32,mode=listen

 creates a listening socket on the host, and all connections to that
 socket would be forwarded to the vsock port, where the guest should
 set up a server.

i.e. "mode" is what QEMU does, whether connect to the address or listen 
on it.


Another possibility for the names is to copy "hostfwd" and "guestfwd" 
names that are in netdev -netdev, i.e. respectively:


  -object vsock-guestfwd,socket=SocketAddress,port=uint32
  -object vsock-hostfwd,socket=SocketAddress,port=uint32

but I think it's worse.

Paolo




[PATCH] virtio-blk: remove SCSI passthrough functionality

2024-05-08 Thread Paolo Bonzini
The legacy SCSI passthrough functionality has never been enabled for
VIRTIO 1.0 and was deprecated more than four years ago.

Get rid of it---almost, because QEMU is advertising it unconditionally
for legacy virtio-blk devices.  Just parse the header and return a
nonzero status.

Signed-off-by: Paolo Bonzini 
---
 docs/about/deprecated.rst   |  10 --
 docs/about/removed-features.rst |   8 ++
 hw/block/virtio-blk.c   | 166 +++-
 hw/core/machine.c   |   2 -
 4 files changed, 19 insertions(+), 167 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 03f8b1b655e..9bfaeda3adb 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -282,16 +282,6 @@ Device options
 Emulated device options
 '''
 
-``-device virtio-blk,scsi=on|off`` (since 5.0)
-^^
-
-The virtio-blk SCSI passthrough feature is a legacy VIRTIO feature.  VIRTIO 1.0
-and later do not support it because the virtio-scsi device was introduced for
-full SCSI support.  Use virtio-scsi instead when SCSI passthrough is required.
-
-Note this also applies to ``-device virtio-blk-pci,scsi=on|off``, which is an
-alias.
-
 ``-device nvme-ns,eui64-default=on|off`` (since 7.1)
 
 
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index 53ca08aba9c..1044d657c1a 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -505,6 +505,14 @@ configurations (e.g. -smp 8,sockets=0) is removed since 
9.0, users have
 to ensure that all the topology members described with -smp are greater
 than zero.
 
+``-device virtio-blk,scsi=on|off`` (since 9.1)
+^^
+
+The virtio-blk SCSI passthrough feature is a legacy VIRTIO feature.  VIRTIO 1.0
+and later do not support it because the virtio-scsi device was introduced for
+full SCSI support.  Use virtio-scsi instead when SCSI passthrough is required.
+
+
 User-mode emulator command line arguments
 -
 
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index bb86e65f652..73bdfd6122a 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -172,57 +172,6 @@ static void virtio_blk_discard_write_zeroes_complete(void 
*opaque, int ret)
 virtio_blk_free_request(req);
 }
 
-#ifdef __linux__
-
-typedef struct {
-VirtIOBlockReq *req;
-struct sg_io_hdr hdr;
-} VirtIOBlockIoctlReq;
-
-static void virtio_blk_ioctl_complete(void *opaque, int status)
-{
-VirtIOBlockIoctlReq *ioctl_req = opaque;
-VirtIOBlockReq *req = ioctl_req->req;
-VirtIOBlock *s = req->dev;
-VirtIODevice *vdev = VIRTIO_DEVICE(s);
-struct virtio_scsi_inhdr *scsi;
-struct sg_io_hdr *hdr;
-
-scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
-
-if (status) {
-status = VIRTIO_BLK_S_UNSUPP;
-virtio_stl_p(vdev, >errors, 255);
-goto out;
-}
-
-hdr = _req->hdr;
-/*
- * From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi)
- * clear the masked_status field [hence status gets cleared too, see
- * block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED
- * status has occurred.  However they do set DRIVER_SENSE in driver_status
- * field. Also a (sb_len_wr > 0) indicates there is a sense buffer.
- */
-if (hdr->status == 0 && hdr->sb_len_wr > 0) {
-hdr->status = CHECK_CONDITION;
-}
-
-virtio_stl_p(vdev, >errors,
- hdr->status | (hdr->msg_status << 8) |
- (hdr->host_status << 16) | (hdr->driver_status << 24));
-virtio_stl_p(vdev, >residual, hdr->resid);
-virtio_stl_p(vdev, >sense_len, hdr->sb_len_wr);
-virtio_stl_p(vdev, >data_len, hdr->dxfer_len);
-
-out:
-virtio_blk_req_complete(req, status);
-virtio_blk_free_request(req);
-g_free(ioctl_req);
-}
-
-#endif
-
 static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s, VirtQueue *vq)
 {
 VirtIOBlockReq *req = virtqueue_pop(vq, sizeof(VirtIOBlockReq));
@@ -233,20 +182,14 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock 
*s, VirtQueue *vq)
 return req;
 }
 
-static int virtio_blk_handle_scsi_req(VirtIOBlockReq *req)
+static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 {
-int status = VIRTIO_BLK_S_OK;
-struct virtio_scsi_inhdr *scsi = NULL;
+int status;
+struct virtio_scsi_inhdr *scsi;
 VirtIOBlock *blk = req->dev;
 VirtIODevice *vdev = VIRTIO_DEVICE(blk);
 VirtQueueElement *elem = >elem;
 
-#ifdef __linux__
-int i;
-VirtIOBlockIoctlReq *ioctl_req;
-BlockAIOCB *acb;
-#endif
-
 /*
  * We require at least one output segment each for the virtio_blk_outhdr
  * and 

[PATCH 5/6] hw/xtensa: require libfdt

2024-05-08 Thread Paolo Bonzini
All other boards require libfdt if it can be used (including for example
i386/x86_64), so change the "imply" to "select" and always allow -dtb
in qemu-system-xtensa.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 hw/xtensa/xtfpga.c | 9 -
 hw/xtensa/Kconfig  | 4 ++--
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index f49e6591dc2..955e8867a36 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -356,7 +356,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE,
  strlen(kernel_cmdline) + 1, kernel_cmdline);
 }
-#ifdef CONFIG_FDT
 if (dtb_filename) {
 int fdt_size;
 void *fdt = load_device_tree(dtb_filename, _size);
@@ -373,14 +372,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4 * KiB);
 g_free(fdt);
 }
-#else
-if (dtb_filename) {
-error_report("could not load DTB '%s': "
- "FDT support is not configured in QEMU",
- dtb_filename);
-exit(EXIT_FAILURE);
-}
-#endif
 if (initrd_filename) {
 BpMemInfo initrd_location = { 0 };
 int initrd_size = load_ramdisk(initrd_filename, cur_lowmem,
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
index 8ea283a7a3b..fc5c785cfac 100644
--- a/hw/xtensa/Kconfig
+++ b/hw/xtensa/Kconfig
@@ -14,8 +14,8 @@ config XTENSA_VIRT
 config XTENSA_XTFPGA
 bool
 default y
-depends on XTENSA
-imply DEVICE_TREE
+depends on XTENSA && FDT
+select DEVICE_TREE
 select OPENCORES_ETH
 select PFLASH_CFI01
 select SERIAL
-- 
2.45.0




[PATCH 6/6] configs: disable emulators that require it if libfdt is not found

2024-05-08 Thread Paolo Bonzini
Since boards can express their dependency on libfdt and
system/device_tree.c, only leave TARGET_NEED_FDT if the target has a
hard dependency.

Those emulators will be skipped if libfdt is disabled, or if it
is "auto" and not found and --disable-download is passed; unless
the target is mentioned explicitly in --target-list, in which case
the build will fail.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 configs/targets/aarch64-softmmu.mak  | 1 +
 configs/targets/arm-softmmu.mak  | 1 +
 configs/targets/i386-softmmu.mak | 1 -
 configs/targets/loongarch64-softmmu.mak  | 1 +
 configs/targets/microblaze-softmmu.mak   | 1 +
 configs/targets/microblazeel-softmmu.mak | 1 +
 configs/targets/mips64el-softmmu.mak | 1 -
 configs/targets/or1k-softmmu.mak | 1 +
 configs/targets/ppc-softmmu.mak  | 1 -
 configs/targets/ppc64-softmmu.mak| 1 +
 configs/targets/riscv32-softmmu.mak  | 1 +
 configs/targets/riscv64-softmmu.mak  | 1 +
 configs/targets/rx-softmmu.mak   | 1 +
 configs/targets/x86_64-softmmu.mak   | 1 -
 meson.build  | 6 +-
 .gitlab-ci.d/buildtest.yml   | 8 
 16 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/configs/targets/aarch64-softmmu.mak 
b/configs/targets/aarch64-softmmu.mak
index 83c22391a69..84cb32dc2f4 100644
--- a/configs/targets/aarch64-softmmu.mak
+++ b/configs/targets/aarch64-softmmu.mak
@@ -3,4 +3,5 @@ TARGET_BASE_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml 
gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml 
gdb-xml/arm-m-profile-mve.xml gdb-xml/aarch64-pauth.xml
+# needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/configs/targets/arm-softmmu.mak b/configs/targets/arm-softmmu.mak
index 92c8349b964..bf390b7a8de 100644
--- a/configs/targets/arm-softmmu.mak
+++ b/configs/targets/arm-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml 
gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml 
gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
+# needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index d61b5076134..2ac69d5ba37 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,5 +1,4 @@
 TARGET_ARCH=i386
 TARGET_SUPPORTS_MTTCG=y
-TARGET_NEED_FDT=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/i386-32bit.xml
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
index f23780fdd89..84beb19b90a 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -2,4 +2,5 @@ TARGET_ARCH=loongarch64
 TARGET_BASE_ARCH=loongarch
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/loongarch-base32.xml gdb-xml/loongarch-base64.xml 
gdb-xml/loongarch-fpu.xml
+# all boards require libfdt
 TARGET_NEED_FDT=y
diff --git a/configs/targets/microblaze-softmmu.mak 
b/configs/targets/microblaze-softmmu.mak
index e84c0cc7283..eea266d4f3d 100644
--- a/configs/targets/microblaze-softmmu.mak
+++ b/configs/targets/microblaze-softmmu.mak
@@ -1,5 +1,6 @@
 TARGET_ARCH=microblaze
 TARGET_BIG_ENDIAN=y
 TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_XML_FILES=gdb-xml/microblaze-core.xml 
gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/microblazeel-softmmu.mak 
b/configs/targets/microblazeel-softmmu.mak
index 9b688036bd3..77b968acad3 100644
--- a/configs/targets/microblazeel-softmmu.mak
+++ b/configs/targets/microblazeel-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=microblaze
 TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_XML_FILES=gdb-xml/microblaze-core.xml 
gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/mips64el-softmmu.mak 
b/configs/targets/mips64el-softmmu.mak
index 8d9ab3ddc4b..3864daa7364 100644
--- a/configs/targets/mips64el-softmmu.mak
+++ b/configs/targets/mips64el-softmmu.mak
@@ -1,3 +1,2 @@
 TARGET_ARCH=mips64
 TARGET_BASE_ARCH=mips
-TARGET_NEED_FDT=y
diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 432f855a30a..0341cb2a6b3 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=openrisc
 TARGET_SUPPORTS_MTTCG=y
 TARGET_BIG_ENDIAN=y
+# needed by boot.c and all boards
 TARGET_NEED_FDT=y
diff --git a/configs/targets/ppc-softmmu.mak b/configs/targets/ppc-softmmu.mak
index f3ea9c98f75..53120dab41d 100644
--- a/configs/targets/ppc-softmmu.mak
+++ b/configs/targets/ppc-softmmu.mak
@@ -2,4 +2,3 @@ TARGET_ARCH=ppc
 TARGET_BIG_ENDIAN=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/power-core.xml gdb-xml/power-fpu.xm

[PATCH 3/6] kconfig: allow compiling out QEMU device tree code per target

2024-05-08 Thread Paolo Bonzini
Introduce a new Kconfig symbol, CONFIG_DEVICE_TREE, that specifies whether
to include the common device tree code in system/device_tree.c and to
link to libfdt.  For now, include it unconditionally if libfdt is
available.

Signed-off-by: Paolo Bonzini 
---
 meson.build  |  1 +
 include/monitor/hmp.h|  1 +
 include/sysemu/device_tree.h |  1 -
 monitor/hmp-cmds.c   | 17 +
 system/device_tree-stub.c| 10 ++
 system/device_tree.c | 14 --
 Kconfig.host |  4 
 hw/core/Kconfig  |  9 -
 hw/core/meson.build  |  2 +-
 system/meson.build   |  4 +++-
 10 files changed, 45 insertions(+), 18 deletions(-)
 create mode 100644 system/device_tree-stub.c

diff --git a/meson.build b/meson.build
index 2e7e2b15406..d8f259d2610 100644
--- a/meson.build
+++ b/meson.build
@@ -2990,6 +2990,7 @@ host_kconfig = \
   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
   (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
   (x11.found() ? ['CONFIG_X11=y'] : []) + \
+  (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
   (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
   (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
   (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index f4cf8f6717d..954f3c83ad9 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -180,5 +180,6 @@ void hmp_ioport_write(Monitor *mon, const QDict *qdict);
 void hmp_boot_set(Monitor *mon, const QDict *qdict);
 void hmp_info_mtree(Monitor *mon, const QDict *qdict);
 void hmp_info_cryptodev(Monitor *mon, const QDict *qdict);
+void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index 8eab3959341..eb601522f88 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -134,7 +134,6 @@ int qemu_fdt_add_path(void *fdt, const char *path);
 } while (0)
 
 void qemu_fdt_dumpdtb(void *fdt, int size);
-void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
 
 /**
  * qemu_fdt_setprop_sized_cells_from_array:
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 871898ac46b..ea79148ee85 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -22,6 +22,7 @@
 #include "monitor/monitor-internal.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-control.h"
+#include "qapi/qapi-commands-machine.h"
 #include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qdict.h"
 #include "qemu/cutils.h"
@@ -443,3 +444,19 @@ void hmp_info_mtree(Monitor *mon, const QDict *qdict)
 
 mtree_info(flatview, dispatch_tree, owner, disabled);
 }
+
+#if defined(CONFIG_FDT)
+void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
+{
+const char *filename = qdict_get_str(qdict, "filename");
+Error *local_err = NULL;
+
+qmp_dumpdtb(filename, _err);
+
+if (hmp_handle_error(mon, local_err)) {
+return;
+}
+
+monitor_printf(mon, "dtb dumped to %s", filename);
+}
+#endif
diff --git a/system/device_tree-stub.c b/system/device_tree-stub.c
new file mode 100644
index 000..bddda6fa37a
--- /dev/null
+++ b/system/device_tree-stub.c
@@ -0,0 +1,10 @@
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
+
+#ifdef CONFIG_FDT
+void qmp_dumpdtb(const char *filename, Error **errp)
+{
+error_setg(errp, "This machine doesn't have a FDT");
+}
+#endif
diff --git a/system/device_tree.c b/system/device_tree.c
index eb5166ca360..2e38259d34f 100644
--- a/system/device_tree.c
+++ b/system/device_tree.c
@@ -668,20 +668,6 @@ void qmp_dumpdtb(const char *filename, Error **errp)
 }
 }
 
-void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
-{
-const char *filename = qdict_get_str(qdict, "filename");
-Error *local_err = NULL;
-
-qmp_dumpdtb(filename, _err);
-
-if (hmp_handle_error(mon, local_err)) {
-return;
-}
-
-info_report("dtb dumped to %s", filename);
-}
-
 void qemu_fdt_randomize_seeds(void *fdt)
 {
 int noffset, poffset, len;
diff --git a/Kconfig.host b/Kconfig.host
index f6a2a131e6c..a0d4a52131e 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -23,6 +23,10 @@ config IVSHMEM
 config TPM
 bool
 
+config FDT
+bool
+select DEVICE_TREE
+
 config VHOST_USER
 bool
 
diff --git a/hw/core/Kconfig b/hw/core/Kconfig
index 9397503656d..24411f59306 100644
--- a/hw/core/Kconfig
+++ b/hw/core/Kconfig
@@ -4,8 +4,14 @@ config EMPTY_SLOT
 config PTIMER
 bool
 
+config DEVICE_TREE
+bool
+# fail the build if libfdt not found
+depends on FDT
+
 config FITLOADER
 bool
+depends on DEVICE_TREE
 
 config GENERIC_LOADER
 bool
@@ -14,13 +20,14 @@ config GENERIC_LOADER
 config GUEST_LOADER
 bool
 default y
-depends on TCG
+

[PATCH 2/6] meson: move libfdt together with other dependencies

2024-05-08 Thread Paolo Bonzini
Move the libfdt detection code together with other dependencies instead
of keeping it with subprojects.  This has the disadvantage of performing
the detection even if no target requires libfdt; but it has the advantage
that Kconfig will be able to observe the availability of the library.

Signed-off-by: Paolo Bonzini 
---
 meson.build | 79 ++---
 1 file changed, 38 insertions(+), 41 deletions(-)

diff --git a/meson.build b/meson.build
index 7ca0ba4987f..2e7e2b15406 100644
--- a/meson.build
+++ b/meson.build
@@ -1858,6 +1858,34 @@ if numa.found() and not cc.links('''
   endif
 endif
 
+fdt = not_found
+fdt_opt = get_option('fdt')
+if fdt_opt == 'enabled' and get_option('wrap_mode') == 'nodownload'
+  fdt_opt = 'system'
+endif
+if fdt_opt in ['enabled', 'system'] or (fdt_opt == 'auto' and have_system)
+  fdt = cc.find_library('fdt', required: fdt_opt == 'system')
+  if fdt.found() and cc.links('''
+ #include 
+ #include 
+ int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
+   dependencies: fdt)
+fdt_opt = 'system'
+  elif fdt_opt != 'system'
+fdt_opt = get_option('wrap_mode') == 'nodownload' ? 'disabled' : 'internal'
+fdt = not_found
+  else
+error('system libfdt is too old (1.5.1 or newer required)')
+  endif
+endif
+if fdt_opt == 'internal'
+  assert(not fdt.found())
+  libfdt_proj = subproject('dtc', required: true,
+   default_options: ['tools=false',  'yaml=disabled',
+ 'python=disabled', 
'default_library=static'])
+  fdt = libfdt_proj.get_variable('libfdt_dep')
+endif
+
 rdma = not_found
 if not get_option('rdma').auto() or have_system
   libumad = cc.find_library('ibumad', required: get_option('rdma'))
@@ -2199,6 +2227,7 @@ config_host_data.set('CONFIG_BSD', host_os 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', host_os == 'darwin')
+config_host_data.set('CONFIG_FDT', fdt.found())
 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
@@ -3025,14 +3054,16 @@ foreach target : target_dirs
 error('No accelerator available for target @0@'.format(target))
   endif
 
-  actual_target_dirs += target
   config_target += keyval.load('configs/targets' / target + '.mak')
   config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
 
-  if 'TARGET_NEED_FDT' in config_target
+  if 'TARGET_NEED_FDT' in config_target and not fdt.found()
 fdt_required += target
+continue
   endif
 
+  actual_target_dirs += target
+
   # Add default keys
   if 'TARGET_BASE_ARCH' not in config_target
 config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
@@ -3120,6 +3151,10 @@ genh += custom_target('config-poison.h',
   command: [find_program('scripts/make-config-poison.sh'),
 target_configs_h])
 
+if fdt_required.length() > 0
+  error('fdt disabled but required by targets ' + ', '.join(fdt_required))
+endif
+
 ###
 # Subprojects #
 ###
@@ -3130,44 +3165,6 @@ if have_system and vfio_user_server_allowed
   libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
 endif
 
-fdt = not_found
-fdt_opt = get_option('fdt')
-if fdt_required.length() > 0 or fdt_opt == 'enabled'
-  if fdt_opt == 'disabled'
-error('fdt disabled but required by targets ' + ', '.join(fdt_required))
-  endif
-
-  if fdt_opt in ['enabled', 'auto', 'system']
-if get_option('wrap_mode') == 'nodownload'
-  fdt_opt = 'system'
-endif
-fdt = cc.find_library('fdt', required: fdt_opt == 'system')
-if fdt.found() and cc.links('''
-   #include 
-   #include 
-   int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
- dependencies: fdt)
-  fdt_opt = 'system'
-elif fdt_opt == 'system'
-   error('system libfdt requested, but it is too old (1.5.1 or newer 
required)')
-else
-  fdt_opt = 'internal'
-  fdt = not_found
-endif
-  endif
-  if not fdt.found()
-assert(fdt_opt == 'internal')
-libfdt_proj = subproject('dtc', required: true,
- default_options: ['tools=false',  'yaml=disabled',
-   'python=disabled', 
'default_library=static'])
-fdt = libfdt_proj.get_variable('libfdt_dep')
-  endif
-else
-  fdt_opt = 'disabled'
-endif
-
-config_host_data.set('CONFIG_FDT', fdt.found())
-
 vhost_user = not_found
 if host_os == 'linux' and have_vhost_user
   libvhost_user = subproject('libvhost-user')
@@ -4419,7 +4416,7 @@ summary_info += {'Linux AIO support': libaio}
 summary_info += {'Linux io_uring support': linux_io_uring}
 summary_info += {'ATTR/XATTR support': libattr}
 summar

[PATCH 4/6] kconfig: express dependency of individual boards on libfdt

2024-05-08 Thread Paolo Bonzini
Now that boards are enabled by default and the "CONFIG_FOO=y"
entries are gone from configs/devices/, there cannot be any more
a conflicts between the default contents of configs/devices/
and a failed "depends on" clause.

With this change, each individual board or target can express
whether it needs FDT.  It can then include the common code in the
build via "select DEVICE_TREE", which will also as tell meson to link
with libfdt.

This allows building non-microvm x86 emulators without having
libfdt available.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Paolo Bonzini 
---
 Kconfig.host  |  1 -
 hw/arm/Kconfig|  5 +
 hw/i386/Kconfig   |  3 ++-
 hw/loongarch/Kconfig  |  3 ++-
 hw/mips/Kconfig   |  3 ++-
 hw/openrisc/Kconfig   |  2 ++
 hw/ppc/Kconfig| 15 ---
 hw/riscv/Kconfig  |  4 
 hw/rx/Kconfig |  3 ++-
 hw/xtensa/Kconfig |  1 +
 target/arm/Kconfig|  2 ++
 target/microblaze/Kconfig |  1 +
 target/openrisc/Kconfig   |  1 +
 target/riscv/Kconfig  |  2 ++
 14 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/Kconfig.host b/Kconfig.host
index a0d4a52131e..17f405004b3 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -25,7 +25,6 @@ config TPM
 
 config FDT
 bool
-select DEVICE_TREE
 
 config VHOST_USER
 bool
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 98c264ed219..8b97683a45e 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -15,6 +15,7 @@ config ARM_VIRT
 select ACPI
 select ARM_SMMUV3
 select GPIO_KEY
+select DEVICE_TREE
 select FW_CFG_DMA
 select PCI_EXPRESS
 select PCI_EXPRESS_GENERIC_BRIDGE
@@ -265,6 +266,7 @@ config SBSA_REF
 default y
 depends on TCG && AARCH64
 imply PCI_DEVICES
+select DEVICE_TREE
 select AHCI
 select ARM_SMMUV3
 select GPIO_KEY
@@ -347,6 +349,7 @@ config VEXPRESS
 bool
 default y
 depends on TCG && ARM
+select DEVICE_TREE
 select A9MPCORE
 select A15MPCORE
 select ARM_MPTIMER
@@ -492,6 +495,7 @@ config XLNX_ZYNQMP_ARM
 select CPU_CLUSTER
 select DDC
 select DPCD
+select DEVICE_TREE
 select SDHCI
 select SSI
 select SSI_M25P80
@@ -509,6 +513,7 @@ config XLNX_VERSAL
 depends on TCG && AARCH64
 select ARM_GIC
 select CPU_CLUSTER
+select DEVICE_TREE
 select PL011
 select CADENCE
 select VIRTIO_MMIO
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index 4362164962c..5af47f4bf2f 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -115,7 +115,8 @@ config Q35
 config MICROVM
 bool
 default y
-depends on I386
+depends on I386 && FDT
+select DEVICE_TREE
 select SERIAL_ISA # for serial_hds_isa_init()
 select ISA_BUS
 select APIC
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 78640505630..830cfef72db 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -1,7 +1,8 @@
 config LOONGARCH_VIRT
 bool
 default y
-depends on LOONGARCH64
+depends on LOONGARCH64 && FDT
+select DEVICE_TREE
 select PCI
 select PCI_EXPRESS_GENERIC_BRIDGE
 imply VIRTIO_VGA
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 9bccb363eb9..a7f26edebe8 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -80,9 +80,10 @@ config MIPS_CPS
 config MIPS_BOSTON
 bool
 default y
-depends on MIPS64 && !TARGET_BIG_ENDIAN
+depends on MIPS64 && !TARGET_BIG_ENDIAN && FDT
 imply PCI_DEVICES
 imply TEST_DEVICES
+select DEVICE_TREE
 select FITLOADER
 select MIPS_CPS
 select PCI_EXPRESS_XILINX
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 9c9015e0a5d..76b953c62c2 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -2,6 +2,7 @@ config OR1K_SIM
 bool
 default y
 depends on OPENRISC
+select DEVICE_TREE
 select SERIAL
 select OPENCORES_ETH
 select OMPIC
@@ -14,6 +15,7 @@ config OR1K_VIRT
 imply PCI_DEVICES
 imply VIRTIO_VGA
 imply TEST_DEVICES
+select DEVICE_TREE
 select PCI
 select PCI_EXPRESS_GENERIC_BRIDGE
 select GOLDFISH_RTC
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index 78f83e78ce5..347212f4dba 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -1,7 +1,7 @@
 config PSERIES
 bool
 default y
-depends on PPC64
+depends on PPC64 && FDT
 imply USB_OHCI_PCI
 imply PCI_DEVICES
 imply TEST_DEVICES
@@ -26,7 +26,7 @@ config SPAPR_RNG
 config POWERNV
 bool
 default y
-depends on PPC64
+depends on PPC64 && FDT
 imply PCI_DEVICES
 imply TEST_DEVICES
 select ISA_IPMI_BT
@@ -52,7 +52,7 @@ config PPC405
 config PPC440
 bool
 default y
-depends on PPC
+depends on PPC && FDT
 imply PCI_DEVICES
 imply TEST_DEVICES
 imply E1000_PCI
@@ -71,7 +71,7

[PATCH 1/6] meson: pick libfdt from common_ss when building target-specific files

2024-05-08 Thread Paolo Bonzini
Avoid having to list dependencies such as libfdt twice, both on common_ss
and specific_ss.  Instead, just take all the dependencies in common_ss
and allow the target-specific libqemu-*.fa library to use them.

Signed-off-by: Paolo Bonzini 
---
 meson.build  | 14 +++---
 hw/arm/meson.build   |  2 +-
 hw/loongarch/meson.build |  2 +-
 hw/mips/meson.build  |  2 +-
 hw/openrisc/meson.build  |  4 ++--
 hw/ppc/meson.build   |  4 +---
 hw/riscv/meson.build |  2 +-
 7 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/meson.build b/meson.build
index 43da4923721..7ca0ba4987f 100644
--- a/meson.build
+++ b/meson.build
@@ -3868,15 +3868,23 @@ foreach target : target_dirs
 
   target_common = common_ss.apply(config_target, strict: false)
   objects = common_all.extract_objects(target_common.sources())
-  deps = target_common.dependencies()
+  arch_deps += target_common.dependencies()
 
   target_specific = specific_ss.apply(config_target, strict: false)
   arch_srcs += target_specific.sources()
   arch_deps += target_specific.dependencies()
 
+  # allow using headers from the dependencies but do not include the sources,
+  # because this emulator only needs those in "objects".  For external
+  # dependencies, the full dependency is included below in the executable.
+  lib_deps = []
+  foreach dep : arch_deps
+lib_deps += dep.partial_dependency(compile_args: true, includes: true)
+  endforeach
+
   lib = static_library('qemu-' + target,
  sources: arch_srcs + genh,
- dependencies: arch_deps,
+ dependencies: lib_deps,
  objects: objects,
  include_directories: target_inc,
  c_args: c_args,
@@ -3924,7 +3932,7 @@ foreach target : target_dirs
 emulator = executable(exe_name, exe['sources'],
install: true,
c_args: c_args,
-   dependencies: arch_deps + deps + exe['dependencies'],
+   dependencies: arch_deps + exe['dependencies'],
objects: lib.extract_all_objects(recursive: true),
link_depends: [block_syms, qemu_syms],
link_args: link_args,
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 6808135c1f7..aefde0c69a3 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -1,5 +1,5 @@
 arm_ss = ss.source_set()
-arm_ss.add(files('boot.c'), fdt)
+arm_ss.add(files('boot.c'))
 arm_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c'))
 arm_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
 arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c'))
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index d306d82c2ee..bce7ebac97e 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -3,7 +3,7 @@ loongarch_ss.add(files(
 'fw_cfg.c',
 'boot.c',
 ))
-loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('virt.c'), 
fdt])
+loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('virt.c'))
 loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
 
 hw_arch += {'loongarch': loongarch_ss}
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index f06d88f3430..ca37c42d900 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -9,7 +9,7 @@ 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'))
-mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: [files('boston.c'), fdt])
+mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: files('boston.c'))
 endif
 
 hw_arch += {'mips': mips_ss}
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index 2dbc6365bb7..82f1f0ef1cc 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,7 +1,7 @@
 openrisc_ss = ss.source_set()
 openrisc_ss.add(files('cputimer.c'))
 openrisc_ss.add(files('boot.c'))
-openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), 
fdt])
-openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: files('openrisc_sim.c'))
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: files('virt.c'))
 
 hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index d096636ee7f..3ebbf329bcc 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -3,9 +3,7 @@ ppc_ss.add(files(
   'ppc.c',
   'ppc_booke.c',
 ))
-ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: [files(
-  'fdt.c',
-), fdt])
+ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: files('fdt.c'))
 ppc_ss.add(when: 'CONFIG_FW_CFG_PPC', if_true: files('fw_cfg.c'))
 
 # IBM pSeries (sPAPR)
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 2f7ee81be3c..f872674093a 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -1,5 +1,5 @@
 riscv_ss = ss.

[PATCH v2 0/6] kconfig: express dependency of individual boards on libfdt

2024-05-08 Thread Paolo Bonzini
This is a follow up to the "default y" patch series at
https://lore.kernel.org/qemu-devel/20240423131612.28362-1-pbonz...@redhat.com/
and shows an example of what that series enables.

With this change, individual boards will be enabled/disabled depending
on whether libfdt is present or not.  In particular, x86 will simply
disable microvm and build the "traditional" chipsets if libfdt is not
found.

All boards or targets that need libfdt now have an explicit "depends on
FDT" (sometimes the boards delegate that to the target).  TARGET_NEED_FDT
is only used for targets that absolutely cannot build without libfdt,
or for which all boards require it.

For simplicity, patch 1 simplifies the libfdt handling in meson.build,
removing the ability to force use of the subproject.  There is no
use case that I can imagine, if you want to use the subproject just
delete libfdt from your OS installation.

Paolo

v1->v2:
- use libfdt CPPFLAGS when building target-specific files
- limited scope of libfdt detection changes: keep it enabled when building
  --without-default-features (see commit message for 0577e84d374,
  "configure: Disable capstone and slirp in the --without-default-features
  mode", 2022-02-21)
- patch 6 does not 
- split patch 3 in two parts
- fix compilation errors due to missing qmp_dumpdtb/hmp_dumpdtb
- make MIPS_BOSTON depend on FDT

Paolo Bonzini (6):
  meson: pick libfdt from common_ss when building target-specific files
  meson: move libfdt together with other dependencies
  kconfig: allow compiling out QEMU device tree code per target
  kconfig: express dependency of individual boards on libfdt
  hw/xtensa: require libfdt
  configs: disable emulators that require it if libfdt is not found

 configs/targets/aarch64-softmmu.mak  |   1 +
 configs/targets/arm-softmmu.mak  |   1 +
 configs/targets/i386-softmmu.mak |   1 -
 configs/targets/loongarch64-softmmu.mak  |   1 +
 configs/targets/microblaze-softmmu.mak   |   1 +
 configs/targets/microblazeel-softmmu.mak |   1 +
 configs/targets/mips64el-softmmu.mak |   1 -
 configs/targets/or1k-softmmu.mak |   1 +
 configs/targets/ppc-softmmu.mak  |   1 -
 configs/targets/ppc64-softmmu.mak|   1 +
 configs/targets/riscv32-softmmu.mak  |   1 +
 configs/targets/riscv64-softmmu.mak  |   1 +
 configs/targets/rx-softmmu.mak   |   1 +
 configs/targets/x86_64-softmmu.mak   |   1 -
 meson.build  | 100 +--
 include/monitor/hmp.h|   1 +
 include/sysemu/device_tree.h |   1 -
 hw/xtensa/xtfpga.c   |   9 --
 monitor/hmp-cmds.c   |  17 
 system/device_tree-stub.c|  10 +++
 system/device_tree.c |  14 
 .gitlab-ci.d/buildtest.yml   |   8 +-
 Kconfig.host |   3 +
 hw/arm/Kconfig   |   5 ++
 hw/arm/meson.build   |   2 +-
 hw/core/Kconfig  |   9 +-
 hw/core/meson.build  |   2 +-
 hw/i386/Kconfig  |   3 +-
 hw/loongarch/Kconfig |   3 +-
 hw/loongarch/meson.build |   2 +-
 hw/mips/Kconfig  |   3 +-
 hw/mips/meson.build  |   2 +-
 hw/openrisc/Kconfig  |   2 +
 hw/openrisc/meson.build  |   4 +-
 hw/ppc/Kconfig   |  15 ++--
 hw/ppc/meson.build   |   4 +-
 hw/riscv/Kconfig |   4 +
 hw/riscv/meson.build |   2 +-
 hw/rx/Kconfig|   3 +-
 hw/xtensa/Kconfig|   3 +-
 system/meson.build   |   4 +-
 target/arm/Kconfig   |   2 +
 target/microblaze/Kconfig|   1 +
 target/openrisc/Kconfig  |   1 +
 target/riscv/Kconfig |   2 +
 45 files changed, 154 insertions(+), 101 deletions(-)
 create mode 100644 system/device_tree-stub.c

-- 
2.45.0




[PATCH] loongarch64: move memory map to boot.c

2024-05-07 Thread Paolo Bonzini
Ensure that it can be used even if virt.c is not included in the build, as
is the case for --without-default-devices.

Signed-off-by: Paolo Bonzini 
---
 include/hw/loongarch/boot.h | 10 ++
 include/hw/loongarch/virt.h | 10 --
 hw/loongarch/boot.c |  3 +++
 hw/loongarch/virt.c |  3 ---
 .gitlab-ci.d/buildtest.yml  |  2 +-
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
index 4ebcc89dcf2..b3b870df1f0 100644
--- a/include/hw/loongarch/boot.h
+++ b/include/hw/loongarch/boot.h
@@ -104,6 +104,16 @@ struct loongarch_boot_info {
 uint64_t a0, a1, a2;
 };
 
+extern struct memmap_entry *memmap_table;
+extern unsigned memmap_entries;
+
+struct memmap_entry {
+uint64_t address;
+uint64_t length;
+uint32_t type;
+uint32_t reserved;
+};
+
 void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info);
 
 #endif /* HW_LOONGARCH_BOOT_H */
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 4e14bf6060d..fdbd2b146f1 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -37,16 +37,6 @@
 
 #define FDT_BASE0x10
 
-extern struct memmap_entry *memmap_table;
-extern unsigned memmap_entries;
-
-struct memmap_entry {
-uint64_t address;
-uint64_t length;
-uint32_t type;
-uint32_t reserved;
-};
-
 struct LoongArchMachineState {
 /*< private >*/
 MachineState parent_obj;
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
index 7d1630b2e74..03f6301a773 100644
--- a/hw/loongarch/boot.c
+++ b/hw/loongarch/boot.c
@@ -15,6 +15,9 @@
 #include "sysemu/reset.h"
 #include "sysemu/qtest.h"
 
+struct memmap_entry *memmap_table;
+unsigned memmap_entries;
+
 ram_addr_t initrd_offset;
 uint64_t initrd_size;
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c0999878df6..504e1fb349d 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -516,9 +516,6 @@ static void virt_powerdown_req(Notifier *notifier, void 
*opaque)
 acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS);
 }
 
-struct memmap_entry *memmap_table;
-unsigned memmap_entries;
-
 static void memmap_add_entry(uint64_t address, uint64_t length, uint32_t type)
 {
 /* Ensure there are no duplicate entries. */
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index e9402a68a79..bab61945643 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
 # Check our reduced build configurations
 # requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
 #   mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, loongarch64, s390x, sh4, sh4eb, x86_64
+# does not build without boards: i386, s390x, sh4, sh4eb, x86_64
 build-without-defaults:
   extends: .native_build_job_template
   needs:
-- 
2.45.0




[PATCH] sh4: select correct components for no-board build

2024-05-07 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 .gitlab-ci.d/buildtest.yml | 5 +++--
 hw/sh4/meson.build | 2 +-
 target/sh4/Kconfig | 2 ++
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index bab61945643..13afd0df1f0 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
 # Check our reduced build configurations
 # requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
 #   mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, s390x, sh4, sh4eb, x86_64
+# does not build without boards: i386, s390x, x86_64
 build-without-defaults:
   extends: .native_build_job_template
   needs:
@@ -665,7 +665,8 @@ build-without-defaults:
   --disable-qom-cast-debug
   --disable-strip
 TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
-  mips-softmmu mips64-softmmu mipsel-softmmu sparc-softmmu
+  mips-softmmu mips64-softmmu mipsel-softmmu
+  sh4-softmmu sh4eb-softmmu sparc-softmmu
   sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
   hexagon-linux-user i386-linux-user s390x-linux-user
 MAKE_CHECK_ARGS: check
diff --git a/hw/sh4/meson.build b/hw/sh4/meson.build
index 424d5674dea..70e814c3a28 100644
--- a/hw/sh4/meson.build
+++ b/hw/sh4/meson.build
@@ -1,5 +1,5 @@
 sh4_ss = ss.source_set()
-sh4_ss.add(files(
+sh4_ss.add(when: 'CONFIG_SH7750', if_true: files(
   'sh7750.c',
   'sh7750_regnames.c',
 ))
diff --git a/target/sh4/Kconfig b/target/sh4/Kconfig
index 2397c860280..93b92f1e480 100644
--- a/target/sh4/Kconfig
+++ b/target/sh4/Kconfig
@@ -1,2 +1,4 @@
 config SH4
 bool
+# needed for sh_intc_get_pending_vector
+select SH_INTC
-- 
2.45.0




Re: [PATCH] configure: quote -D options that are passed to meson

2024-05-07 Thread Paolo Bonzini
On Tue, May 7, 2024 at 1:58 PM Peter Maydell  wrote:
>
> On Tue, 7 May 2024 at 11:50, Paolo Bonzini  wrote:
> >
> > Ensure that they go through unmodified, instead of removing one layer
> > of quoting.
>
> Do you have an example of what goes wrong that we could
> mention in the commit message ?

I only found it by inspection. The only case I can think of is
"-Dpkg_config_path=/home/pbonzini/a path with spaces/".

I can add the following text:

---
-D is a pretty specialized option and most options that can have spaces
do not need it (for example, c_args is covered by --extra-cflags).
Therefore it's unlikely that this causes actual trouble.  However,
a somewhat realistic failure case would be with -Dpkg_config_path
and a pkg-config directory that contains spaces.
---

Paolo




[PULL 07/26] target/i386: pull cc_op update to callers of gen_jmp_rel{, _csize}

2024-05-07 Thread Paolo Bonzini
gen_update_cc_op must be called before control flow splits.  Doing it
in gen_jmp_rel{,_csize} may hide bugs, instead assert that cc_op is
clean---even if that means a few more calls to gen_update_cc_op().

With this new invariant, setting cc_op to CC_OP_DYNAMIC is unnecessary
since the caller should have done it.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 466fee38c0e..024da6d88eb 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2853,6 +2853,8 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 target_ulong new_pc = s->pc + diff;
 target_ulong new_eip = new_pc - s->cs_base;
 
+assert(!s->cc_op_dirty);
+
 /* In 64-bit mode, operand size is fixed at 64 bits. */
 if (!CODE64(s)) {
 if (ot == MO_16) {
@@ -2866,9 +2868,6 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 }
 new_eip &= mask;
 
-gen_update_cc_op(s);
-set_cc_op(s, CC_OP_DYNAMIC);
-
 if (tb_cflags(s->base.tb) & CF_PCREL) {
 tcg_gen_addi_tl(cpu_eip, cpu_eip, new_pc - s->pc_save);
 /*
@@ -5146,6 +5145,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 : (int16_t)insn_get(env, s, MO_16));
 gen_push_v(s, eip_next_tl(s));
 gen_bnd_jmp(s);
+gen_update_cc_op(s);
 gen_jmp_rel(s, dflag, diff, 0);
 }
 break;
@@ -5169,6 +5169,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 ? (int32_t)insn_get(env, s, MO_32)
 : (int16_t)insn_get(env, s, MO_16));
 gen_bnd_jmp(s);
+gen_update_cc_op(s);
 gen_jmp_rel(s, dflag, diff, 0);
 }
 break;
@@ -5189,6 +5190,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 case 0xeb: /* jmp Jb */
 {
 int diff = (int8_t)insn_get(env, s, MO_8);
+gen_update_cc_op(s);
 gen_jmp_rel(s, dflag, diff, 0);
 }
 break;
-- 
2.45.0




[PULL 02/26] target/i386: use TSTEQ/TSTNE to test low bits

2024-05-07 Thread Paolo Bonzini
When testing the sign bit or equality to zero of a partial register, it
is useful to use a single TSTEQ or TSTNE operation.  It can also be used
to test the parity flag, using bit 0 of the population count.

Do not do this for target_ulong-sized values however; the optimizer would
produce a comparison against zero anyway, and it avoids shifts by 64
which are undefined behavior.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 28 
 target/i386/tcg/emit.c.inc  |  5 ++---
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 051ffb5e1fd..4735f084d40 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -928,11 +928,21 @@ typedef struct CCPrepare {
 bool no_setcond;
 } CCPrepare;
 
+static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size)
+{
+if (size == MO_TL) {
+return (CCPrepare) { .cond = TCG_COND_LT, .reg = src, .mask = -1 };
+} else {
+return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src, .mask = -1,
+ .imm = 1ull << ((8 << size) - 1) };
+}
+}
+
 /* compute eflags.C to reg */
 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
 {
 TCGv t0, t1;
-int size, shift;
+MemOp size;
 
 switch (s->cc_op) {
 case CC_OP_SUBB ... CC_OP_SUBQ:
@@ -967,9 +977,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv 
reg)
 case CC_OP_SHLB ... CC_OP_SHLQ:
 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
 size = s->cc_op - CC_OP_SHLB;
-shift = (8 << size) - 1;
-return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = (target_ulong)1 << shift };
+return gen_prepare_sign_nz(cpu_cc_src, size);
 
 case CC_OP_MULB ... CC_OP_MULQ:
 return (CCPrepare) { .cond = TCG_COND_NE,
@@ -1029,8 +1037,7 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, 
TCGv reg)
 default:
 {
 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
-TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
-return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
+return gen_prepare_sign_nz(cpu_cc_dst, size);
 }
 }
 }
@@ -1077,8 +1084,13 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, 
TCGv reg)
 default:
 {
 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
-TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
-return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
+if (size == MO_TL) {
+return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_dst,
+ .mask = -1 };
+} else {
+return (CCPrepare) { .cond = TCG_COND_TSTEQ, .reg = cpu_cc_dst,
+ .mask = -1, .imm = (1ull << (8 << size)) 
- 1 };
+}
 }
 }
 }
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 6bcf88ecd71..0e00f6635dd 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1209,7 +1209,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State 
*env, X86DecodedInsn *dec
 [JCC_Z] = TCG_COND_EQ,
 [JCC_BE] = TCG_COND_LEU,
 [JCC_S] = TCG_COND_LT,  /* test sign bit by comparing against 0 */
-[JCC_P] = TCG_COND_EQ,  /* even parity - tests low bit of popcount */
+[JCC_P] = TCG_COND_TSTEQ,  /* even parity - tests low bit of popcount 
*/
 [JCC_L] = TCG_COND_LT,
 [JCC_LE] = TCG_COND_LE,
 };
@@ -1260,8 +1260,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State 
*env, X86DecodedInsn *dec
 case JCC_P:
 tcg_gen_ext8u_tl(s->tmp0, s->T0);
 tcg_gen_ctpop_tl(s->tmp0, s->tmp0);
-tcg_gen_andi_tl(s->tmp0, s->tmp0, 1);
-cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(0);
+cmp_lhs = s->tmp0, cmp_rhs = tcg_constant_tl(1);
 break;
 
 case JCC_S:
-- 
2.45.0




[PULL 23/26] target/i386: remove now-converted opcodes from old decoder

2024-05-07 Thread Paolo Bonzini
Send all converted opcodes to disas_insn_new() directly from the big
decoding switch statement; once more, the debugging/bisecting logic
disappears.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/helper.h|   11 -
 target/i386/tcg/shift_helper_template.h.inc |  108 -
 target/i386/tcg/int_helper.c|   34 -
 target/i386/tcg/translate.c | 2175 +--
 target/i386/tcg/decode-new.c.inc|3 -
 5 files changed, 11 insertions(+), 2320 deletions(-)
 delete mode 100644 target/i386/tcg/shift_helper_template.h.inc

diff --git a/target/i386/helper.h b/target/i386/helper.h
index ac2b04abd63..3c207ac62d6 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -207,15 +207,4 @@ DEF_HELPER_1(emms, void, env)
 #define SHIFT 2
 #include "tcg/ops_sse_header.h.inc"
 
-DEF_HELPER_3(rclb, tl, env, tl, tl)
-DEF_HELPER_3(rclw, tl, env, tl, tl)
-DEF_HELPER_3(rcll, tl, env, tl, tl)
-DEF_HELPER_3(rcrb, tl, env, tl, tl)
-DEF_HELPER_3(rcrw, tl, env, tl, tl)
-DEF_HELPER_3(rcrl, tl, env, tl, tl)
-#ifdef TARGET_X86_64
-DEF_HELPER_3(rclq, tl, env, tl, tl)
-DEF_HELPER_3(rcrq, tl, env, tl, tl)
-#endif
-
 DEF_HELPER_1(rdrand, tl, env)
diff --git a/target/i386/tcg/shift_helper_template.h.inc 
b/target/i386/tcg/shift_helper_template.h.inc
deleted file mode 100644
index 54f15d6e05c..000
--- a/target/i386/tcg/shift_helper_template.h.inc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  x86 shift helpers
- *
- *  Copyright (c) 2008 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DATA_BITS (1 << (3 + SHIFT))
-#define SHIFT_MASK (DATA_BITS - 1)
-#if DATA_BITS <= 32
-#define SHIFT1_MASK 0x1f
-#else
-#define SHIFT1_MASK 0x3f
-#endif
-
-#if DATA_BITS == 8
-#define SUFFIX b
-#define DATA_MASK 0xff
-#elif DATA_BITS == 16
-#define SUFFIX w
-#define DATA_MASK 0x
-#elif DATA_BITS == 32
-#define SUFFIX l
-#define DATA_MASK 0x
-#elif DATA_BITS == 64
-#define SUFFIX q
-#define DATA_MASK 0xULL
-#else
-#error unhandled operand size
-#endif
-
-target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0,
-  target_ulong t1)
-{
-int count, eflags;
-target_ulong src;
-target_long res;
-
-count = t1 & SHIFT1_MASK;
-#if DATA_BITS == 16
-count = rclw_table[count];
-#elif DATA_BITS == 8
-count = rclb_table[count];
-#endif
-if (count) {
-eflags = env->cc_src;
-t0 &= DATA_MASK;
-src = t0;
-res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1));
-if (count > 1) {
-res |= t0 >> (DATA_BITS + 1 - count);
-}
-t0 = res;
-env->cc_src = (eflags & ~(CC_C | CC_O)) |
-(lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
-((src >> (DATA_BITS - count)) & CC_C);
-}
-return t0;
-}
-
-target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, target_ulong t0,
-  target_ulong t1)
-{
-int count, eflags;
-target_ulong src;
-target_long res;
-
-count = t1 & SHIFT1_MASK;
-#if DATA_BITS == 16
-count = rclw_table[count];
-#elif DATA_BITS == 8
-count = rclb_table[count];
-#endif
-if (count) {
-eflags = env->cc_src;
-t0 &= DATA_MASK;
-src = t0;
-res = (t0 >> count) |
-((target_ulong)(eflags & CC_C) << (DATA_BITS - count));
-if (count > 1) {
-res |= t0 << (DATA_BITS + 1 - count);
-}
-t0 = res;
-env->cc_src = (eflags & ~(CC_C | CC_O)) |
-(lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
-((src >> (count - 1)) & CC_C);
-}
-return t0;
-}
-
-#undef DATA_BITS
-#undef SHIFT_MASK
-#undef SHIFT1_MASK
-#undef DATA_TYPE
-#undef DATA_MASK
-#undef SUFFIX
diff --git a/target/i386/tcg/int_helper.c b/target/i386/tcg/int_helper.c
index ab85dc55400..df16130f5df 100644
--- a/target/i386/tcg/int_helper.c
+++ b/target/i386/tcg/int_helper.c
@@ -29,22 +29,6 @@
 
 //#define DEBUG_MULDIV
 
-/* modulo 9 table */
-static const uint8_t rclb_table[32] = {
-0, 1, 2, 3, 4, 5, 6, 7,
-8, 0, 1, 2, 3, 4, 5, 6,
-   

[PULL 25/26] target/i386: split legacy decoder into a separate function

2024-05-07 Thread Paolo Bonzini
Split the bits that have some duplication with disas_insn_new, from
those that should be the main topic of the conversion.  This is the
first step towards removing duplicate decoding of prefixes between
disas_insn and disas_insn_new.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 58 +++--
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 973bf07ef27..eb0e37e1480 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3117,15 +3117,15 @@ static bool disas_insn_x87(DisasContext *s, CPUState 
*cpu, int b)
 return true;
 }
 
+static void disas_insn_old(DisasContext *s, CPUState *cpu, int b);
+
 /* convert one instruction. s->base.is_jmp is set if the translation must
be stopped. Return the next pc value */
 static bool disas_insn(DisasContext *s, CPUState *cpu)
 {
 CPUX86State *env = cpu_env(cpu);
 int b, prefixes;
-int shift;
-MemOp ot, aflag, dflag;
-int modrm, reg, rm, mod, op, opreg, val;
+MemOp aflag, dflag;
 bool orig_cc_op_dirty = s->cc_op_dirty;
 CCOp orig_cc_op = s->cc_op;
 target_ulong orig_pc_save = s->pc_save;
@@ -3271,6 +3271,38 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 s->aflag = aflag;
 s->dflag = dflag;
 
+switch (b) {
+case 0 ... 0xd7:
+case 0xe0  ... 0xff:
+case 0x10e ... 0x117:
+case 0x128 ... 0x12f:
+case 0x138 ... 0x19f:
+case 0x1a0 ... 0x1a1:
+case 0x1a8 ... 0x1a9:
+case 0x1af:
+case 0x1b2:
+case 0x1b4 ... 0x1b7:
+case 0x1be ... 0x1bf:
+case 0x1c2 ... 0x1c6:
+case 0x1c8 ... 0x1ff:
+disas_insn_new(s, cpu, b);
+break;
+default:
+disas_insn_old(s, cpu, b);
+break;
+}
+return true;
+}
+
+static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
+{
+CPUX86State *env = cpu_env(cpu);
+int prefixes = s->prefix;
+MemOp dflag = s->dflag;
+int shift;
+MemOp ot;
+int modrm, reg, rm, mod, op, opreg, val;
+
 /* now check op code */
 switch (b) {
 /**/
@@ -4726,31 +4758,15 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 
 set_cc_op(s, CC_OP_POPCNT);
 break;
-case 0 ... 0xd7:
-case 0xe0  ... 0xff:
-case 0x10e ... 0x117:
-case 0x128 ... 0x12f:
-case 0x138 ... 0x19f:
-case 0x1a0 ... 0x1a1:
-case 0x1a8 ... 0x1a9:
-case 0x1af:
-case 0x1b2:
-case 0x1b4 ... 0x1b7:
-case 0x1be ... 0x1bf:
-case 0x1c2 ... 0x1c6:
-case 0x1c8 ... 0x1ff:
-disas_insn_new(s, cpu, b);
-break;
 default:
 goto unknown_op;
 }
-return true;
+return;
  illegal_op:
 gen_illegal_opcode(s);
-return true;
+return;
  unknown_op:
 gen_unknown_opcode(env, s);
-return true;
 }
 
 void tcg_x86_init(void)
-- 
2.45.0




[PULL 13/26] target/i386: move 00-5F opcodes to new decoder

2024-05-07 Thread Paolo Bonzini
Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c  |   2 +-
 target/i386/tcg/decode-new.c.inc | 120 ++
 target/i386/tcg/emit.c.inc   | 202 +++
 3 files changed, 323 insertions(+), 1 deletion(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 6a0c74c225f..8bc1828a6bc 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3146,7 +3146,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && 0) {
+if (use_new && b <= 0x5f) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 3fc6485d74c..1e792426ff5 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -121,6 +121,8 @@
 
 #define X86_OP_GROUP2(op, op0, s0, op1, s1, ...)  \
 X86_OP_GROUP3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
+#define X86_OP_GROUPw(op, op0, s0, ...)   \
+X86_OP_GROUP3(op, op0, s0, None, None, None, None, ## __VA_ARGS__)
 #define X86_OP_GROUP0(op, ...)\
 X86_OP_GROUP3(op, None, None, None, None, None, None, ## __VA_ARGS__)
 
@@ -140,12 +142,23 @@
 .op3 = X86_TYPE_I, .s3 = X86_SIZE_b,  \
 ## __VA_ARGS__)
 
+/*
+ * Short forms that are mostly useful for ALU opcodes and other
+ * one-byte opcodes.  For vector instructions it is usually
+ * clearer to write all three operands explicitly, because the
+ * corresponding gen_* function will use OP_PTRn rather than s->T0
+ * and s->T1.
+ */
+#define X86_OP_ENTRYrr(op, op0, s0, op1, s1, ...) \
+X86_OP_ENTRY3(op, None, None, op0, s0, op1, s1, ## __VA_ARGS__)
 #define X86_OP_ENTRY2(op, op0, s0, op1, s1, ...)  \
 X86_OP_ENTRY3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
 #define X86_OP_ENTRYw(op, op0, s0, ...)   \
 X86_OP_ENTRY3(op, op0, s0, None, None, None, None, ## __VA_ARGS__)
 #define X86_OP_ENTRYr(op, op0, s0, ...)   \
 X86_OP_ENTRY3(op, None, None, None, None, op0, s0, ## __VA_ARGS__)
+#define X86_OP_ENTRY1(op, op0, s0, ...)   \
+X86_OP_ENTRY3(op, op0, s0, 2op, s0, None, None, ## __VA_ARGS__)
 #define X86_OP_ENTRY0(op, ...)\
 X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__)
 
@@ -1096,7 +1109,114 @@ static void decode_0F(DisasContext *s, CPUX86State 
*env, X86OpEntry *entry, uint
 }
 
 static const X86OpEntry opcodes_root[256] = {
+[0x00] = X86_OP_ENTRY2(ADD, E,b, G,b, lock),
+[0x01] = X86_OP_ENTRY2(ADD, E,v, G,v, lock),
+[0x02] = X86_OP_ENTRY2(ADD, G,b, E,b, lock),
+[0x03] = X86_OP_ENTRY2(ADD, G,v, E,v, lock),
+[0x04] = X86_OP_ENTRY2(ADD, 0,b, I,b, lock),   /* AL, Ib */
+[0x05] = X86_OP_ENTRY2(ADD, 0,v, I,z, lock),   /* rAX, Iz */
+[0x06] = X86_OP_ENTRYr(PUSH, ES, w, chk(i64)),
+[0x07] = X86_OP_ENTRYw(POP, ES, w, chk(i64)),
+
+[0x10] = X86_OP_ENTRY2(ADC, E,b, G,b, lock),
+[0x11] = X86_OP_ENTRY2(ADC, E,v, G,v, lock),
+[0x12] = X86_OP_ENTRY2(ADC, G,b, E,b, lock),
+[0x13] = X86_OP_ENTRY2(ADC, G,v, E,v, lock),
+[0x14] = X86_OP_ENTRY2(ADC, 0,b, I,b, lock),   /* AL, Ib */
+[0x15] = X86_OP_ENTRY2(ADC, 0,v, I,z, lock),   /* rAX, Iz */
+[0x16] = X86_OP_ENTRYr(PUSH, SS, w, chk(i64)),
+[0x17] = X86_OP_ENTRYw(POP, SS, w, chk(i64)),
+
+[0x20] = X86_OP_ENTRY2(AND, E,b, G,b, lock),
+[0x21] = X86_OP_ENTRY2(AND, E,v, G,v, lock),
+[0x22] = X86_OP_ENTRY2(AND, G,b, E,b, lock),
+[0x23] = X86_OP_ENTRY2(AND, G,v, E,v, lock),
+[0x24] = X86_OP_ENTRY2(AND, 0,b, I,b, lock),   /* AL, Ib */
+[0x25] = X86_OP_ENTRY2(AND, 0,v, I,z, lock),   /* rAX, Iz */
+[0x26] = {},
+[0x27] = X86_OP_ENTRY0(DAA, chk(i64)),
+
+[0x30] = X86_OP_ENTRY2(XOR, E,b, G,b, lock),
+[0x31] = X86_OP_ENTRY2(XOR, E,v, G,v, lock),
+[0x32] = X86_OP_ENTRY2(XOR, G,b, E,b, lock),
+[0x33] = X86_OP_ENTRY2(XOR, G,v, E,v, lock),
+[0x34] = X86_OP_ENTRY2(XOR, 0,b, I,b, lock),   /* AL, Ib */
+[0x35] = X86_OP_ENTRY2(XOR, 0,v, I,z, lock),   /* rAX, Iz */
+[0x36] = {},
+[0x37] = X86_OP_ENTRY0(AAA, chk(i64)),
+
+[0x40] = X86_OP_ENTRY1(INC, 0,v, chk(i64)),
+[0x41] = X86_OP_ENTRY1(INC, 1,v, chk(i64)),
+[0x42] = X86_OP_ENTRY1(INC, 2,v, chk(i64)),
+[0x43] = X86_OP_ENTRY1(INC, 3,v, chk(i64)),
+[0x44] = X86_OP_ENTRY1(INC, 4,v, chk(i64)),
+[0x45] = X86_OP_ENTRY1(INC, 5,v, chk(i64)),
+[0x46] = X86_OP_ENTRY1(INC, 6,v, chk(i64)),
+[0x47] = X86_OP_ENTRY1(INC, 7,v, chk(i64)),
+
+[0x50] = X86_OP_ENTRYr(PUSH, LoBits,d64),
+[0x51] = X86_OP_ENTRYr(PUSH, LoBits,d64),
+[0x52] 

[PULL 14/26] target/i386: extract gen_far_call/jmp, reordering temporaries

2024-05-07 Thread Paolo Bonzini
Extract the code into new functions, and swap T0/T1 so that T0 corresponds
to the first immediate in the instruction stream.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 93 +
 1 file changed, 53 insertions(+), 40 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 8bc1828a6bc..e5672df9b94 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2512,12 +2512,13 @@ static inline void gen_op_movl_T0_seg(DisasContext *s, 
X86Seg seg_reg)
  offsetof(CPUX86State,segs[seg_reg].selector));
 }
 
-static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
+static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
 {
-tcg_gen_ext16u_tl(s->T0, s->T0);
-tcg_gen_st32_tl(s->T0, tcg_env,
+TCGv selector = tcg_temp_new();
+tcg_gen_ext16u_tl(selector, seg);
+tcg_gen_st32_tl(selector, tcg_env,
 offsetof(CPUX86State,segs[seg_reg].selector));
-tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
+tcg_gen_shli_tl(cpu_seg_base[seg_reg], selector, 4);
 }
 
 /* move T0 to seg_reg and compute if the CPU state may change. Never
@@ -2537,13 +2538,45 @@ static void gen_movl_seg_T0(DisasContext *s, X86Seg 
seg_reg)
 s->base.is_jmp = DISAS_EOB_NEXT;
 }
 } else {
-gen_op_movl_seg_T0_vm(s, seg_reg);
+gen_op_movl_seg_real(s, seg_reg, s->T0);
 if (seg_reg == R_SS) {
 s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
 }
 }
 }
 
+static void gen_far_call(DisasContext *s)
+{
+TCGv_i32 new_cs = tcg_temp_new_i32();
+tcg_gen_trunc_tl_i32(new_cs, s->T1);
+if (PE(s) && !VM86(s)) {
+gen_helper_lcall_protected(tcg_env, new_cs, s->T0,
+   tcg_constant_i32(s->dflag - 1),
+   eip_next_tl(s));
+} else {
+TCGv_i32 new_eip = tcg_temp_new_i32();
+tcg_gen_trunc_tl_i32(new_eip, s->T0);
+gen_helper_lcall_real(tcg_env, new_cs, new_eip,
+  tcg_constant_i32(s->dflag - 1),
+  eip_next_i32(s));
+}
+s->base.is_jmp = DISAS_JUMP;
+}
+
+static void gen_far_jmp(DisasContext *s)
+{
+if (PE(s) && !VM86(s)) {
+TCGv_i32 new_cs = tcg_temp_new_i32();
+tcg_gen_trunc_tl_i32(new_cs, s->T1);
+gen_helper_ljmp_protected(tcg_env, new_cs, s->T0,
+  eip_next_tl(s));
+} else {
+gen_op_movl_seg_real(s, R_CS, s->T1);
+gen_op_jmp_v(s, s->T0);
+}
+s->base.is_jmp = DISAS_JUMP;
+}
+
 static void gen_svm_check_intercept(DisasContext *s, uint32_t type)
 {
 /* no SVM activated; fast case */
@@ -3654,23 +3687,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 if (mod == 3) {
 goto illegal_op;
 }
-gen_op_ld_v(s, ot, s->T1, s->A0);
+gen_op_ld_v(s, ot, s->T0, s->A0);
 gen_add_A0_im(s, 1 << ot);
-gen_op_ld_v(s, MO_16, s->T0, s->A0);
-do_lcall:
-if (PE(s) && !VM86(s)) {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-gen_helper_lcall_protected(tcg_env, s->tmp2_i32, s->T1,
-   tcg_constant_i32(dflag - 1),
-   eip_next_tl(s));
-} else {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
-gen_helper_lcall_real(tcg_env, s->tmp2_i32, s->tmp3_i32,
-  tcg_constant_i32(dflag - 1),
-  eip_next_i32(s));
-}
-s->base.is_jmp = DISAS_JUMP;
+gen_op_ld_v(s, MO_16, s->T1, s->A0);
+gen_far_call(s);
 break;
 case 4: /* jmp Ev */
 if (dflag == MO_16) {
@@ -3684,19 +3704,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 if (mod == 3) {
 goto illegal_op;
 }
-gen_op_ld_v(s, ot, s->T1, s->A0);
+gen_op_ld_v(s, ot, s->T0, s->A0);
 gen_add_A0_im(s, 1 << ot);
-gen_op_ld_v(s, MO_16, s->T0, s->A0);
-do_ljmp:
-if (PE(s) && !VM86(s)) {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-gen_helper_ljmp_protected(tcg_env, s->tmp2_i32, s->T1,
-  eip_next_tl(s));
-} else {
-gen_op_movl_seg_T0_vm(s, R_CS);
-gen_op_jmp_v(s, s->T1);
-}
-s->base.is_jmp = DISAS_JUMP;
+ 

[PULL 03/26] target/i386: use TSTEQ/TSTNE to check flags

2024-05-07 Thread Paolo Bonzini
The new conditions obviously come in handy when testing individual bits
of EFLAGS, and they make it possible to remove the .mask field of
CCPrepare.

Lowering to shift+and is done by the optimizer if necessary.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4735f084d40..62ba21c1d74 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -996,8 +996,8 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv 
reg)
 case CC_OP_EFLAGS:
 case CC_OP_SARB ... CC_OP_SARQ:
 /* CC_SRC & 1 */
-return (CCPrepare) { .cond = TCG_COND_NE,
- .reg = cpu_cc_src, .mask = CC_C };
+return (CCPrepare) { .cond = TCG_COND_TSTNE,
+ .reg = cpu_cc_src, .mask = -1, .imm = CC_C };
 
 default:
/* The need to compute only C from CC_OP_DYNAMIC is important
@@ -1014,8 +1014,8 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, 
TCGv reg)
 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
 {
 gen_compute_eflags(s);
-return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = CC_P };
+return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
+ .mask = -1, .imm = CC_P };
 }
 
 /* compute eflags.S to reg */
@@ -1029,8 +1029,8 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, 
TCGv reg)
 case CC_OP_ADCX:
 case CC_OP_ADOX:
 case CC_OP_ADCOX:
-return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = CC_S };
+return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
+ .mask = -1, .imm = CC_S };
 case CC_OP_CLR:
 case CC_OP_POPCNT:
 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
@@ -1058,8 +1058,8 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, 
TCGv reg)
  .reg = cpu_cc_src, .mask = -1 };
 default:
 gen_compute_eflags(s);
-return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = CC_O };
+return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
+ .mask = -1, .imm = CC_O };
 }
 }
 
@@ -1074,8 +1074,8 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, 
TCGv reg)
 case CC_OP_ADCX:
 case CC_OP_ADOX:
 case CC_OP_ADCOX:
-return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = CC_Z };
+return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
+ .mask = -1, .imm = CC_Z };
 case CC_OP_CLR:
 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
 case CC_OP_POPCNT:
@@ -1153,8 +1153,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 break;
 case JCC_BE:
 gen_compute_eflags(s);
-cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
-   .mask = CC_Z | CC_C };
+cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
+   .mask = -1, .imm = CC_Z | CC_C };
 break;
 case JCC_S:
 cc = gen_prepare_eflags_s(s, reg);
@@ -1168,8 +1168,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 reg = s->tmp0;
 }
 tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S);
-cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
-   .mask = CC_O };
+cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg,
+   .mask = -1, .imm = CC_O };
 break;
 default:
 case JCC_LE:
@@ -1178,8 +1178,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 reg = s->tmp0;
 }
 tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S);
-cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
-   .mask = CC_O | CC_Z };
+cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg,
+   .mask = -1, .imm = CC_O | CC_Z };
 break;
 }
 break;
-- 
2.45.0




[PULL 26/26] target/i386: remove duplicate prefix decoding

2024-05-07 Thread Paolo Bonzini
Now that a bulk of opcodes go through the new decoder, it is sensible
to do some cleanup.  Go immediately through disas_insn_new and only jump
back after parsing the prefixes.

disas_insn() now only contains the three sigsetjmp cases, and they
are more easily managed if they are inlined into i386_tr_translate_insn.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c  | 259 +++
 target/i386/tcg/decode-new.c.inc |  63 ++--
 2 files changed, 103 insertions(+), 219 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index eb0e37e1480..3842b294842 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2451,10 +2451,6 @@ static void gen_sty_env_A0(DisasContext *s, int offset, 
bool align)
 tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop);
 }
 
-#include "decode-new.h"
-#include "emit.c.inc"
-#include "decode-new.c.inc"
-
 static void gen_cmpxchg8b(DisasContext *s, CPUX86State *env, int modrm)
 {
 TCGv_i64 cmp, val, old;
@@ -3117,183 +3113,6 @@ static bool disas_insn_x87(DisasContext *s, CPUState 
*cpu, int b)
 return true;
 }
 
-static void disas_insn_old(DisasContext *s, CPUState *cpu, int b);
-
-/* convert one instruction. s->base.is_jmp is set if the translation must
-   be stopped. Return the next pc value */
-static bool disas_insn(DisasContext *s, CPUState *cpu)
-{
-CPUX86State *env = cpu_env(cpu);
-int b, prefixes;
-MemOp aflag, dflag;
-bool orig_cc_op_dirty = s->cc_op_dirty;
-CCOp orig_cc_op = s->cc_op;
-target_ulong orig_pc_save = s->pc_save;
-
-s->pc = s->base.pc_next;
-s->override = -1;
-s->popl_esp_hack = 0;
-#ifdef TARGET_X86_64
-s->rex_r = 0;
-s->rex_x = 0;
-s->rex_b = 0;
-#endif
-s->rip_offset = 0; /* for relative ip address */
-s->vex_l = 0;
-s->vex_v = 0;
-s->vex_w = false;
-switch (sigsetjmp(s->jmpbuf, 0)) {
-case 0:
-break;
-case 1:
-gen_exception_gpf(s);
-return true;
-case 2:
-/* Restore state that may affect the next instruction. */
-s->pc = s->base.pc_next;
-/*
- * TODO: These save/restore can be removed after the table-based
- * decoder is complete; we will be decoding the insn completely
- * before any code generation that might affect these variables.
- */
-s->cc_op_dirty = orig_cc_op_dirty;
-s->cc_op = orig_cc_op;
-s->pc_save = orig_pc_save;
-/* END TODO */
-s->base.num_insns--;
-tcg_remove_ops_after(s->prev_insn_end);
-s->base.insn_start = s->prev_insn_start;
-s->base.is_jmp = DISAS_TOO_MANY;
-return false;
-default:
-g_assert_not_reached();
-}
-
-prefixes = 0;
-
- next_byte:
-s->prefix = prefixes;
-b = x86_ldub_code(env, s);
-/* Collect prefixes.  */
-switch (b) {
-case 0x0f:
-b = x86_ldub_code(env, s) + 0x100;
-break;
-case 0xf3:
-prefixes |= PREFIX_REPZ;
-prefixes &= ~PREFIX_REPNZ;
-goto next_byte;
-case 0xf2:
-prefixes |= PREFIX_REPNZ;
-prefixes &= ~PREFIX_REPZ;
-goto next_byte;
-case 0xf0:
-prefixes |= PREFIX_LOCK;
-goto next_byte;
-case 0x2e:
-s->override = R_CS;
-goto next_byte;
-case 0x36:
-s->override = R_SS;
-goto next_byte;
-case 0x3e:
-s->override = R_DS;
-goto next_byte;
-case 0x26:
-s->override = R_ES;
-goto next_byte;
-case 0x64:
-s->override = R_FS;
-goto next_byte;
-case 0x65:
-s->override = R_GS;
-goto next_byte;
-case 0x66:
-prefixes |= PREFIX_DATA;
-goto next_byte;
-case 0x67:
-prefixes |= PREFIX_ADR;
-goto next_byte;
-#ifdef TARGET_X86_64
-case 0x40 ... 0x4f:
-if (CODE64(s)) {
-/* REX prefix */
-prefixes |= PREFIX_REX;
-s->vex_w = (b >> 3) & 1;
-s->rex_r = (b & 0x4) << 1;
-s->rex_x = (b & 0x2) << 2;
-s->rex_b = (b & 0x1) << 3;
-goto next_byte;
-}
-break;
-#endif
-case 0xc5: /* 2-byte VEX */
-case 0xc4: /* 3-byte VEX */
-if (CODE32(s) && !VM86(s)) {
-int vex2 = x86_ldub_code(env, s);
-s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
-
-if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
-/* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
-   otherwise the instruction is LES or LDS.  */
-break;
-}
-disas_insn_new(s, cpu, b);
-return s->pc;
-

[PULL 12/26] target/i386: reintroduce debugging mechanism

2024-05-07 Thread Paolo Bonzini
Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c  | 27 +++
 target/i386/tcg/decode-new.c.inc |  3 +++
 2 files changed, 30 insertions(+)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index f018d6303a9..6a0c74c225f 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2969,6 +2969,9 @@ static void gen_sty_env_A0(DisasContext *s, int offset, 
bool align)
 tcg_gen_qemu_st_i128(t, s->tmp0, mem_index, mop);
 }
 
+static bool first = true;
+static unsigned long limit;
+
 #include "decode-new.h"
 #include "emit.c.inc"
 #include "decode-new.c.inc"
@@ -3124,15 +3127,39 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 
 prefixes = 0;
 
+if (first) {
+const char *limit_str = getenv("QEMU_I386_LIMIT");
+limit = limit_str ? atol(limit_str) : -1;
+first = false;
+}
+bool use_new = true;
+#ifdef CONFIG_USER_ONLY
+use_new &= limit > 0;
+#endif
+
  next_byte:
 s->prefix = prefixes;
 b = x86_ldub_code(env, s);
 /* Collect prefixes.  */
 switch (b) {
 default:
+#ifndef CONFIG_USER_ONLY
+use_new &= b <= limit;
+#endif
+if (use_new && 0) {
+disas_insn_new(s, cpu, b);
+return true;
+}
 break;
 case 0x0f:
 b = x86_ldub_code(env, s) + 0x100;
+#ifndef CONFIG_USER_ONLY
+use_new &= b <= limit;
+#endif
+if (use_new && 0) {
+disas_insn_new(s, cpu, b);
+return true;
+}
 break;
 case 0xf3:
 prefixes |= PREFIX_REPZ;
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 426c4594120..3fc6485d74c 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1689,6 +1689,9 @@ static void disas_insn_new(DisasContext *s, CPUState 
*cpu, int b)
 X86DecodeFunc decode_func = decode_root;
 uint8_t cc_live;
 
+#ifdef CONFIG_USER_ONLY
+if (limit) { --limit; }
+#endif
 s->has_modrm = false;
 
  next_byte:
-- 
2.45.0




[PULL 06/26] target/i386: cleanup cc_op changes for REP/REPZ/REPNZ

2024-05-07 Thread Paolo Bonzini
gen_update_cc_op must be called before control flow splits.  Do it
where the jump on ECX!=0 is translated.

On the other hand, remove the call before gen_jcc1, which takes care of
it already, and explain why REPZ/REPNZ need not use CC_OP_DYNAMIC---the
translation block ends before any control-flow-dependent cc_op could
be observed.

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3f1d2858fc9..466fee38c0e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1242,11 +1242,15 @@ static inline void gen_jcc1(DisasContext *s, int b, 
TCGLabel *l1)
 }
 
 /* XXX: does not work with gdbstub "ice" single step - not a
-   serious problem */
+   serious problem.  The caller can jump to the returned label
+   to stop the REP but, if the flags have changed, it has to call
+   gen_update_cc_op before doing so.  */
 static TCGLabel *gen_jz_ecx_string(DisasContext *s)
 {
 TCGLabel *l1 = gen_new_label();
 TCGLabel *l2 = gen_new_label();
+
+gen_update_cc_op(s);
 gen_op_jnz_ecx(s, l1);
 gen_set_label(l2);
 gen_jmp_rel_csize(s, 0, 1);
@@ -1342,7 +1346,6 @@ static void gen_repz(DisasContext *s, MemOp ot,
  void (*fn)(DisasContext *s, MemOp ot))
 {
 TCGLabel *l2;
-gen_update_cc_op(s);
 l2 = gen_jz_ecx_string(s);
 fn(s, ot);
 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
@@ -1364,15 +1367,18 @@ static void gen_repz2(DisasContext *s, MemOp ot, int nz,
   void (*fn)(DisasContext *s, MemOp ot))
 {
 TCGLabel *l2;
-gen_update_cc_op(s);
 l2 = gen_jz_ecx_string(s);
 fn(s, ot);
 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
-gen_update_cc_op(s);
 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);
 if (s->repz_opt) {
 gen_op_jz_ecx(s, l2);
 }
+/*
+ * Only one iteration is done at a time, so the translation
+ * block ends unconditionally after this instruction and there
+ * is no control flow junction - no need to set CC_OP_DYNAMIC.
+ */
 gen_jmp_rel_csize(s, -cur_insn_len(s), 0);
 }
 
-- 
2.45.0




[PULL 22/26] target/i386: port extensions of one-byte opcodes to new decoder

2024-05-07 Thread Paolo Bonzini
A few two-byte opcodes are simple extensions of existing one-byte opcodes;
they are easy to decode and need no change to emit.c.inc.  Port them to
the new decoder.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c  |  4 
 target/i386/tcg/decode-new.c.inc | 20 
 target/i386/tcg/emit.c.inc   | 15 +++
 3 files changed, 39 insertions(+)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 751ec5d0f1a..4fbd91e70d1 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3209,6 +3209,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #endif
 if (use_new &&
 ((b >= 0x138 && b <= 0x19f) ||
+ (b & ~9) == 0x1a0 ||
+ b == 0x1af || b == 0x1b2 ||
+ (b >= 0x1b4 && b <= 0x1b7) ||
+ b == 0x1be || b == 0x1bf || b == 0x1c3 ||
  (b >= 0x1c8 && b <= 0x1cf))) {
 disas_insn_new(s, cpu, b);
 return true;
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 16e23ec3d88..f9a966943fb 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1053,6 +1053,9 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x96] = X86_OP_ENTRYw(SETcc, E,b),
 [0x97] = X86_OP_ENTRYw(SETcc, E,b),
 
+[0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
+[0xa1] = X86_OP_ENTRYw(POP, FS, w),
+
 [0x28] = X86_OP_ENTRY3(MOVDQ,  V,x,  None,None, W,x, vex1 p_00_66), /* 
MOVAPS */
 [0x29] = X86_OP_ENTRY3(MOVDQ,  W,x,  None,None, V,x, vex1 p_00_66), /* 
MOVAPS */
 [0x2A] = X86_OP_GROUP0(0F2A),
@@ -1117,9 +1120,26 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x9e] = X86_OP_ENTRYw(SETcc, E,b),
 [0x9f] = X86_OP_ENTRYw(SETcc, E,b),
 
+[0xa8] = X86_OP_ENTRYr(PUSH,   GS, w),
+[0xa9] = X86_OP_ENTRYw(POP,GS, w),
 [0xae] = X86_OP_GROUP0(group15),
+/*
+ * It's slightly more efficient to put Ev operand in T0 and allow gen_IMUL3
+ * to assume sextT0.  Multiplication is commutative anyway.
+ */
+[0xaf] = X86_OP_ENTRY3(IMUL3,  G,v, E,v, 2op,v, sextT0),
+
+[0xb2] = X86_OP_ENTRY3(LSS,G,v, EM,p, None, None),
+[0xb4] = X86_OP_ENTRY3(LFS,G,v, EM,p, None, None),
+[0xb5] = X86_OP_ENTRY3(LGS,G,v, EM,p, None, None),
+[0xb6] = X86_OP_ENTRY3(MOV,G,v, E,b, None, None, zextT0), /* MOVZX */
+[0xb7] = X86_OP_ENTRY3(MOV,G,v, E,w, None, None, zextT0), /* MOVZX */
+
+[0xbe] = X86_OP_ENTRY3(MOV,G,v, E,b, None, None, sextT0), /* MOVSX */
+[0xbf] = X86_OP_ENTRY3(MOV,G,v, E,w, None, None, sextT0), /* MOVSX */
 
 [0xc2] = X86_OP_ENTRY4(VCMP,   V,x, H,x, W,x,   vex2_rep3 
p_00_66_f3_f2),
+[0xc3] = X86_OP_ENTRY3(MOV,EM,y,G,y, None,None, cpuid(SSE2)), /* 
MOVNTI */
 [0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w,   vex5 mmx p_00_66),
 [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b,   vex5 mmx p_00_66),
 [0xc6] = X86_OP_ENTRY4(VSHUF,  V,x, H,x, W,x,   vex4 p_00_66),
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index befde6677be..58f255873ff 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1979,6 +1979,16 @@ static void gen_LES(DisasContext *s, CPUX86State *env, 
X86DecodedInsn *decode)
 gen_lxx_seg(s, env, decode, R_ES);
 }
 
+static void gen_LFS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+{
+gen_lxx_seg(s, env, decode, R_FS);
+}
+
+static void gen_LGS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+{
+gen_lxx_seg(s, env, decode, R_GS);
+}
+
 static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
 {
 MemOp ot = decode->op[2].ot;
@@ -2023,6 +2033,11 @@ static void gen_LOOPNE(DisasContext *s, CPUX86State 
*env, X86DecodedInsn *decode
 gen_conditional_jump_labels(s, decode->immediate, not_taken, taken);
 }
 
+static void gen_LSS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+{
+gen_lxx_seg(s, env, decode, R_SS);
+}
+
 static void gen_MOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
 {
 /* nothing to do! */
-- 
2.45.0




[PULL 24/26] target/i386: decode x87 instructions in a separate function

2024-05-07 Thread Paolo Bonzini
These are unlikely to be converted to the table-based decoding
soon (perhaps there could be generic ESC decoding in decode-new.c.inc
for the Mod/RM byte, but not operand decoding), so keep them separate
from the remaining legacy-decoded instructions.

Acked-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 1120 ++-
 1 file changed, 566 insertions(+), 554 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index f4e5843d5f5..973bf07ef27 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2553,6 +2553,570 @@ static void gen_cmpxchg16b(DisasContext *s, CPUX86State 
*env, int modrm)
 }
 #endif
 
+static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b)
+{
+CPUX86State *env = cpu_env(cpu);
+bool update_fip = true;
+int modrm, mod, rm, op;
+
+if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
+/* if CR0.EM or CR0.TS are set, generate an FPU exception */
+/* XXX: what to do if illegal op ? */
+gen_exception(s, EXCP07_PREX);
+return true;
+}
+modrm = x86_ldub_code(env, s);
+mod = (modrm >> 6) & 3;
+rm = modrm & 7;
+op = ((b & 7) << 3) | ((modrm >> 3) & 7);
+if (mod != 3) {
+/* memory op */
+AddressParts a = gen_lea_modrm_0(env, s, modrm);
+TCGv ea = gen_lea_modrm_1(s, a, false);
+TCGv last_addr = tcg_temp_new();
+bool update_fdp = true;
+
+tcg_gen_mov_tl(last_addr, ea);
+gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
+
+switch (op) {
+case 0x00 ... 0x07: /* fxxxs */
+case 0x10 ... 0x17: /* fixxxl */
+case 0x20 ... 0x27: /* fxxxl */
+case 0x30 ... 0x37: /* fixxx */
+{
+int op1;
+op1 = op & 7;
+
+switch (op >> 4) {
+case 0:
+tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
+s->mem_index, MO_LEUL);
+gen_helper_flds_FT0(tcg_env, s->tmp2_i32);
+break;
+case 1:
+tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
+s->mem_index, MO_LEUL);
+gen_helper_fildl_FT0(tcg_env, s->tmp2_i32);
+break;
+case 2:
+tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
+s->mem_index, MO_LEUQ);
+gen_helper_fldl_FT0(tcg_env, s->tmp1_i64);
+break;
+case 3:
+default:
+tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
+s->mem_index, MO_LESW);
+gen_helper_fildl_FT0(tcg_env, s->tmp2_i32);
+break;
+}
+
+gen_helper_fp_arith_ST0_FT0(op1);
+if (op1 == 3) {
+/* fcomp needs pop */
+gen_helper_fpop(tcg_env);
+}
+}
+break;
+case 0x08: /* flds */
+case 0x0a: /* fsts */
+case 0x0b: /* fstps */
+case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
+case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
+case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
+switch (op & 7) {
+case 0:
+switch (op >> 4) {
+case 0:
+tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
+s->mem_index, MO_LEUL);
+gen_helper_flds_ST0(tcg_env, s->tmp2_i32);
+break;
+case 1:
+tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
+s->mem_index, MO_LEUL);
+gen_helper_fildl_ST0(tcg_env, s->tmp2_i32);
+break;
+case 2:
+tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
+s->mem_index, MO_LEUQ);
+gen_helper_fldl_ST0(tcg_env, s->tmp1_i64);
+break;
+case 3:
+default:
+tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0,
+s->mem_index, MO_LESW);
+gen_helper_fildl_ST0(tcg_env, s->tmp2_i32);
+break;
+}
+break;
+case 1:
+/* XXX: the corresponding CPUID bit must be tested ! */
+switch (op >> 4) {
+case 1:
+gen_helper_fisttl_ST0(s->tmp2_i32, tcg_env);
+

[PULL 15/26] target/i386: allow instructions with more than one immediate

2024-05-07 Thread Paolo Bonzini
While keeping decode->immediate for convenience and for 4-operand instructions,
store the immediate in X86DecodedOp as well.  This enables instructions
with more than one immediate such as ENTER.  It can also be used for far
calls and jumps.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h | 17 -
 target/i386/tcg/decode-new.c.inc |  2 +-
 target/i386/tcg/emit.c.inc   |  4 +++-
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 15e6bfef4b1..8ffde8d1cd6 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -271,16 +271,23 @@ typedef struct X86DecodedOp {
 bool has_ea;
 int offset;   /* For MMX and SSE */
 
-/*
- * This field is used internally by macros OP0_PTR/OP1_PTR/OP2_PTR,
- * do not access directly!
- */
-TCGv_ptr v_ptr;
+union {
+   target_ulong imm;
+/*
+ * This field is used internally by macros OP0_PTR/OP1_PTR/OP2_PTR,
+ * do not access directly!
+ */
+TCGv_ptr v_ptr;
+};
 } X86DecodedOp;
 
 struct X86DecodedInsn {
 X86OpEntry e;
 X86DecodedOp op[3];
+/*
+ * Rightmost immediate, for convenience since most instructions have
+ * one (and also for 4-operand instructions).
+ */
 target_ulong immediate;
 AddressParts mem;
 
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 1e792426ff5..c6fd7a053bd 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1473,7 +1473,7 @@ static bool decode_op(DisasContext *s, CPUX86State *env, 
X86DecodedInsn *decode,
 case X86_TYPE_I:  /* Immediate */
 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 = op->imm = insn_get_signed(env, s, op->ot);
 break;
 
 case X86_TYPE_L:  /* The upper 4 bits of the immediate select a 128-bit 
register */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index a64186b8957..fc065caae79 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -259,7 +259,7 @@ static void gen_load(DisasContext *s, X86DecodedInsn 
*decode, int opn, TCGv v)
 }
 break;
 case X86_OP_IMM:
-tcg_gen_movi_tl(v, decode->immediate);
+tcg_gen_movi_tl(v, op->imm);
 break;
 
 case X86_OP_MMX:
@@ -283,6 +283,8 @@ static void gen_load(DisasContext *s, X86DecodedInsn 
*decode, int opn, TCGv v)
 static TCGv_ptr op_ptr(X86DecodedInsn *decode, int opn)
 {
 X86DecodedOp *op = >op[opn];
+
+assert(op->unit == X86_OP_MMX || op->unit == X86_OP_SSE);
 if (op->v_ptr) {
 return op->v_ptr;
 }
-- 
2.45.0




[PULL 05/26] target/i386: cc_op is not dynamic in gen_jcc1

2024-05-07 Thread Paolo Bonzini
Resetting cc_op to CC_OP_DYNAMIC should be done at control flow junctions,
which is not the case here.  This translation block is ending and the
only effect of calling set_cc_op() would be a discard of s->cc_srcT.
This discard is useless (it's a temporary, not a global) and in fact
prevents gen_prepare_cc from returning s->cc_srcT.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 9aecd415b38..3f1d2858fc9 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1227,13 +1227,13 @@ static inline void gen_jcc1_noeob(DisasContext *s, int 
b, TCGLabel *l1)
 
 /* Generate a conditional jump to label 'l1' according to jump opcode
value 'b'. In the fast case, T0 is guaranteed not to be used.
-   A translation block must end soon.  */
+   One or both of the branches will call gen_jmp_rel, so ensure
+   cc_op is clean.  */
 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
 {
 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
 
 gen_update_cc_op(s);
-set_cc_op(s, CC_OP_DYNAMIC);
 if (cc.use_reg2) {
 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
 } else {
-- 
2.45.0




[PULL 21/26] target/i386: move BSWAP to new decoder

2024-05-07 Thread Paolo Bonzini
Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c  |  4 +++-
 target/i386/tcg/decode-new.c.inc |  9 +
 target/i386/tcg/emit.c.inc   | 11 +++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index b1c1aecf71e..751ec5d0f1a 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3207,7 +3207,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && (b >= 0x138 && b <= 0x19f)) {
+if (use_new &&
+((b >= 0x138 && b <= 0x19f) ||
+ (b >= 0x1c8 && b <= 0x1cf))) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index c70a7836914..16e23ec3d88 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1124,6 +1124,15 @@ static const X86OpEntry opcodes_0F[256] = {
 [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b,   vex5 mmx p_00_66),
 [0xc6] = X86_OP_ENTRY4(VSHUF,  V,x, H,x, W,x,   vex4 p_00_66),
 
+[0xc8] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xc9] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xca] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcb] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcc] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcd] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xce] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcf] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+
 [0xd0] = X86_OP_ENTRY3(VADDSUB,   V,x, H,x, W,x,vex2 cpuid(SSE3) 
p_66_f2),
 [0xd1] = X86_OP_ENTRY3(PSRLW_r,   V,x, H,x, W,x,vex4 mmx avx2_256 
p_00_66),
 [0xd2] = X86_OP_ENTRY3(PSRLD_r,   V,x, H,x, W,x,vex4 mmx avx2_256 
p_00_66),
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index a9e32516afd..befde6677be 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1310,6 +1310,17 @@ static void gen_BOUND(DisasContext *s, CPUX86State *env, 
X86DecodedInsn *decode)
 }
 }
 
+static void gen_BSWAP(DisasContext *s, CPUX86State *env, X86DecodedInsn 
*decode)
+{
+#ifdef TARGET_X86_64
+if (s->dflag == MO_64) {
+tcg_gen_bswap64_i64(s->T0, s->T0);
+return;
+}
+#endif
+tcg_gen_bswap32_tl(s->T0, s->T0, TCG_BSWAP_OZ);
+}
+
 static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
 {
 MemOp ot = decode->op[0].ot;
-- 
2.45.0




[PULL 17/26] target/i386: generalize gen_movl_seg_T0

2024-05-07 Thread Paolo Bonzini
In the new decoder it is sometimes easier to put the segment
in T1 instead of T0, usually because another operand was loaded
by common code in T0.  Genrealize gen_movl_seg_T0 to allow
using any source.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 16 
 target/i386/tcg/emit.c.inc  |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4f47c40fb08..e09bfdaa39b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2525,12 +2525,12 @@ static void gen_op_movl_seg_real(DisasContext *s, 
X86Seg seg_reg, TCGv seg)
 tcg_gen_shli_tl(cpu_seg_base[seg_reg], selector, 4);
 }
 
-/* move T0 to seg_reg and compute if the CPU state may change. Never
+/* move SRC to seg_reg and compute if the CPU state may change. Never
call this function with seg_reg == R_CS */
-static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
+static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src)
 {
 if (PE(s) && !VM86(s)) {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
+tcg_gen_trunc_tl_i32(s->tmp2_i32, src);
 gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), s->tmp2_i32);
 /* abort translation because the addseg value may change or
because ss32 may change. For R_SS, translation must always
@@ -2542,7 +2542,7 @@ static void gen_movl_seg_T0(DisasContext *s, X86Seg 
seg_reg)
 s->base.is_jmp = DISAS_EOB_NEXT;
 }
 } else {
-gen_op_movl_seg_real(s, seg_reg, s->T0);
+gen_op_movl_seg_real(s, seg_reg, src);
 if (seg_reg == R_SS) {
 s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
 }
@@ -4084,13 +4084,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 goto illegal_op;
 reg = b >> 3;
 ot = gen_pop_T0(s);
-gen_movl_seg_T0(s, reg);
+gen_movl_seg(s, reg, s->T0);
 gen_pop_update(s, ot);
 break;
 case 0x1a1: /* pop fs */
 case 0x1a9: /* pop gs */
 ot = gen_pop_T0(s);
-gen_movl_seg_T0(s, (b >> 3) & 7);
+gen_movl_seg(s, (b >> 3) & 7, s->T0);
 gen_pop_update(s, ot);
 break;
 
@@ -4137,7 +4137,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 if (reg >= 6 || reg == R_CS)
 goto illegal_op;
 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
-gen_movl_seg_T0(s, reg);
+gen_movl_seg(s, reg, s->T0);
 break;
 case 0x8c: /* mov Gv, seg */
 modrm = x86_ldub_code(env, s);
@@ -4323,7 +4323,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 gen_add_A0_im(s, 1 << ot);
 /* load the segment first to handle exceptions properly */
 gen_op_ld_v(s, MO_16, s->T0, s->A0);
-gen_movl_seg_T0(s, op);
+gen_movl_seg(s, op, s->T0);
 /* then put the data */
 gen_op_mov_reg_v(s, ot, reg, s->T1);
 break;
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 5834f8ea0fd..56ce0d2a9f3 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -306,8 +306,8 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn 
*decode, int opn, TCGv
 case X86_OP_SKIP:
 break;
 case X86_OP_SEG:
-/* Note that gen_movl_seg_T0 takes care of interrupt shadow and TF.  */
-gen_movl_seg_T0(s, op->n);
+/* Note that gen_movl_seg takes care of interrupt shadow and TF.  */
+gen_movl_seg(s, op->n, s->T0);
 break;
 case X86_OP_INT:
 if (op->has_ea) {
-- 
2.45.0




[PULL 11/26] target/i386: cleanup *gen_eob*

2024-05-07 Thread Paolo Bonzini
Create a new wrapper for syscall/sysret, and do not go through multiple
layers of wrappers.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 25 -
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 8e0289ca414..f018d6303a9 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2783,7 +2783,7 @@ static void gen_bnd_jmp(DisasContext *s)
If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
S->TF.  This is used by the syscall/sysret insns.  */
 static void
-do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
+gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
 {
 bool inhibit_reset;
 
@@ -2817,28 +2817,27 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool 
recheck_tf, bool jr)
 }
 
 static inline void
-gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
+gen_eob_syscall(DisasContext *s)
 {
-do_gen_eob_worker(s, inhibit, recheck_tf, false);
+gen_eob_worker(s, false, true, false);
 }
 
-/* End of block.
-   If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.  */
-static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
+/* End of block.  Set HF_INHIBIT_IRQ_MASK if it isn't already set.  */
+static void gen_eob_inhibit_irq(DisasContext *s)
 {
-gen_eob_worker(s, inhibit, false);
+gen_eob_worker(s, true, false, false);
 }
 
 /* End of block, resetting the inhibit irq flag.  */
 static void gen_eob(DisasContext *s)
 {
-gen_eob_worker(s, false, false);
+gen_eob_worker(s, false, false, false);
 }
 
 /* Jump to register */
 static void gen_jr(DisasContext *s)
 {
-do_gen_eob_worker(s, false, false, true);
+gen_eob_worker(s, false, false, true);
 }
 
 /* Jump to eip+diff, truncating the result to OT. */
@@ -5591,7 +5590,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 gen_set_eflags(s, IF_MASK);
 /* interruptions are enabled only the first insn after sti */
 gen_update_eip_next(s);
-gen_eob_inhibit_irq(s, true);
+gen_eob_inhibit_irq(s);
 }
 break;
 case 0x62: /* bound */
@@ -5725,7 +5724,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 /* TF handling for the syscall insn is different. The TF bit is  
checked
after the syscall insn completes. This allows #DB to not be
generated after one has entered CPL0 if TF is set in FMASK.  */
-gen_eob_worker(s, false, true);
+gen_eob_syscall(s);
 break;
 case 0x107: /* sysret */
 /* For Intel SYSRET is only valid in long mode */
@@ -5744,7 +5743,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
checked after the sysret insn completes. This allows #DB to be
generated "as if" the syscall insn in userspace has just
completed.  */
-gen_eob_worker(s, false, true);
+gen_eob_syscall(s);
 }
 break;
 case 0x1a2: /* cpuid */
@@ -7059,7 +7058,7 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 case DISAS_EOB_INHIBIT_IRQ:
 gen_update_cc_op(dc);
 gen_update_eip_cur(dc);
-gen_eob_inhibit_irq(dc, true);
+gen_eob_inhibit_irq(dc);
 break;
 case DISAS_JUMP:
 gen_jr(dc);
-- 
2.45.0




[PULL 19/26] target/i386: merge and enlarge a few ranges for call to disas_insn_new

2024-05-07 Thread Paolo Bonzini
Since new opcodes are not going to be added in translate.c, round the
case labels that call to disas_insn_new(), including whole sets of
eight opcodes when possible.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index f83204bd1ed..3060fdbee94 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -6869,9 +6869,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 break;
 case 0x10e ... 0x117:
 case 0x128 ... 0x12f:
-case 0x138 ... 0x13a:
-case 0x150 ... 0x179:
-case 0x17c ... 0x17f:
+case 0x138 ... 0x13f:
+case 0x150 ... 0x17f:
 case 0x1c2:
 case 0x1c4 ... 0x1c6:
 case 0x1d0 ... 0x1fe:
-- 
2.45.0




[PULL 04/26] target/i386: remove mask from CCPrepare

2024-05-07 Thread Paolo Bonzini
With the introduction of TSTEQ and TSTNE the .mask field is always -1,
so remove all the now-unnecessary code.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 81 +
 1 file changed, 27 insertions(+), 54 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 62ba21c1d74..9aecd415b38 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -923,7 +923,6 @@ typedef struct CCPrepare {
 TCGv reg;
 TCGv reg2;
 target_ulong imm;
-target_ulong mask;
 bool use_reg2;
 bool no_setcond;
 } CCPrepare;
@@ -931,9 +930,9 @@ typedef struct CCPrepare {
 static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size)
 {
 if (size == MO_TL) {
-return (CCPrepare) { .cond = TCG_COND_LT, .reg = src, .mask = -1 };
+return (CCPrepare) { .cond = TCG_COND_LT, .reg = src };
 } else {
-return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src, .mask = -1,
+return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = src,
  .imm = 1ull << ((8 << size) - 1) };
 }
 }
@@ -962,17 +961,17 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, 
TCGv reg)
 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
 add_sub:
 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
- .reg2 = t1, .mask = -1, .use_reg2 = true };
+ .reg2 = t1, .use_reg2 = true };
 
 case CC_OP_LOGICB ... CC_OP_LOGICQ:
 case CC_OP_CLR:
 case CC_OP_POPCNT:
-return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
+return (CCPrepare) { .cond = TCG_COND_NEVER };
 
 case CC_OP_INCB ... CC_OP_INCQ:
 case CC_OP_DECB ... CC_OP_DECQ:
 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
- .mask = -1, .no_setcond = true };
+ .no_setcond = true };
 
 case CC_OP_SHLB ... CC_OP_SHLQ:
 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
@@ -981,23 +980,23 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, 
TCGv reg)
 
 case CC_OP_MULB ... CC_OP_MULQ:
 return (CCPrepare) { .cond = TCG_COND_NE,
- .reg = cpu_cc_src, .mask = -1 };
+ .reg = cpu_cc_src };
 
 case CC_OP_BMILGB ... CC_OP_BMILGQ:
 size = s->cc_op - CC_OP_BMILGB;
 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
-return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
+return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0 };
 
 case CC_OP_ADCX:
 case CC_OP_ADCOX:
 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
- .mask = -1, .no_setcond = true };
+ .no_setcond = true };
 
 case CC_OP_EFLAGS:
 case CC_OP_SARB ... CC_OP_SARQ:
 /* CC_SRC & 1 */
 return (CCPrepare) { .cond = TCG_COND_TSTNE,
- .reg = cpu_cc_src, .mask = -1, .imm = CC_C };
+ .reg = cpu_cc_src, .imm = CC_C };
 
 default:
/* The need to compute only C from CC_OP_DYNAMIC is important
@@ -1006,7 +1005,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, 
TCGv reg)
gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
cpu_cc_src2, cpu_cc_op);
return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
-.mask = -1, .no_setcond = true };
+.no_setcond = true };
 }
 }
 
@@ -1015,7 +1014,7 @@ static CCPrepare gen_prepare_eflags_p(DisasContext *s, 
TCGv reg)
 {
 gen_compute_eflags(s);
 return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
- .mask = -1, .imm = CC_P };
+ .imm = CC_P };
 }
 
 /* compute eflags.S to reg */
@@ -1030,10 +1029,10 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, 
TCGv reg)
 case CC_OP_ADOX:
 case CC_OP_ADCOX:
 return (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = cpu_cc_src,
- .mask = -1, .imm = CC_S };
+ .imm = CC_S };
 case CC_OP_CLR:
 case CC_OP_POPCNT:
-return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
+return (CCPrepare) { .cond = TCG_COND_NEVER };
 default:
 {
 MemOp size = (s->cc_op - CC_OP_ADDB) & 3;
@@ -1049,17 +1048,16 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, 
TCGv reg)
 case CC_OP_ADOX:
 case CC_OP_ADCOX:
 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
- .mask = -1, .no_setcond = true };
+ .no_setcond = true };
 case CC_OP_CLR:
 case CC_OP_POPCNT:
-return (CCPrepare) { .cond = TCG_COND_NEVER, .mas

[PULL 08/26] target/i386: extend cc_* when using them to compute flags

2024-05-07 Thread Paolo Bonzini
Instead of using s->tmp0 or s->tmp4 as the result, just extend the cc_*
registers in place.  It is harmless and, if multiple setcc instructions
are used, the optimizer will be able to remove the redundant ones.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 44 +++--
 1 file changed, 18 insertions(+), 26 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 024da6d88eb..7292908adc3 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -940,28 +940,24 @@ static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size)
 /* compute eflags.C to reg */
 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
 {
-TCGv t0, t1;
 MemOp size;
 
 switch (s->cc_op) {
 case CC_OP_SUBB ... CC_OP_SUBQ:
 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
 size = s->cc_op - CC_OP_SUBB;
-t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
-/* If no temporary was used, be careful not to alias t1 and t0.  */
-t0 = t1 == cpu_cc_src ? s->tmp0 : reg;
-tcg_gen_mov_tl(t0, s->cc_srcT);
-gen_extu(size, t0);
-goto add_sub;
+gen_ext_tl(s->cc_srcT, s->cc_srcT, size, false);
+gen_ext_tl(cpu_cc_src, cpu_cc_src, size, false);
+return (CCPrepare) { .cond = TCG_COND_LTU, .reg = s->cc_srcT,
+ .reg2 = cpu_cc_src, .use_reg2 = true };
 
 case CC_OP_ADDB ... CC_OP_ADDQ:
 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
 size = s->cc_op - CC_OP_ADDB;
-t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
-t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
-add_sub:
-return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
- .reg2 = t1, .use_reg2 = true };
+gen_ext_tl(cpu_cc_dst, cpu_cc_dst, size, false);
+gen_ext_tl(cpu_cc_src, cpu_cc_src, size, false);
+return (CCPrepare) { .cond = TCG_COND_LTU, .reg = cpu_cc_dst,
+ .reg2 = cpu_cc_src, .use_reg2 = true };
 
 case CC_OP_LOGICB ... CC_OP_LOGICQ:
 case CC_OP_CLR:
@@ -984,8 +980,8 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv 
reg)
 
 case CC_OP_BMILGB ... CC_OP_BMILGQ:
 size = s->cc_op - CC_OP_BMILGB;
-t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
-return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0 };
+gen_ext_tl(cpu_cc_src, cpu_cc_src, size, false);
+return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src };
 
 case CC_OP_ADCX:
 case CC_OP_ADCOX:
@@ -1098,7 +1094,6 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 int inv, jcc_op, cond;
 MemOp size;
 CCPrepare cc;
-TCGv t0;
 
 inv = b & 1;
 jcc_op = (b >> 1) & 7;
@@ -1109,24 +1104,21 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 size = s->cc_op - CC_OP_SUBB;
 switch (jcc_op) {
 case JCC_BE:
-tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
-gen_extu(size, s->tmp4);
-t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false);
-cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4,
-   .reg2 = t0, .use_reg2 = true };
+gen_ext_tl(s->cc_srcT, s->cc_srcT, size, false);
+gen_ext_tl(cpu_cc_src, cpu_cc_src, size, false);
+cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->cc_srcT,
+   .reg2 = cpu_cc_src, .use_reg2 = true };
 break;
-
 case JCC_L:
 cond = TCG_COND_LT;
 goto fast_jcc_l;
 case JCC_LE:
 cond = TCG_COND_LE;
 fast_jcc_l:
-tcg_gen_mov_tl(s->tmp4, s->cc_srcT);
-gen_exts(size, s->tmp4);
-t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true);
-cc = (CCPrepare) { .cond = cond, .reg = s->tmp4,
-   .reg2 = t0, .use_reg2 = true };
+gen_ext_tl(s->cc_srcT, s->cc_srcT, size, true);
+gen_ext_tl(cpu_cc_src, cpu_cc_src, size, true);
+cc = (CCPrepare) { .cond = cond, .reg = s->cc_srcT,
+   .reg2 = cpu_cc_src, .use_reg2 = true };
 break;
 
 default:
-- 
2.45.0




[PULL 09/26] target/i386: do not use s->T0 and s->T1 as scratch registers for CCPrepare

2024-05-07 Thread Paolo Bonzini
Instead of using s->T0 or s->T1, create a scratch register
when computing the C, NC, L or LE conditions.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 7292908adc3..dae9553fcaa 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -998,6 +998,9 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv 
reg)
/* The need to compute only C from CC_OP_DYNAMIC is important
   in efficiently implementing e.g. INC at the start of a TB.  */
gen_update_cc_op(s);
+   if (!reg) {
+   reg = tcg_temp_new();
+   }
gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
cpu_cc_src2, cpu_cc_op);
return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
@@ -1152,8 +1155,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 break;
 case JCC_L:
 gen_compute_eflags(s);
-if (reg == cpu_cc_src) {
-reg = s->tmp0;
+if (!reg || reg == cpu_cc_src) {
+reg = tcg_temp_new();
 }
 tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S);
 cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg,
@@ -1162,8 +1165,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 default:
 case JCC_LE:
 gen_compute_eflags(s);
-if (reg == cpu_cc_src) {
-reg = s->tmp0;
+if (!reg || reg == cpu_cc_src) {
+reg = tcg_temp_new();
 }
 tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S);
 cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg,
@@ -1208,7 +1211,7 @@ static inline void gen_compute_eflags_c(DisasContext *s, 
TCGv reg)
value 'b'. In the fast case, T0 is guaranteed not to be used. */
 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
 {
-CCPrepare cc = gen_prepare_cc(s, b, s->T0);
+CCPrepare cc = gen_prepare_cc(s, b, NULL);
 
 if (cc.use_reg2) {
 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
@@ -1223,7 +1226,7 @@ static inline void gen_jcc1_noeob(DisasContext *s, int b, 
TCGLabel *l1)
cc_op is clean.  */
 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
 {
-CCPrepare cc = gen_prepare_cc(s, b, s->T0);
+CCPrepare cc = gen_prepare_cc(s, b, NULL);
 
 gen_update_cc_op(s);
 if (cc.use_reg2) {
@@ -2493,7 +2496,7 @@ static void gen_jcc(DisasContext *s, int b, int diff)
 
 static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src)
 {
-CCPrepare cc = gen_prepare_cc(s, b, s->T1);
+CCPrepare cc = gen_prepare_cc(s, b, NULL);
 
 if (!cc.use_reg2) {
 cc.reg2 = tcg_constant_tl(cc.imm);
-- 
2.45.0




[PULL 10/26] target/i386: clarify the "reg" argument of functions returning CCPrepare

2024-05-07 Thread Paolo Bonzini
Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index dae9553fcaa..8e0289ca414 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -937,7 +937,7 @@ static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size)
 }
 }
 
-/* compute eflags.C to reg */
+/* compute eflags.C, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
 {
 MemOp size;
@@ -1008,7 +1008,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* compute eflags.P to reg */
+/* compute eflags.P, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
 {
 gen_compute_eflags(s);
@@ -1016,7 +1016,7 @@ static CCPrepare gen_prepare_eflags_p(DisasContext *s, 
TCGv reg)
  .imm = CC_P };
 }
 
-/* compute eflags.S to reg */
+/* compute eflags.S, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
 {
 switch (s->cc_op) {
@@ -1040,7 +1040,7 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* compute eflags.O to reg */
+/* compute eflags.O, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
 {
 switch (s->cc_op) {
@@ -1060,7 +1060,7 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* compute eflags.Z to reg */
+/* compute eflags.Z, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
 {
 switch (s->cc_op) {
@@ -1090,8 +1090,9 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* perform a conditional store into register 'reg' according to jump opcode
-   value 'b'. In the fast case, T0 is guaranteed not to be used. */
+/* return how to compute jump opcode 'b'.  'reg' can be clobbered
+ * if needed; it may be used for CCPrepare.reg if that will
+ * provide more freedom in the translation of a subsequent setcond. */
 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
 {
 int inv, jcc_op, cond;
-- 
2.45.0




[PULL 18/26] target/i386: move C0-FF opcodes to new decoder (except for x87)

2024-05-07 Thread Paolo Bonzini
The shift instructions are rewritten instead of reusing code from the old
decoder.  Rotates use CC_OP_ADCOX more extensively and generally rely
more on the optimizer, so that the code generators are shared between
the immediate-count and variable-count cases.

In particular, this makes gen_RCL and gen_RCR pretty efficient for the
count == 1 case, which becomes (apart from a few extra movs) something like:

  (compute_cc_all if needed)
  // save old value for OF calculation
  mov cc_src2, T0
  // the bulk of RCL is just this!
  deposit T0, cc_src, T0, 1, TARGET_LONG_BITS - 1
  // compute carry
  shr cc_dst, cc_src2, length - 1
  and cc_dst, cc_dst, 1
  // compute overflow
  xor cc_src2, cc_src2, T0
  extract cc_src2, cc_src2, length - 1, 1

32-bit MUL and IMUL are also slightly more efficient on 64-bit hosts.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |2 +
 target/i386/tcg/translate.c  |   23 +-
 target/i386/tcg/decode-new.c.inc |  153 +
 target/i386/tcg/emit.c.inc   | 1021 +-
 4 files changed, 1188 insertions(+), 11 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 790ad5e1d00..e86a5c2cb56 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -47,6 +47,7 @@ typedef enum X86OpType {
 X86_TYPE_Y, /* string destination */
 
 /* Custom */
+X86_TYPE_EM, /* modrm byte selects an ALU memory operand */
 X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
 X86_TYPE_I_unsigned, /* Immediate, zero-extended */
 X86_TYPE_2op, /* 2-operand RMW instruction */
@@ -89,6 +90,7 @@ typedef enum X86OpSize {
 X86_SIZE_x,  /* 128/256-bit, based on operand size */
 X86_SIZE_y,  /* 32/64-bit, based on operand size */
 X86_SIZE_z,  /* 16-bit for 16-bit operand size, else 32-bit */
+X86_SIZE_z_f64,  /* 32-bit for 32-bit operand size or 64-bit mode, else 
16-bit */
 
 /* Custom */
 X86_SIZE_d64,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index e09bfdaa39b..f83204bd1ed 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -38,6 +38,9 @@
 #include "exec/helper-info.c.inc"
 #undef  HELPER_H
 
+/* Fixes for Windows namespace pollution.  */
+#undef IN
+#undef OUT
 
 #define PREFIX_REPZ   0x01
 #define PREFIX_REPNZ  0x02
@@ -2489,14 +2492,24 @@ static inline int insn_const_size(MemOp ot)
 }
 }
 
+static void gen_conditional_jump_labels(DisasContext *s, target_long diff,
+TCGLabel *not_taken, TCGLabel *taken)
+{
+if (not_taken) {
+gen_set_label(not_taken);
+}
+gen_jmp_rel_csize(s, 0, 1);
+
+gen_set_label(taken);
+gen_jmp_rel(s, s->dflag, diff, 0);
+}
+
 static void gen_jcc(DisasContext *s, int b, int diff)
 {
 TCGLabel *l1 = gen_new_label();
 
 gen_jcc1(s, b, l1);
-gen_jmp_rel_csize(s, 0, 1);
-gen_set_label(l1);
-gen_jmp_rel(s, s->dflag, diff, 0);
+gen_conditional_jump_labels(s, diff, NULL, l1);
 }
 
 static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src)
@@ -2753,7 +2766,7 @@ static void gen_unknown_opcode(CPUX86State *env, 
DisasContext *s)
 
 /* an interrupt is different from an exception because of the
privilege checks */
-static void gen_interrupt(DisasContext *s, int intno)
+static void gen_interrupt(DisasContext *s, uint8_t intno)
 {
 gen_update_cc_op(s);
 gen_update_eip_cur(s);
@@ -3184,7 +3197,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && b <= 0xbf) {
+if (use_new && (b < 0xd8 || b >= 0xe0)) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 55fc0173a41..b145af7a565 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -43,6 +43,12 @@
  * Operand types
  * -
  *
+ * For memory-only operands, if the emitter functions wants to rely on
+ * generic load and writeback, the decoder needs to know the type of the
+ * operand.  Therefore, M is often replaced by the more specific EM and WM
+ * (respectively selecting an ALU operand, like the operand type E, or a
+ * vector operand like the operand type W).
+ *
  * Immediates are almost always signed or masked away in helpers.  Two
  * common exceptions are IN/OUT and absolute jumps.  For these, there is
  * an additional custom operand type "I_unsigned".  Alternatively, the
@@ -135,6 +141,8 @@
 ## __VA_ARGS__\
 }
 
+#define X86_OP_GROUP1(op, op0, s0, ...)   \
+X86_OP_GROUP3(op, op0, s0, 2op, s0, None, None, ## __VA_ARGS__)
 #define X86_OP_GROUP2(op, op0, s0, op1, s1, ...) 

[PULL 20/26] target/i386: move remaining conditional operations to new decoder

2024-05-07 Thread Paolo Bonzini
Move long-displacement Jcc, SETcc and CMOVcc to the new decoder.
While filling in the tables makes the code seem longer, the new
emitters are all just one line of code.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |  1 +
 target/i386/tcg/translate.c  |  2 +-
 target/i386/tcg/decode-new.c.inc | 56 
 target/i386/tcg/emit.c.inc   | 10 ++
 4 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index e86a5c2cb56..2ea06b44787 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -107,6 +107,7 @@ typedef enum X86CPUIDFeature {
 X86_FEAT_AVX2,
 X86_FEAT_BMI1,
 X86_FEAT_BMI2,
+X86_FEAT_CMOV,
 X86_FEAT_CMPCCXADD,
 X86_FEAT_F16C,
 X86_FEAT_FMA,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3060fdbee94..b1c1aecf71e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3207,7 +3207,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && 0) {
+if (use_new && (b >= 0x138 && b <= 0x19f)) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index b145af7a565..c70a7836914 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -999,6 +999,15 @@ static const X86OpEntry opcodes_0F[256] = {
 /* Incorrectly listed as Mq,Vq in the manual */
 [0x17] = X86_OP_ENTRY3(VMOVHPx_st,  M,q, None,None, V,dq, vex5 p_00_66),
 
+[0x40] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x41] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x42] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x43] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x44] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x45] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x46] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x47] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+
 [0x50] = X86_OP_ENTRY3(MOVMSK, G,y, None,None, U,x, vex7 p_00_66),
 [0x51] = X86_OP_GROUP3(sse_unary,  V,x, H,x, W,x, vex2_rep3 
p_00_66_f3_f2), /* sqrtps */
 [0x52] = X86_OP_GROUP3(sse_unary,  V,x, H,x, W,x, vex4_rep5 p_00_f3), /* 
rsqrtps */
@@ -1026,6 +1035,24 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x76] = X86_OP_ENTRY3(PCMPEQD,V,x, H,x, W,x,  vex4 mmx avx2_256 
p_00_66),
 [0x77] = X86_OP_GROUP0(0F77),
 
+[0x80] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x81] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x82] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x83] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x84] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x85] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x86] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x87] = X86_OP_ENTRYr(Jcc, J,z_f64),
+
+[0x90] = X86_OP_ENTRYw(SETcc, E,b),
+[0x91] = X86_OP_ENTRYw(SETcc, E,b),
+[0x92] = X86_OP_ENTRYw(SETcc, E,b),
+[0x93] = X86_OP_ENTRYw(SETcc, E,b),
+[0x94] = X86_OP_ENTRYw(SETcc, E,b),
+[0x95] = X86_OP_ENTRYw(SETcc, E,b),
+[0x96] = X86_OP_ENTRYw(SETcc, E,b),
+[0x97] = X86_OP_ENTRYw(SETcc, E,b),
+
 [0x28] = X86_OP_ENTRY3(MOVDQ,  V,x,  None,None, W,x, vex1 p_00_66), /* 
MOVAPS */
 [0x29] = X86_OP_ENTRY3(MOVDQ,  W,x,  None,None, V,x, vex1 p_00_66), /* 
MOVAPS */
 [0x2A] = X86_OP_GROUP0(0F2A),
@@ -1038,6 +1065,15 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x38] = X86_OP_GROUP0(0F38),
 [0x3a] = X86_OP_GROUP0(0F3A),
 
+[0x48] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x49] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4a] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4b] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4c] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4d] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4e] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4f] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+
 [0x58] = X86_OP_ENTRY3(VADD,   V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
 [0x59] = X86_OP_ENTRY3(VMUL,   V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
 [0x5a] = X86_OP_GROUP0(0F5A),
@@ -1063,6 +1099,24 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x7e] = X86_OP_GROUP0(0F7E),
 [0x7f] = X86_OP_GROUP0(0F7F),
 
+[0x88] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x89] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8a] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8b] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8c] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8d] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8e] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8f] = X86_OP_ENTRYr(Jcc, J,z_f64),
+
+[0x98] = 

[PULL 16/26] target/i386: move 60-BF opcodes to new decoder

2024-05-07 Thread Paolo Bonzini
Compared to the old decoder, the main differences in translation
are for the little-used ARPL instruction.  IMUL is adjusted a bit
to share more code to produce flags, but is otherwise very similar.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |   3 +
 target/i386/tcg/translate.c  |   9 +-
 target/i386/tcg/decode-new.c.inc | 185 ++
 target/i386/tcg/emit.c.inc   | 323 +++
 4 files changed, 518 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 8ffde8d1cd6..790ad5e1d00 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -48,6 +48,7 @@ typedef enum X86OpType {
 
 /* Custom */
 X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
+X86_TYPE_I_unsigned, /* Immediate, zero-extended */
 X86_TYPE_2op, /* 2-operand RMW instruction */
 X86_TYPE_LoBits, /* encoded in bits 0-2 of the operand + REX.B */
 X86_TYPE_0, /* Hard-coded GPRs (RAX..RDI) */
@@ -165,6 +166,8 @@ typedef enum X86InsnSpecial {
 /* Always locked if it has a memory operand (XCHG) */
 X86_SPECIAL_Locked,
 
+/* Do not apply segment base to effective address */
+X86_SPECIAL_NoSeg,
 /*
  * 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
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index e5672df9b94..4f47c40fb08 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1288,7 +1288,11 @@ static void gen_cmps(DisasContext *s, MemOp ot)
 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_ld_v(s, ot, s->T0, s->A0);
+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);
 
 dshift = gen_compute_Dshift(s, ot);
 gen_op_add_reg(s, s->aflag, R_ESI, dshift);
@@ -3122,6 +3126,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 
 s->pc = s->base.pc_next;
 s->override = -1;
+s->popl_esp_hack = 0;
 #ifdef TARGET_X86_64
 s->rex_r = 0;
 s->rex_x = 0;
@@ -3179,7 +3184,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && b <= 0x5f) {
+if (use_new && b <= 0xbf) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index c6fd7a053bd..55fc0173a41 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -33,6 +33,22 @@
  * ("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.
  *
+ * The manual lists immediate far destinations as Ap (technically an implicit
+ * argument).  The decoder splits them into two immediates, using "Ip" for
+ * the offset part (that comes first in the instruction stream) and "Iw" for
+ * the segment/selector part.  The size of the offset is given by s->dflag
+ * and the instructions are illegal in 64-bit mode, so the choice of "Ip"
+ * is somewhat arbitrary; "Iv" or "Iz" would work just as well.
+ *
+ * Operand types
+ * -
+ *
+ * Immediates are almost always signed or masked away in helpers.  Two
+ * common exceptions are IN/OUT and absolute jumps.  For these, there is
+ * an additional custom operand type "I_unsigned".  Alternatively, the
+ * mask could be applied (and the original sign-extended value would be
+ * optimized away by TCG) in the emitter function.
+ *
  * Vector operands
  * ---
  *
@@ -151,6 +167,8 @@
  */
 #define X86_OP_ENTRYrr(op, op0, s0, op1, s1, ...) \
 X86_OP_ENTRY3(op, None, None, op0, s0, op1, s1, ## __VA_ARGS__)
+#define X86_OP_ENTRYwr(op, op0, s0, op1, s1, ...) \
+X86_OP_ENTRY3(op, op0, s0, None, None, op1, s1, ## __VA_ARGS__)
 #define X86_OP_ENTRY2(op, op0, s0, op1, s1, ...)  \
 X86_OP_ENTRY3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
 #define X86_OP_ENTRYw(op, op0, s0, ...)   \
@@ -163,6 +181,7 @@
 X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__)
 
 #define cpuid(feat) .cpuid = X86_FEAT_##feat,
+#define noseg .special = X86_SPECIAL_NoSeg,
 #define xchg .special = X86_SPECIAL_Locked,
 #define lock .special = X86_SPECIAL_HasLock,
 #define mmx .special = X86_SPECIAL_MMX,
@@ -209,6 +228,8 @@
 #define p_66_f3_f2.valid_prefix = P_66 | P_F3 | P_F2,
 

[PULL 00/26] target/i386 changes for 2024-05-07

2024-05-07 Thread Paolo Bonzini
The following changes since commit e116b92d01c2cd75957a9f8ad1d4932292867b81:

  Merge tag 'qemu-sparc-20240506' of https://github.com/mcayland/qemu into 
staging (2024-05-06 10:19:56 -0700)

are available in the Git repository at:

  https://gitlab.com/bonzini/qemu.git tags/for-upstream

for you to fetch changes up to d4e6d40c36071c287199c072cd5d296091ee5968:

  target/i386: remove duplicate prefix decoding (2024-05-07 08:53:26 +0200)


* target/i386/tcg: conversion of one byte opcodes to table-based decoder


Babu Moger (1):
  target/i386: Fix CPUID encoding of Fn801E_ECX

Paolo Bonzini (25):
  target/i386: use TSTEQ/TSTNE to test low bits
  target/i386: use TSTEQ/TSTNE to check flags
  target/i386: remove mask from CCPrepare
  target/i386: cc_op is not dynamic in gen_jcc1
  target/i386: cleanup cc_op changes for REP/REPZ/REPNZ
  target/i386: pull cc_op update to callers of gen_jmp_rel{,_csize}
  target/i386: extend cc_* when using them to compute flags
  target/i386: do not use s->T0 and s->T1 as scratch registers for CCPrepare
  target/i386: clarify the "reg" argument of functions returning CCPrepare
  target/i386: cleanup *gen_eob*
  target/i386: reintroduce debugging mechanism
  target/i386: move 00-5F opcodes to new decoder
  target/i386: extract gen_far_call/jmp, reordering temporaries
  target/i386: allow instructions with more than one immediate
  target/i386: move 60-BF opcodes to new decoder
  target/i386: generalize gen_movl_seg_T0
  target/i386: move C0-FF opcodes to new decoder (except for x87)
  target/i386: merge and enlarge a few ranges for call to disas_insn_new
  target/i386: move remaining conditional operations to new decoder
  target/i386: move BSWAP to new decoder
  target/i386: port extensions of one-byte opcodes to new decoder
  target/i386: remove now-converted opcodes from old decoder
  target/i386: decode x87 instructions in a separate function
  target/i386: split legacy decoder into a separate function
  target/i386: remove duplicate prefix decoding

 target/i386/cpu.h   |6 +
 target/i386/helper.h|   11 -
 target/i386/tcg/decode-new.h|   23 +-
 target/i386/tcg/shift_helper_template.h.inc |  108 -
 hw/i386/pc.c|1 +
 target/i386/cpu.c   |   18 +-
 target/i386/tcg/int_helper.c|   34 -
 target/i386/tcg/translate.c | 3781 ++-
 target/i386/tcg/decode-new.c.inc|  608 -
 target/i386/tcg/emit.c.inc  | 1595 ++-
 10 files changed, 2989 insertions(+), 3196 deletions(-)
 delete mode 100644 target/i386/tcg/shift_helper_template.h.inc
-- 
2.45.0




[PULL 01/26] target/i386: Fix CPUID encoding of Fn8000001E_ECX

2024-05-07 Thread Paolo Bonzini
From: Babu Moger 

Observed the following failure while booting the SEV-SNP guest and the
guest fails to boot with the smp parameters:
"-smp 192,sockets=1,dies=12,cores=8,threads=2".

qemu-system-x86_64: sev_snp_launch_update: SNP_LAUNCH_UPDATE ret=-5 fw_error=22 
'Invalid parameter'
qemu-system-x86_64: SEV-SNP: CPUID validation failed for function 0x801e, 
index: 0x0.
provided: eax:0x, ebx: 0x0100, ecx: 0x0b00, edx: 0x
expected: eax:0x, ebx: 0x0100, ecx: 0x0300, edx: 0x
qemu-system-x86_64: SEV-SNP: failed update CPUID page

Reason for the failure is due to overflowing of bits used for "Node per
processor" in CPUID Fn801E_ECX. This field's width is 3 bits wide and
can hold maximum value 0x7. With dies=12 (0xB), it overflows and spills
over into the reserved bits. In the case of SEV-SNP, this causes CPUID
enforcement failure and guest fails to boot.

The PPR documentation for CPUID_Fn801E_ECX [Node Identifiers]
=
BitsDescription
31:11   Reserved.

10:8NodesPerProcessor: Node per processor. Read-only.
ValidValues:
Value   Description
0h  1 node per processor.
7h-1h   Reserved.

7:0 NodeId: Node ID. Read-only. Reset: Fixed,XXh.
=

As in the spec, the valid value for "node per processor" is 0 and rest
are reserved.

Looking back at the history of decoding of CPUID_Fn801E_ECX, noticed
that there were cases where "node per processor" can be more than 1. It
is valid only for pre-F17h (pre-EPYC) architectures. For EPYC or later
CPUs, the linux kernel does not use this information to build the L3
topology.

Also noted that the CPUID Function 0x801E_ECX is available only when
TOPOEXT feature is enabled. This feature is enabled only for EPYC(F17h)
or later processors. So, previous generation of processors do not not
enumerate 0x801E_ECX leaf.

There could be some corner cases where the older guests could enable the
TOPOEXT feature by running with -cpu host, in which case legacy guests
might notice the topology change. To address those cases introduced a
new CPU property "legacy-multi-node". It will be true for older machine
types to maintain compatibility. By default, it will be false, so new
decoding will be used going forward.

The documentation is taken from Preliminary Processor Programming
Reference (PPR) for AMD Family 19h Model 11h, Revision B1 Processors 55901
Rev 0.25 - Oct 6, 2022.

Cc: qemu-sta...@nongnu.org
Fixes: 31ada106d891 ("Simplify CPUID_8000_001E for AMD")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537
Reviewed-by: Zhao Liu 
Signed-off-by: Babu Moger 
Message-ID: 
<0ee4b0a8293188a53970a2b0e4f4ef713425055e.1714757834.git.babu.mo...@amd.com>
Signed-off-by: Paolo Bonzini 
---
 target/i386/cpu.h |  6 ++
 hw/i386/pc.c  |  1 +
 target/i386/cpu.c | 18 ++
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 565c7a98c37..1e0d2c915f5 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1994,6 +1994,12 @@ struct ArchCPU {
  */
 bool legacy_cache;
 
+/* Compatibility bits for old machine types.
+ * If true decode the CPUID Function 0x801E_ECX to support multiple
+ * nodes per processor
+ */
+bool legacy_multi_node;
+
 /* Compatibility bits for old machine types: */
 bool enable_cpuid_0xb;
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 08c7de416fd..46235466d7a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -81,6 +81,7 @@
 GlobalProperty pc_compat_9_0[] = {
 { TYPE_X86_CPU, "guest-phys-bits", "0" },
 { "sev-guest", "legacy-vm-type", "true" },
+{ TYPE_X86_CPU, "legacy-multi-node", "on" },
 };
 const size_t pc_compat_9_0_len = G_N_ELEMENTS(pc_compat_9_0);
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 3ef30a765c1..1058b6803fd 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -398,12 +398,9 @@ static void encode_topo_cpuid801e(X86CPU *cpu, 
X86CPUTopoInfo *topo_info,
  * 31:11 Reserved.
  * 10:8 NodesPerProcessor: Node per processor. Read-only. Reset: XXXb.
  *  ValidValues:
- *  Value Description
- *  000b  1 node per processor.
- *  001b  2 nodes per processor.
- *  010b Reserved.
- *  011b 4 nodes per processor.
- *  111b-100b Reserved.
+ *  Value   Description
+ *  0h  1 node per processor.
+ *  7h-1h   Reserved.
  *  7:0 NodeId: Node ID. Read-only. Reset: XXh.
  *
  * NOTE: Hardware reserves 3 bits for number of nodes per processor.
@@ -412,8 +409,12 @@ static void encode_topo_cpuid801e(X86CPU *cpu, 
X86CPUTopoInfo *topo_info,
  * NodeId is 

[PATCH] configure: quote -D options that are passed to meson

2024-05-07 Thread Paolo Bonzini
Ensure that they go through unmodified, instead of removing one layer
of quoting.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Paolo Bonzini 
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index bd85377a6ae..10fbe10ad9c 100755
--- a/configure
+++ b/configure
@@ -764,7 +764,7 @@ for opt do
   --*) meson_option_parse "$opt" "$optarg"
   ;;
   # Pass through -D options to meson
-  -D*) meson_options="$meson_options $opt"
+  -D*) meson_option_add "$opt"
   ;;
   esac
 done
-- 
2.45.0




Re: [PATCH 2/4] kconfig: express dependency of individual boards on libfdt

2024-05-07 Thread Paolo Bonzini
On Tue, May 7, 2024 at 9:48 AM Philippe Mathieu-Daudé  wrote:
>
> On 7/5/24 09:19, Paolo Bonzini wrote:
> > Now that boards are enabled by default and the "CONFIG_FOO=y"
> > entries are gone from configs/devices/, there cannot be any more
> > a conflicts between the default contents of configs/devices/
> > and a failed "depends on" clause.
> >
> > With this change, each individual board or target can express
> > whether it needs FDT.  It can also include it in the
> > build via "select DEVICE_TREE", instead of having each hw/*/meson.build
> > file do it by hand, and this will bring in more components
> > such as CONFIG_GUEST_LOADER.
> >
> > This allows building non-microvm x86 emulators without having
> > libfdt available.
> >
> > Signed-off-by: Paolo Bonzini 
> > ---
> >   meson.build   |  1 +
> >   Kconfig.host  |  3 +++
> >   hw/arm/Kconfig|  5 +
> >   hw/arm/meson.build|  2 +-
> >   hw/core/Kconfig   |  9 -
> >   hw/core/meson.build   |  2 +-
> >   hw/i386/Kconfig   |  3 ++-
> >   hw/loongarch/Kconfig  |  3 ++-
> >   hw/loongarch/meson.build  |  2 +-
> >   hw/mips/Kconfig   |  1 +
> >   hw/mips/meson.build   |  2 +-
> >   hw/openrisc/Kconfig   |  2 ++
> >   hw/openrisc/meson.build   |  4 ++--
> >   hw/ppc/Kconfig| 15 ---
> >   hw/ppc/meson.build|  4 +---
> >   hw/riscv/Kconfig  |  4 
> >   hw/riscv/meson.build  |  2 +-
> >   hw/rx/Kconfig |  3 ++-
> >   hw/xtensa/Kconfig |  1 +
> >   system/meson.build|  2 +-
> >   target/arm/Kconfig|  2 ++
> >   target/microblaze/Kconfig |  1 +
> >   target/openrisc/Kconfig   |  1 +
> >   target/riscv/Kconfig  |  2 ++
> >   24 files changed, 54 insertions(+), 22 deletions(-)
>
>
> > diff --git a/hw/arm/meson.build b/hw/arm/meson.build
> > index 6808135c1f7..aefde0c69a3 100644
> > --- a/hw/arm/meson.build
> > +++ b/hw/arm/meson.build
> > @@ -1,5 +1,5 @@
> >   arm_ss = ss.source_set()
> > -arm_ss.add(files('boot.c'), fdt)
> > +arm_ss.add(files('boot.c'))
>
> Don't we need to add fdt includes path to CPPFLAGS?

Good catch! I thought it'd be done automatically for all dependencies
included in common_ss (system_ss is included in common_ss and lists
fdt as a dependency), but actually it needs a small tweak:

diff --git a/meson.build b/meson.build
index 24502f4ff6a..342df23269d 100644
--- a/meson.build
+++ b/meson.build
@@ -3898,7 +3898,7 @@ foreach target : target_dirs

   target_common = common_ss.apply(config_target, strict: false)
   objects = common_all.extract_objects(target_common.sources())
-  deps = target_common.dependencies()
+  arch_deps += target_common.dependencies()

   target_specific = specific_ss.apply(config_target, strict: false)
   arch_srcs += target_specific.sources()
@@ -3954,7 +3954,7 @@ foreach target : target_dirs
 emulator = executable(exe_name, exe['sources'],
install: true,
c_args: c_args,
-   dependencies: arch_deps + deps + exe['dependencies'],
+   dependencies: arch_deps + exe['dependencies'],
objects: lib.extract_all_objects(recursive: true),
link_depends: [block_syms, qemu_syms],
link_args: link_args,

I'll include it in a v2 once I test it more fully.

Paolo




[PATCH 4/4] configs: disable emulators that require it if libfdt is not found

2024-05-07 Thread Paolo Bonzini
Since boards can express their dependency on libfdt and
system/device_tree.c, only leave TARGET_NEED_FDT if the target has a
hard dependency.

By default, unless --enable-libfdt is passed (in which case the
dependency is mandatory, as usual for --enable-* options) or the
target is mention in --target-list, those emulators will be skipped if
libfdt is not present.

Signed-off-by: Paolo Bonzini 
---
 configs/targets/aarch64-softmmu.mak  |  1 +
 configs/targets/arm-softmmu.mak  |  1 +
 configs/targets/i386-softmmu.mak |  1 -
 configs/targets/loongarch64-softmmu.mak  |  1 +
 configs/targets/microblaze-softmmu.mak   |  1 +
 configs/targets/microblazeel-softmmu.mak |  1 +
 configs/targets/mips64el-softmmu.mak |  1 -
 configs/targets/or1k-softmmu.mak |  1 +
 configs/targets/ppc-softmmu.mak  |  1 -
 configs/targets/ppc64-softmmu.mak|  1 +
 configs/targets/riscv32-softmmu.mak  |  1 +
 configs/targets/riscv64-softmmu.mak  |  1 +
 configs/targets/rx-softmmu.mak   |  1 +
 configs/targets/x86_64-softmmu.mak   |  1 -
 meson.build  | 14 ++
 .gitlab-ci.d/buildtest.yml   |  7 ---
 16 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/configs/targets/aarch64-softmmu.mak 
b/configs/targets/aarch64-softmmu.mak
index 83c22391a69..84cb32dc2f4 100644
--- a/configs/targets/aarch64-softmmu.mak
+++ b/configs/targets/aarch64-softmmu.mak
@@ -3,4 +3,5 @@ TARGET_BASE_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml 
gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml 
gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml 
gdb-xml/arm-m-profile-mve.xml gdb-xml/aarch64-pauth.xml
+# needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/configs/targets/arm-softmmu.mak b/configs/targets/arm-softmmu.mak
index 92c8349b964..bf390b7a8de 100644
--- a/configs/targets/arm-softmmu.mak
+++ b/configs/targets/arm-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=arm
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml 
gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml 
gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
+# needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index d61b5076134..2ac69d5ba37 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,5 +1,4 @@
 TARGET_ARCH=i386
 TARGET_SUPPORTS_MTTCG=y
-TARGET_NEED_FDT=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/i386-32bit.xml
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
index f23780fdd89..84beb19b90a 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -2,4 +2,5 @@ TARGET_ARCH=loongarch64
 TARGET_BASE_ARCH=loongarch
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/loongarch-base32.xml gdb-xml/loongarch-base64.xml 
gdb-xml/loongarch-fpu.xml
+# all boards require libfdt
 TARGET_NEED_FDT=y
diff --git a/configs/targets/microblaze-softmmu.mak 
b/configs/targets/microblaze-softmmu.mak
index e84c0cc7283..eea266d4f3d 100644
--- a/configs/targets/microblaze-softmmu.mak
+++ b/configs/targets/microblaze-softmmu.mak
@@ -1,5 +1,6 @@
 TARGET_ARCH=microblaze
 TARGET_BIG_ENDIAN=y
 TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_XML_FILES=gdb-xml/microblaze-core.xml 
gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/microblazeel-softmmu.mak 
b/configs/targets/microblazeel-softmmu.mak
index 9b688036bd3..77b968acad3 100644
--- a/configs/targets/microblazeel-softmmu.mak
+++ b/configs/targets/microblazeel-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=microblaze
 TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_XML_FILES=gdb-xml/microblaze-core.xml 
gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/mips64el-softmmu.mak 
b/configs/targets/mips64el-softmmu.mak
index 8d9ab3ddc4b..3864daa7364 100644
--- a/configs/targets/mips64el-softmmu.mak
+++ b/configs/targets/mips64el-softmmu.mak
@@ -1,3 +1,2 @@
 TARGET_ARCH=mips64
 TARGET_BASE_ARCH=mips
-TARGET_NEED_FDT=y
diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 432f855a30a..0341cb2a6b3 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,4 +1,5 @@
 TARGET_ARCH=openrisc
 TARGET_SUPPORTS_MTTCG=y
 TARGET_BIG_ENDIAN=y
+# needed by boot.c and all boards
 TARGET_NEED_FDT=y
diff --git a/configs/targets/ppc-softmmu.mak b/configs/targets/ppc-softmmu.mak
index f3ea9c98f75..53120dab41d 100644
--- a/configs/targets/ppc-softmmu.mak
+++ b/configs/targets/ppc-softmmu.mak
@@ -2,4 +2,3 @@ TARGET_ARCH=ppc
 TARGET_BIG_ENDIAN=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_XML_FILES= gdb-xml/power-core.xml gdb-xml/power-fpu.xml 
gdb-xml/power

[PATCH 2/4] kconfig: express dependency of individual boards on libfdt

2024-05-07 Thread Paolo Bonzini
Now that boards are enabled by default and the "CONFIG_FOO=y"
entries are gone from configs/devices/, there cannot be any more
a conflicts between the default contents of configs/devices/
and a failed "depends on" clause.

With this change, each individual board or target can express
whether it needs FDT.  It can also include it in the
build via "select DEVICE_TREE", instead of having each hw/*/meson.build
file do it by hand, and this will bring in more components
such as CONFIG_GUEST_LOADER.

This allows building non-microvm x86 emulators without having
libfdt available.

Signed-off-by: Paolo Bonzini 
---
 meson.build   |  1 +
 Kconfig.host  |  3 +++
 hw/arm/Kconfig|  5 +
 hw/arm/meson.build|  2 +-
 hw/core/Kconfig   |  9 -
 hw/core/meson.build   |  2 +-
 hw/i386/Kconfig   |  3 ++-
 hw/loongarch/Kconfig  |  3 ++-
 hw/loongarch/meson.build  |  2 +-
 hw/mips/Kconfig   |  1 +
 hw/mips/meson.build   |  2 +-
 hw/openrisc/Kconfig   |  2 ++
 hw/openrisc/meson.build   |  4 ++--
 hw/ppc/Kconfig| 15 ---
 hw/ppc/meson.build|  4 +---
 hw/riscv/Kconfig  |  4 
 hw/riscv/meson.build  |  2 +-
 hw/rx/Kconfig |  3 ++-
 hw/xtensa/Kconfig |  1 +
 system/meson.build|  2 +-
 target/arm/Kconfig|  2 ++
 target/microblaze/Kconfig |  1 +
 target/openrisc/Kconfig   |  1 +
 target/riscv/Kconfig  |  2 ++
 24 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/meson.build b/meson.build
index 530f92c0a9c..3ae95215083 100644
--- a/meson.build
+++ b/meson.build
@@ -2986,6 +2986,7 @@ host_kconfig = \
   (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
   (opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
   (x11.found() ? ['CONFIG_X11=y'] : []) + \
+  (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
   (have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
   (have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
   (have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
diff --git a/Kconfig.host b/Kconfig.host
index f6a2a131e6c..17f405004b3 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -23,6 +23,9 @@ config IVSHMEM
 config TPM
 bool
 
+config FDT
+bool
+
 config VHOST_USER
 bool
 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 98c264ed219..8b97683a45e 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -15,6 +15,7 @@ config ARM_VIRT
 select ACPI
 select ARM_SMMUV3
 select GPIO_KEY
+select DEVICE_TREE
 select FW_CFG_DMA
 select PCI_EXPRESS
 select PCI_EXPRESS_GENERIC_BRIDGE
@@ -265,6 +266,7 @@ config SBSA_REF
 default y
 depends on TCG && AARCH64
 imply PCI_DEVICES
+select DEVICE_TREE
 select AHCI
 select ARM_SMMUV3
 select GPIO_KEY
@@ -347,6 +349,7 @@ config VEXPRESS
 bool
 default y
 depends on TCG && ARM
+select DEVICE_TREE
 select A9MPCORE
 select A15MPCORE
 select ARM_MPTIMER
@@ -492,6 +495,7 @@ config XLNX_ZYNQMP_ARM
 select CPU_CLUSTER
 select DDC
 select DPCD
+select DEVICE_TREE
 select SDHCI
 select SSI
 select SSI_M25P80
@@ -509,6 +513,7 @@ config XLNX_VERSAL
 depends on TCG && AARCH64
 select ARM_GIC
 select CPU_CLUSTER
+select DEVICE_TREE
 select PL011
 select CADENCE
 select VIRTIO_MMIO
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 6808135c1f7..aefde0c69a3 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -1,5 +1,5 @@
 arm_ss = ss.source_set()
-arm_ss.add(files('boot.c'), fdt)
+arm_ss.add(files('boot.c'))
 arm_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c'))
 arm_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
 arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c'))
diff --git a/hw/core/Kconfig b/hw/core/Kconfig
index 9397503656d..24411f59306 100644
--- a/hw/core/Kconfig
+++ b/hw/core/Kconfig
@@ -4,8 +4,14 @@ config EMPTY_SLOT
 config PTIMER
 bool
 
+config DEVICE_TREE
+bool
+# fail the build if libfdt not found
+depends on FDT
+
 config FITLOADER
 bool
+depends on DEVICE_TREE
 
 config GENERIC_LOADER
 bool
@@ -14,13 +20,14 @@ config GENERIC_LOADER
 config GUEST_LOADER
 bool
 default y
-depends on TCG
+depends on TCG && DEVICE_TREE
 
 config OR_IRQ
 bool
 
 config PLATFORM_BUS
 bool
+depends on DEVICE_TREE
 
 config REGISTER
 bool
diff --git a/hw/core/meson.build b/hw/core/meson.build
index f20d4143f7a..a3d9bab9f42 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -16,7 +16,7 @@ common_ss.add(files('cpu-common.c'))
 common_ss.add(files('machine-smp.c'))
 system_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
 system_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: 
files('generic-loader.c'))
-system_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: 
files('guest-loader.c'))
+system_ss.a

[PATCH 3/4] hw/xtensa: require libfdt

2024-05-07 Thread Paolo Bonzini
All other boards require libfdt if it can be used (including for example
i386/x86_64), so change the "imply" to "select" and always allow -dtb
in qemu-system-xtensa.

Signed-off-by: Paolo Bonzini 
---
 hw/xtensa/xtfpga.c | 9 -
 hw/xtensa/Kconfig  | 4 ++--
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index f49e6591dc2..955e8867a36 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -356,7 +356,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE,
  strlen(kernel_cmdline) + 1, kernel_cmdline);
 }
-#ifdef CONFIG_FDT
 if (dtb_filename) {
 int fdt_size;
 void *fdt = load_device_tree(dtb_filename, _size);
@@ -373,14 +372,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4 * KiB);
 g_free(fdt);
 }
-#else
-if (dtb_filename) {
-error_report("could not load DTB '%s': "
- "FDT support is not configured in QEMU",
- dtb_filename);
-exit(EXIT_FAILURE);
-}
-#endif
 if (initrd_filename) {
 BpMemInfo initrd_location = { 0 };
 int initrd_size = load_ramdisk(initrd_filename, cur_lowmem,
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
index 8ea283a7a3b..fc5c785cfac 100644
--- a/hw/xtensa/Kconfig
+++ b/hw/xtensa/Kconfig
@@ -14,8 +14,8 @@ config XTENSA_VIRT
 config XTENSA_XTFPGA
 bool
 default y
-depends on XTENSA
-imply DEVICE_TREE
+depends on XTENSA && FDT
+select DEVICE_TREE
 select OPENCORES_ETH
 select PFLASH_CFI01
 select SERIAL
-- 
2.45.0




[PATCH 0/4] express dependency of individual boards on libfdt

2024-05-07 Thread Paolo Bonzini
Just like we have boards that depend on TCG, not all boards in a
target may require libfdt.  Express one by one which boards do,
using Kconfig "depends on" and "select" directives, and use the
result to include system/device_tree.c in the build.

Some binaries do require libfdt altogether.  In a normal build without
--target-list or --enable-libfdt, these binaries will be disabled with a
message printed by meson.

Paolo

Paolo Bonzini (4):
  meson: remove system/internal distinction for libfdt
  kconfig: express dependency of individual boards on libfdt
  hw/xtensa: require libfdt
  configs: disable emulators that require it if libfdt is not found

 configs/targets/aarch64-softmmu.mak  |  1 +
 configs/targets/arm-softmmu.mak  |  1 +
 configs/targets/i386-softmmu.mak |  1 -
 configs/targets/loongarch64-softmmu.mak  |  1 +
 configs/targets/microblaze-softmmu.mak   |  1 +
 configs/targets/microblazeel-softmmu.mak |  1 +
 configs/targets/mips64el-softmmu.mak |  1 -
 configs/targets/or1k-softmmu.mak |  1 +
 configs/targets/ppc-softmmu.mak  |  1 -
 configs/targets/ppc64-softmmu.mak|  1 +
 configs/targets/riscv32-softmmu.mak  |  1 +
 configs/targets/riscv64-softmmu.mak  |  1 +
 configs/targets/rx-softmmu.mak   |  1 +
 configs/targets/x86_64-softmmu.mak   |  1 -
 meson.build  | 82 
 hw/xtensa/xtfpga.c   |  9 ---
 .gitlab-ci.d/buildtest.yml   |  7 +-
 Kconfig.host |  3 +
 hw/arm/Kconfig   |  5 ++
 hw/arm/meson.build   |  2 +-
 hw/core/Kconfig  |  9 ++-
 hw/core/meson.build  |  2 +-
 hw/i386/Kconfig  |  3 +-
 hw/loongarch/Kconfig |  3 +-
 hw/loongarch/meson.build |  2 +-
 hw/mips/Kconfig  |  1 +
 hw/mips/meson.build  |  2 +-
 hw/openrisc/Kconfig  |  2 +
 hw/openrisc/meson.build  |  4 +-
 hw/ppc/Kconfig   | 15 +++--
 hw/ppc/meson.build   |  4 +-
 hw/riscv/Kconfig |  4 ++
 hw/riscv/meson.build |  2 +-
 hw/rx/Kconfig|  3 +-
 hw/xtensa/Kconfig|  3 +-
 meson_options.txt|  6 +-
 scripts/meson-buildoptions.sh|  4 +-
 system/meson.build   |  2 +-
 target/arm/Kconfig   |  2 +
 target/microblaze/Kconfig|  1 +
 target/openrisc/Kconfig  |  1 +
 target/riscv/Kconfig |  2 +
 42 files changed, 112 insertions(+), 87 deletions(-)

-- 
2.45.0




[PATCH 1/4] meson: remove system/internal distinction for libfdt

2024-05-07 Thread Paolo Bonzini
Treat libfdt like slirp and the other dependencies that use --enable-download;
remove the ability to force usage of the subproject.

Signed-off-by: Paolo Bonzini 
---
 meson.build   | 69 +++
 meson_options.txt |  6 +--
 scripts/meson-buildoptions.sh |  4 +-
 3 files changed, 34 insertions(+), 45 deletions(-)

diff --git a/meson.build b/meson.build
index 43da4923721..530f92c0a9c 100644
--- a/meson.build
+++ b/meson.build
@@ -1858,6 +1858,30 @@ if numa.found() and not cc.links('''
   endif
 endif
 
+fdt = not_found
+if get_option('fdt').disable_auto_if(not have_system).allowed()
+  fdt = cc.find_library('fdt', required: false)
+  if fdt.found()
+if not cc.links('''
+  #include 
+  #include 
+  int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
+dependencies: fdt)
+  libfdt_proj = subproject('dtc', required: get_option('fdt'),
+   default_options: ['tools=false',  
'yaml=disabled',
+ 'python=disabled', 
'default_library=static'])
+  fdt = libfdt_proj.get_variable('libfdt_dep')
+endif
+if not fdt.found()
+  if get_option('fdt').enabled()
+error('libfdt found but too old (1.5.1 or newer required)')
+  else
+warning('libfdt found but too old (1.5.1 or newer required)')
+  endif
+endif
+  endif
+endif
+
 rdma = not_found
 if not get_option('rdma').auto() or have_system
   libumad = cc.find_library('ibumad', required: get_option('rdma'))
@@ -2199,6 +2223,7 @@ config_host_data.set('CONFIG_BSD', host_os 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', host_os == 'darwin')
+config_host_data.set('CONFIG_FDT', fdt.found())
 config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
 config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
 config_host_data.set('CONFIG_LIBUDEV', libudev.found())
@@ -3120,6 +3145,10 @@ genh += custom_target('config-poison.h',
   command: [find_program('scripts/make-config-poison.sh'),
 target_configs_h])
 
+if fdt_required.length() > 0 and not fdt.found()
+  error('fdt disabled but required by targets ' + ', '.join(fdt_required))
+endif
+
 ###
 # Subprojects #
 ###
@@ -3130,44 +3159,6 @@ if have_system and vfio_user_server_allowed
   libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
 endif
 
-fdt = not_found
-fdt_opt = get_option('fdt')
-if fdt_required.length() > 0 or fdt_opt == 'enabled'
-  if fdt_opt == 'disabled'
-error('fdt disabled but required by targets ' + ', '.join(fdt_required))
-  endif
-
-  if fdt_opt in ['enabled', 'auto', 'system']
-if get_option('wrap_mode') == 'nodownload'
-  fdt_opt = 'system'
-endif
-fdt = cc.find_library('fdt', required: fdt_opt == 'system')
-if fdt.found() and cc.links('''
-   #include 
-   #include 
-   int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
- dependencies: fdt)
-  fdt_opt = 'system'
-elif fdt_opt == 'system'
-   error('system libfdt requested, but it is too old (1.5.1 or newer 
required)')
-else
-  fdt_opt = 'internal'
-  fdt = not_found
-endif
-  endif
-  if not fdt.found()
-assert(fdt_opt == 'internal')
-libfdt_proj = subproject('dtc', required: true,
- default_options: ['tools=false',  'yaml=disabled',
-   'python=disabled', 
'default_library=static'])
-fdt = libfdt_proj.get_variable('libfdt_dep')
-  endif
-else
-  fdt_opt = 'disabled'
-endif
-
-config_host_data.set('CONFIG_FDT', fdt.found())
-
 vhost_user = not_found
 if host_os == 'linux' and have_vhost_user
   libvhost_user = subproject('libvhost-user')
@@ -4411,7 +4402,7 @@ summary_info += {'Linux AIO support': libaio}
 summary_info += {'Linux io_uring support': linux_io_uring}
 summary_info += {'ATTR/XATTR support': libattr}
 summary_info += {'RDMA support':  rdma}
-summary_info += {'fdt support':   fdt_opt == 'disabled' ? false : fdt_opt}
+summary_info += {'fdt support':   fdt}
 summary_info += {'libcap-ng support': libcap_ng}
 summary_info += {'bpf support':   libbpf}
 summary_info += {'rbd support':   rbd}
diff --git a/meson_options.txt b/meson_options.txt
index adc77bae0cd..90902c19d1c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -308,9 +308,9 @@ option('vduse_blk_export', type: 'feature', value: 'auto',
 
 option('capstone', type: 'feature', value: 'auto',
description: 'Whether and how to find the capstone library')
-option('fdt', type: 'combo', value: 'auto',
-   choices: ['disabled', 'enabled', 'auto', 'system', 'internal'],
-   description: 'Whether and how to find the libfdt library')
+option('fdt', type: 'f

Re: [PATCH v2 05/25] target/i386: cleanup cc_op changes for REP/REPZ/REPNZ

2024-05-06 Thread Paolo Bonzini
On Mon, May 6, 2024 at 6:08 PM Richard Henderson
 wrote:
> > -gen_update_cc_op(s);
> >   l2 = gen_jz_ecx_string(s);
> > +/*
> > + * Only one iteration is done at a time, so there is
> > + * no control flow junction here and cc_op is never dynamic.
> > + */
> >   fn(s, ot);
> >   gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
> > -gen_update_cc_op(s);
> >   gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);
> >   if (s->repz_opt) {
> >   gen_op_jz_ecx(s, l2);
>
> Ok, but only because gen_jcc1 does the gen_update_cc_op.  The comment is 
> neither correct
> nor necessary.

Yeah, it's true that gen_jcc1 does the update. On the other hand,
there are two different kinds of cc_op updates:

1) at branches, if you know that only one of the sides might write
cc_op - so you ensure it's up-to-date before the branch - and set
CC_OP_DYNAMIC at the junction. Same if you have movcond instead of a
branch.

2) at end of translation block, to spill the value lazily (because in
the middle of the TB we are able to restore it from insn data). With
these patches there is never a need to do this, because gen_jmp_rel()
and gen_jmp_rel_csize() take care of it.

The comment deals with the former, the removal with the latter.

The idea of the comment is that after SCAS/CMPS you have CC_OP_SUB*,
so in principle you may expect that you need to set CC_OP_DYNAMIC
explicitly at the end of a REPZ/REPNZ, which is where the CX != 0 and
CX == 0 paths join. But this is not necessary, because there is
nothing after that instruction - the translation block ends.

So I guess the comment could instead be placed at the end of the function?

/*
 * Only one iteration is done at a time, so the translation
 * block has ended unconditionally at this point and there
 * is no control flow junction - no need to set CC_OP_DYNAMIC.
 */

What do you think?

Paolo




Re: [PATCH 0/3] Make it possible to compile the x86 binaries without FDC

2024-05-06 Thread Paolo Bonzini
On Thu, Apr 25, 2024 at 8:43 PM Thomas Huth  wrote:
> OTOH, it seems
> to work fine, and the FDC is only disabled when it is not available
> in the binary, so I hope this patch is fine, too.

We do the same for parallel so i think it should be fine---definitely
for -nodefaults, and I'd say in general too.  The CMOS byte already
has a way to communicate no-floppy (0, see cmos_get_fd_drive_type).

Paolo




Re: [PATCH v2] qemu-options: Deprecate "-runas" and introduce "-run-with user=..." instead

2024-05-06 Thread Paolo Bonzini
On Mon, May 6, 2024 at 1:21 PM Thomas Huth  wrote:
>
> The old "-runas" option has the disadvantage that it is not visible
> in the QAPI schema, so it is not available via the normal introspection
> mechanisms. We've recently introduced the "-run-with" option for exactly
> this purpose, which is meant to handle the options that affect the
> runtime behavior. Thus let's introduce a "user=..." parameter here now
> and deprecate the old "-runas" option.

No need to deprecate it, there are other shortcut options that are
just a couple lines of code to implement:

case QEMU_OPTION_watchdog_action: {
opts = qemu_opts_create(qemu_find_opts("action"),
NULL, 0, _abort);
qemu_opt_set(opts, "watchdog", optarg, _abort);
break;

However that would be a larger patch, basically moving all of the
--run-with handling to qemu_process_early_options() (and, as an aside,
setting .merge_lists = true in qemu_run_with_opts).

No objections to your patch, but also no objections to cleaning all of
--run-with; I should have caught it and proposed the shortcut options
when it was introduced or when --chroot was removed.

Paolo

>  if (!os_set_runas(optarg)) {
>  error_report("User \"%s\" doesn't exist"
>   " (and is not :)",
> @@ -3612,6 +3617,16 @@ void qemu_init(int argc, char **argv)
>  if (str) {
>  os_set_chroot(str);
>  }
> +str = qemu_opt_get(opts, "user");
> +if (str) {
> +if (!os_set_runas(str)) {
> +error_report("User \"%s\" doesn't exist"
> + " (and is not :)",
> + optarg);
> +exit(1);
> +}
> +}
> +
>  break;
>  }
>  #endif /* CONFIG_POSIX */
> diff --git a/qemu-options.hx b/qemu-options.hx
> index cf61f6b863..3031479a15 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -4824,7 +4824,8 @@ DEF("runas", HAS_ARG, QEMU_OPTION_runas, \
>  SRST
>  ``-runas user``
>  Immediately before starting guest execution, drop root privileges,
> -switching to the specified user.
> +switching to the specified user. This option is deprecated, use
> +``-run-with user=...`` instead.
>  ERST
>
>  DEF("prom-env", HAS_ARG, QEMU_OPTION_prom_env,
> @@ -4990,13 +4991,15 @@ DEF("qtest-log", HAS_ARG, QEMU_OPTION_qtest_log, "", 
> QEMU_ARCH_ALL)
>
>  #ifdef CONFIG_POSIX
>  DEF("run-with", HAS_ARG, QEMU_OPTION_run_with,
> -"-run-with [async-teardown=on|off][,chroot=dir]\n"
> +"-run-with [async-teardown=on|off][,chroot=dir][user=username|uid:gid]\n"
>  "Set miscellaneous QEMU process lifecycle options:\n"
>  "async-teardown=on enables asynchronous teardown (Linux 
> only)\n"
> -"chroot=dir chroot to dir just before starting the VM\n",
> +"chroot=dir chroot to dir just before starting the VM\n"
> +"user=username switch to the specified user before 
> starting the VM\n"
> +"user=uid:gid dito, but use specified user-ID and 
> group-ID instead\n",
>  QEMU_ARCH_ALL)
>  SRST
> -``-run-with [async-teardown=on|off][,chroot=dir]``
> +``-run-with [async-teardown=on|off][,chroot=dir][user=username|uid:gid]``
>  Set QEMU process lifecycle options.
>
>  ``async-teardown=on`` enables asynchronous teardown. A new process called
> @@ -5013,6 +5016,10 @@ SRST
>  ``chroot=dir`` can be used for doing a chroot to the specified directory
>  immediately before starting the guest execution. This is especially 
> useful
>  in combination with -runas.
> +
> +``user=username`` or ``user=uid:gid`` can be used to drop root privileges
> +by switching to the specified user (via username) or user and group
> +(via uid:gid) immediately before starting guest execution.
>  ERST
>  #endif
>
> --
> 2.45.0
>M




Call for Presentations: KVM Forum 2024

2024-05-06 Thread Paolo Bonzini

###
KVM Forum 2024
September 22-23, 2024
Brno, Czech Republic
https://kvm-forum.qemu.org/
###

KVM Forum is an annual event that presents a rare opportunity for
developers and users to discuss the state of Linux virtualization
technology and plan for the challenges ahead. Sessions include updates
on the state of the KVM virtualization stack, planning for the future,
and opportunities for attendees to collaborate in "birds of a feather"
(BoF) sessions.

This year's event will be held in Brno, Czechia on September 22-23, 2024.
The location should also be easy to reach for attendees of Linux Plumbers
Conference 2024!


CALL FOR PRESENTATIONS
==

We encourage you to submit presentations via Pretalx at
https://kvm-forum.qemu.org/2024/cfp. Suggested topics include:

* Scalability and Optimization

* Hardening and security

* Confidential computing

* Testing

* KVM and the Linux Kernel:
   * New Features and Ports
   * Device Passthrough: VFIO, mdev, vDPA
   * Network Virtualization
   * Virtio and vhost

* Virtual Machine Monitors and Management:
   * VMM Implementation: APIs, Live Migration, Performance Tuning, etc.
   * Multi-process VMMs: vhost-user, vfio-user, QEMU Storage Daemon
   * QEMU without KVM: Hypervisor.framework and other hypervisors
   * Managing KVM: Libvirt, KubeVirt, Kata Containers

* Emulation:
   * New Devices, Boards and Architectures
   * CPU Emulation and Binary Translation

All presentation slots will be 25 minutes + 5 minutes for questions.


IMPORTANT DATES
===

The deadline for submitting presentations is June 8, 2024 - 11:59 PM CEST.

Accepted speakers will be notified on July 5, 2024.


ATTENDING KVM FORUM
===

Admission to KVM Forum costs $75. You can get your ticket at

https://kvm-forum.qemu.org/2024/register/

Admission is free for accepted speakers.

The conference will be held at Hotel International, which is
within walking distance from the train station:

HOTEL INTERNATIONAL
Husova 16
60200 Brno-střed
Czechia

Special room prices are available at the venue for attendees
of KVM Forum. More information will be available soon at
https://kvm-forum.qemu.org/location/.

We are committed to fostering an open and welcoming environment at our
conference. Participants are expected to abide by our code of conduct
and media policy:

https://kvm-forum.qemu.org/coc/
https://kvm-forum.qemu.org/media-policy/


GETTING TO BRNO
===

Brno has a small international airport with flights from London
(Stansted) and other European cities.

Other nearby airports include Vienna, Bratislava and Prague. Travelling
to Brno is easiest from Vienna Schwechat Airport, from where there are
direct buses operated by RegioJet:

Attendees of the Linux Plumbers Conference can travel from Vienna to
Brno by train on Saturday, September 21.

If you need a visa invitation letter, please reach out to the organizers
at kvm-forum-2024...@redhat.com.


CONTACTS


Reach out to us should you have any questions. The program committee may
be contacted as a group via email: kvm-forum-2024...@redhat.com.




[qemu-web PATCH] blog: KVM Forum 2024 CFP

2024-05-06 Thread Paolo Bonzini
Add a new post linking to the KVM Forum 2024 Call for Presentations.
Thanks to Stefan Hajnoczi for providing a draft of this post!

Cc: Stefan Hajnoczi 
Signed-off-by: Paolo Bonzini 
---
 _posts/2024-05-06-kvm-forum-cfp.md | 36 ++
 1 file changed, 36 insertions(+)
 create mode 100644 _posts/2024-05-06-kvm-forum-cfp.md

diff --git a/_posts/2024-05-06-kvm-forum-cfp.md 
b/_posts/2024-05-06-kvm-forum-cfp.md
new file mode 100644
index 000..23398fe
--- /dev/null
+++ b/_posts/2024-05-06-kvm-forum-cfp.md
@@ -0,0 +1,36 @@
+---
+layout: post
+title:  "KVM Forum 2024: Call for presentations"
+date:   2024-05-06 07:00:00 +0100
+categories: [presentations, conferences]
+---
+
+The [KVM Forum 2024](https://kvm-forum.qemu.org/2024/) conference will take
+place in Brno, Czech Republic on September 22-23, 2024. KVM Forum brings
+together the Linux virtualization community, especially around the KVM stack,
+including QEMU and other virtual machine monitors.
+
+The Call for Presentations is open until June 1, 2024. You are invited to
+submit presentation proposals via the [KVM Forum CfP
+page](https://kvm-forum.org/2024/cfp). All presentation slots will be
+25 minutes + 5 minutes for questions.
+
+Suggested topics include:
+
+* Scalability and Optimization
+* Hardening and security
+* Confidential computing
+* Testing
+* KVM and the Linux Kernel
+  * New Features and Architecture Ports
+  * Device Passthrough: VFIO, mdev, vDPA
+  * Network Virtualization
+  * Virtio and vhost
+* Virtual Machine Monitors and Management
+  * VMM Implementation: APIs, Live Migration, Performance Tuning, etc.
+  * Multi-process VMMs: vhost-user, vfio-user, QEMU Storage Daemon, SPDK
+  * QEMU without KVM: Hypervisor.framework, Windows Hypervisor Platform, etc.
+  * Managing KVM: Libvirt, KubeVirt, Kata Containers
+* Emulation
+  * New Devices, Boards and Architectures
+  * CPU Emulation and Binary Translation
-- 
2.45.0




[PATCH v2 17/25] target/i386: move C0-FF opcodes to new decoder (except for x87)

2024-05-06 Thread Paolo Bonzini
The shift instructions are rewritten instead of reusing code from the old
decoder.  Rotates use CC_OP_ADCOX more extensively and generally rely
more on the optimizer, so that the code generators are shared between
the immediate-count and variable-count cases.

In particular, this makes gen_RCL and gen_RCR pretty efficient for the
count == 1 case, which becomes (apart from a few extra movs) something like:

  (compute_cc_all if needed)
  // save old value for OF calculation
  mov cc_src2, T0
  // the bulk of RCL is just this!
  deposit T0, cc_src, T0, 1, TARGET_LONG_BITS - 1
  // compute carry
  shr cc_dst, cc_src2, length - 1
  and cc_dst, cc_dst, 1
  // compute overflow
  xor cc_src2, cc_src2, T0
  extract cc_src2, cc_src2, length - 1, 1

32-bit MUL and IMUL are also slightly more efficient on 64-bit hosts.

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |1 +
 target/i386/tcg/translate.c  |   23 +-
 target/i386/tcg/decode-new.c.inc |  142 +
 target/i386/tcg/emit.c.inc   | 1014 +-
 4 files changed, 1169 insertions(+), 11 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 790ad5e1d00..77bb31eb143 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -89,6 +89,7 @@ typedef enum X86OpSize {
 X86_SIZE_x,  /* 128/256-bit, based on operand size */
 X86_SIZE_y,  /* 32/64-bit, based on operand size */
 X86_SIZE_z,  /* 16-bit for 16-bit operand size, else 32-bit */
+X86_SIZE_z_f64,  /* 32-bit for 32-bit operand size or 64-bit mode, else 
16-bit */
 
 /* Custom */
 X86_SIZE_d64,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 708fe023224..79b6e2760fe 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -38,6 +38,9 @@
 #include "exec/helper-info.c.inc"
 #undef  HELPER_H
 
+/* Fixes for Windows namespace pollution.  */
+#undef IN
+#undef OUT
 
 #define PREFIX_REPZ   0x01
 #define PREFIX_REPNZ  0x02
@@ -2488,14 +2491,24 @@ static inline int insn_const_size(MemOp ot)
 }
 }
 
+static void gen_conditional_jump_labels(DisasContext *s, target_long diff,
+TCGLabel *not_taken, TCGLabel *taken)
+{
+if (not_taken) {
+gen_set_label(not_taken);
+}
+gen_jmp_rel_csize(s, 0, 1);
+
+gen_set_label(taken);
+gen_jmp_rel(s, s->dflag, diff, 0);
+}
+
 static void gen_jcc(DisasContext *s, int b, int diff)
 {
 TCGLabel *l1 = gen_new_label();
 
 gen_jcc1(s, b, l1);
-gen_jmp_rel_csize(s, 0, 1);
-gen_set_label(l1);
-gen_jmp_rel(s, s->dflag, diff, 0);
+gen_conditional_jump_labels(s, diff, NULL, l1);
 }
 
 static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src)
@@ -2752,7 +2765,7 @@ static void gen_unknown_opcode(CPUX86State *env, 
DisasContext *s)
 
 /* an interrupt is different from an exception because of the
privilege checks */
-static void gen_interrupt(DisasContext *s, int intno)
+static void gen_interrupt(DisasContext *s, uint8_t intno)
 {
 gen_update_cc_op(s);
 gen_update_eip_cur(s);
@@ -3183,7 +3196,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && b <= 0xbf) {
+if (use_new && (b < 0xd8 || b >= 0xe0)) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 55fc0173a41..a47ecab6dd4 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -135,6 +135,8 @@
 ## __VA_ARGS__\
 }
 
+#define X86_OP_GROUP1(op, op0, s0, ...)   \
+X86_OP_GROUP3(op, op0, s0, 2op, s0, None, None, ## __VA_ARGS__)
 #define X86_OP_GROUP2(op, op0, s0, op1, s1, ...)  \
 X86_OP_GROUP3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
 #define X86_OP_GROUPw(op, op0, s0, ...)   \
@@ -1174,6 +1176,83 @@ static void decode_group1A(DisasContext *s, CPUX86State 
*env, X86OpEntry *entry,
 }
 }
 
+static void decode_group2(DisasContext *s, CPUX86State *env, X86OpEntry 
*entry, uint8_t *b)
+{
+static const X86GenFunc group2_gen[8] = {
+gen_ROL, gen_ROR, gen_RCL, gen_RCR,
+gen_SHL, gen_SHR, gen_SHL /* SAL, undocumented */, gen_SAR,
+};
+int op = (get_modrm(s, env) >> 3) & 7;
+entry->gen = group2_gen[op];
+if (op == 7) {
+entry->special = X86_SPECIAL_SExtT0;
+} else {
+entry->special = X86_SPECIAL_ZExtT0;
+}
+}
+
+static void decode_group3(DisasContext *s, CPUX86State *env, X86OpEntry 
*entry, uint8_t *b)
+{
+static const X86OpEntry opcodes_grp3[16] = {
+/* 0xf6 */
+[0x00] = X86_OP_ENTRYrr(AND, E,b, I,b),
+[0x02] = X86_O

[PATCH v2 15/25] target/i386: move 60-BF opcodes to new decoder

2024-05-06 Thread Paolo Bonzini
Compared to the old decoder, the main differences in translation
are for the little-used ARPL instruction.  IMUL is adjusted a bit
to share more code to produce flags, but is otherwise very similar.

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |   3 +
 target/i386/tcg/translate.c  |   9 +-
 target/i386/tcg/decode-new.c.inc | 185 ++
 target/i386/tcg/emit.c.inc   | 323 +++
 4 files changed, 518 insertions(+), 2 deletions(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 8ffde8d1cd6..790ad5e1d00 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -48,6 +48,7 @@ typedef enum X86OpType {
 
 /* Custom */
 X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
+X86_TYPE_I_unsigned, /* Immediate, zero-extended */
 X86_TYPE_2op, /* 2-operand RMW instruction */
 X86_TYPE_LoBits, /* encoded in bits 0-2 of the operand + REX.B */
 X86_TYPE_0, /* Hard-coded GPRs (RAX..RDI) */
@@ -165,6 +166,8 @@ typedef enum X86InsnSpecial {
 /* Always locked if it has a memory operand (XCHG) */
 X86_SPECIAL_Locked,
 
+/* Do not apply segment base to effective address */
+X86_SPECIAL_NoSeg,
 /*
  * 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
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4069bd4f125..8f633814586 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1288,7 +1288,11 @@ static void gen_cmps(DisasContext *s, MemOp ot)
 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_ld_v(s, ot, s->T0, s->A0);
+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);
 
 dshift = gen_compute_Dshift(s, ot);
 gen_op_add_reg(s, s->aflag, R_ESI, dshift);
@@ -3121,6 +3125,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 
 s->pc = s->base.pc_next;
 s->override = -1;
+s->popl_esp_hack = 0;
 #ifdef TARGET_X86_64
 s->rex_r = 0;
 s->rex_x = 0;
@@ -3178,7 +3183,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && b <= 0x5f) {
+if (use_new && b <= 0xbf) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index c6fd7a053bd..55fc0173a41 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -33,6 +33,22 @@
  * ("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.
  *
+ * The manual lists immediate far destinations as Ap (technically an implicit
+ * argument).  The decoder splits them into two immediates, using "Ip" for
+ * the offset part (that comes first in the instruction stream) and "Iw" for
+ * the segment/selector part.  The size of the offset is given by s->dflag
+ * and the instructions are illegal in 64-bit mode, so the choice of "Ip"
+ * is somewhat arbitrary; "Iv" or "Iz" would work just as well.
+ *
+ * Operand types
+ * -
+ *
+ * Immediates are almost always signed or masked away in helpers.  Two
+ * common exceptions are IN/OUT and absolute jumps.  For these, there is
+ * an additional custom operand type "I_unsigned".  Alternatively, the
+ * mask could be applied (and the original sign-extended value would be
+ * optimized away by TCG) in the emitter function.
+ *
  * Vector operands
  * ---
  *
@@ -151,6 +167,8 @@
  */
 #define X86_OP_ENTRYrr(op, op0, s0, op1, s1, ...) \
 X86_OP_ENTRY3(op, None, None, op0, s0, op1, s1, ## __VA_ARGS__)
+#define X86_OP_ENTRYwr(op, op0, s0, op1, s1, ...) \
+X86_OP_ENTRY3(op, op0, s0, None, None, op1, s1, ## __VA_ARGS__)
 #define X86_OP_ENTRY2(op, op0, s0, op1, s1, ...)  \
 X86_OP_ENTRY3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
 #define X86_OP_ENTRYw(op, op0, s0, ...)   \
@@ -163,6 +181,7 @@
 X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__)
 
 #define cpuid(feat) .cpuid = X86_FEAT_##feat,
+#define noseg .special = X86_SPECIAL_NoSeg,
 #define xchg .special = X86_SPECIAL_Locked,
 #define lock .special = X86_SPECIAL_HasLock,
 #define mmx .special = X86_SPECIAL_MMX,
@@ -209,6 +228,8 @@
 #define p_66_f3_f2.valid_prefix = P_66 | P_F3 | P_F2,
 #define p_00_66_f3_f2 .vali

[PATCH v2 05/25] target/i386: cleanup cc_op changes for REP/REPZ/REPNZ

2024-05-06 Thread Paolo Bonzini
gen_update_cc_op must be called before control flow splits.  Do it
where the jump on ECX!=0 is translated.

On the other hand, remove the call before gen_jcc1, which takes care of
it already, and explain why REPZ/REPNZ need not use CC_OP_DYNAMIC---the
translation block ends before any control-flow-dependent cc_op could
be observed.

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3f1d2858fc9..6b766f5dd3f 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1242,11 +1242,15 @@ static inline void gen_jcc1(DisasContext *s, int b, 
TCGLabel *l1)
 }
 
 /* XXX: does not work with gdbstub "ice" single step - not a
-   serious problem */
+   serious problem.  The caller can jump to the returned label
+   to stop the REP but, if the flags have changed, it has to call
+   gen_update_cc_op before doing so.  */
 static TCGLabel *gen_jz_ecx_string(DisasContext *s)
 {
 TCGLabel *l1 = gen_new_label();
 TCGLabel *l2 = gen_new_label();
+
+gen_update_cc_op(s);
 gen_op_jnz_ecx(s, l1);
 gen_set_label(l2);
 gen_jmp_rel_csize(s, 0, 1);
@@ -1342,7 +1346,6 @@ static void gen_repz(DisasContext *s, MemOp ot,
  void (*fn)(DisasContext *s, MemOp ot))
 {
 TCGLabel *l2;
-gen_update_cc_op(s);
 l2 = gen_jz_ecx_string(s);
 fn(s, ot);
 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
@@ -1364,11 +1367,13 @@ static void gen_repz2(DisasContext *s, MemOp ot, int nz,
   void (*fn)(DisasContext *s, MemOp ot))
 {
 TCGLabel *l2;
-gen_update_cc_op(s);
 l2 = gen_jz_ecx_string(s);
+/*
+ * Only one iteration is done at a time, so there is
+ * no control flow junction here and cc_op is never dynamic.
+ */
 fn(s, ot);
 gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
-gen_update_cc_op(s);
 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);
 if (s->repz_opt) {
 gen_op_jz_ecx(s, l2);
-- 
2.45.0




[PATCH v2 21/25] target/i386: port extensions of one-byte opcodes to new decoder

2024-05-06 Thread Paolo Bonzini
A few two-byte opcodes are simple extensions of existing one-byte opcodes;
they are easy to decode and need no change to emit.c.inc.  Port them to
the new decoder.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |  1 +
 target/i386/tcg/translate.c  |  4 
 target/i386/tcg/decode-new.c.inc | 31 +++
 target/i386/tcg/emit.c.inc   | 15 +++
 4 files changed, 51 insertions(+)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index cd7ceca21e8..2ea06b44787 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -47,6 +47,7 @@ typedef enum X86OpType {
 X86_TYPE_Y, /* string destination */
 
 /* Custom */
+X86_TYPE_EM, /* modrm byte selects an ALU memory operand */
 X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
 X86_TYPE_I_unsigned, /* Immediate, zero-extended */
 X86_TYPE_2op, /* 2-operand RMW instruction */
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 87ecf082316..14417b961ce 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3208,6 +3208,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #endif
 if (use_new &&
 ((b >= 0x138 && b <= 0x19f) ||
+ (b & ~9) == 0x1a0 ||
+ b == 0x1af || b == 0x1b2 ||
+ (b >= 0x1b4 && b <= 0x1b7) ||
+ b == 0x1be || b == 0x1bf || b == 0x1c3 ||
  (b >= 0x1c8 && b <= 0x1cf))) {
 disas_insn_new(s, cpu, b);
 return true;
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index e65fa208a43..8311b479846 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -43,6 +43,12 @@
  * Operand types
  * -
  *
+ * For memory-only operands, if the emitter functions wants to rely on
+ * generic load and writeback, the decoder needs to know the type of the
+ * operand.  Therefore, M is often replaced by the more specific EM and WM
+ * (respectively selecting an ALU operand, like the operand type E, or a
+ * vector operand like the operand type W).
+ *
  * Immediates are almost always signed or masked away in helpers.  Two
  * common exceptions are IN/OUT and absolute jumps.  For these, there is
  * an additional custom operand type "I_unsigned".  Alternatively, the
@@ -1047,6 +1053,9 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x96] = X86_OP_ENTRYw(SETcc, E,b),
 [0x97] = X86_OP_ENTRYw(SETcc, E,b),
 
+[0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
+[0xa1] = X86_OP_ENTRYw(POP, FS, w),
+
 [0x28] = X86_OP_ENTRY3(MOVDQ,  V,x,  None,None, W,x, vex1 p_00_66), /* 
MOVAPS */
 [0x29] = X86_OP_ENTRY3(MOVDQ,  W,x,  None,None, V,x, vex1 p_00_66), /* 
MOVAPS */
 [0x2A] = X86_OP_GROUP0(0F2A),
@@ -,9 +1120,26 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x9e] = X86_OP_ENTRYw(SETcc, E,b),
 [0x9f] = X86_OP_ENTRYw(SETcc, E,b),
 
+[0xa8] = X86_OP_ENTRYr(PUSH,   GS, w),
+[0xa9] = X86_OP_ENTRYw(POP,GS, w),
 [0xae] = X86_OP_GROUP0(group15),
+/*
+ * It's slightly more efficient to put Ev operand in T0 and allow gen_IMUL3
+ * to assume sextT0.  Multiplication is commutative anyway.
+ */
+[0xaf] = X86_OP_ENTRY3(IMUL3,  G,v, E,v, 2op,v, sextT0),
+
+[0xb2] = X86_OP_ENTRY3(LSS,G,v, M,p, None, None),
+[0xb4] = X86_OP_ENTRY3(LFS,G,v, M,p, None, None),
+[0xb5] = X86_OP_ENTRY3(LGS,G,v, M,p, None, None),
+[0xb6] = X86_OP_ENTRY3(MOV,G,v, E,b, None, None, zextT0), /* MOVZX */
+[0xb7] = X86_OP_ENTRY3(MOV,G,v, E,w, None, None, zextT0), /* MOVZX */
+
+[0xbe] = X86_OP_ENTRY3(MOV,G,v, E,b, None, None, sextT0), /* MOVSX */
+[0xbf] = X86_OP_ENTRY3(MOV,G,v, E,w, None, None, sextT0), /* MOVSX */
 
 [0xc2] = X86_OP_ENTRY4(VCMP,   V,x, H,x, W,x,   vex2_rep3 
p_00_66_f3_f2),
+[0xc3] = X86_OP_ENTRY3(MOV,EM,y,G,y, None,None, cpuid(SSE2)), /* 
MOVNTI */
 [0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w,   vex5 mmx p_00_66),
 [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b,   vex5 mmx p_00_66),
 [0xc6] = X86_OP_ENTRY4(VSHUF,  V,x, H,x, W,x,   vex4 p_00_66),
@@ -1815,8 +1841,13 @@ static bool decode_op(DisasContext *s, CPUX86State *env, 
X86DecodedInsn *decode,
 
 case X86_TYPE_WM:  /* modrm byte selects an XMM/YMM memory operand */
 op->unit = X86_OP_SSE;
+goto get_modrm_mem;
+
+case X86_TYPE_EM:  /* modrm byte selects an ALU memory operand */
+op->unit = X86_OP_INT;
 /* fall through */
 case X86_TYPE_M:  /* modrm byte selects a memory operand */
+get_modrm_mem:
 modrm = get_modrm(s, env);
 if ((modrm >> 6) == 3) {
 return false;
diff --git a/target/i386/tcg/emit.c.inc b/target/i38

[PATCH v2 09/25] target/i386: clarify the "reg" argument of functions returning CCPrepare

2024-05-06 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 2cd7868d596..7efd12cbe7e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -937,7 +937,7 @@ static CCPrepare gen_prepare_sign_nz(TCGv src, MemOp size)
 }
 }
 
-/* compute eflags.C to reg */
+/* compute eflags.C, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
 {
 MemOp size;
@@ -1008,7 +1008,7 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* compute eflags.P to reg */
+/* compute eflags.P, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
 {
 gen_compute_eflags(s);
@@ -1016,7 +1016,7 @@ static CCPrepare gen_prepare_eflags_p(DisasContext *s, 
TCGv reg)
  .imm = CC_P };
 }
 
-/* compute eflags.S to reg */
+/* compute eflags.S, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
 {
 switch (s->cc_op) {
@@ -1040,7 +1040,7 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* compute eflags.O to reg */
+/* compute eflags.O, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
 {
 switch (s->cc_op) {
@@ -1060,7 +1060,7 @@ static CCPrepare gen_prepare_eflags_o(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* compute eflags.Z to reg */
+/* compute eflags.Z, trying to store it in reg if not NULL */
 static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
 {
 switch (s->cc_op) {
@@ -1090,8 +1090,9 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, 
TCGv reg)
 }
 }
 
-/* perform a conditional store into register 'reg' according to jump opcode
-   value 'b'. In the fast case, T0 is guaranteed not to be used. */
+/* return how to compute jump opcode 'b'.  'reg' can be clobbered
+ * if needed; it may be used for CCPrepare.reg if that will
+ * provide more freedom in the translation of a subsequent setcond. */
 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
 {
 int inv, jcc_op, cond;
-- 
2.45.0




[PATCH v2 19/25] target/i386: move remaining conditional operations to new decoder

2024-05-06 Thread Paolo Bonzini
Move long-displacement Jcc, SETcc and CMOVcc to the new decoder.
While filling in the tables makes the code seem longer, the new
emitters are all just one line of code.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/decode-new.h |  1 +
 target/i386/tcg/translate.c  |  2 +-
 target/i386/tcg/decode-new.c.inc | 56 
 target/i386/tcg/emit.c.inc   | 10 ++
 4 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 77bb31eb143..cd7ceca21e8 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -106,6 +106,7 @@ typedef enum X86CPUIDFeature {
 X86_FEAT_AVX2,
 X86_FEAT_BMI1,
 X86_FEAT_BMI2,
+X86_FEAT_CMOV,
 X86_FEAT_CMPCCXADD,
 X86_FEAT_F16C,
 X86_FEAT_FMA,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index b94d9504090..a80021930bf 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3206,7 +3206,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && 0) {
+if (use_new && (b >= 0x138 && b <= 0x19f)) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index a47ecab6dd4..7528e9e4f07 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -993,6 +993,15 @@ static const X86OpEntry opcodes_0F[256] = {
 /* Incorrectly listed as Mq,Vq in the manual */
 [0x17] = X86_OP_ENTRY3(VMOVHPx_st,  M,q, None,None, V,dq, vex5 p_00_66),
 
+[0x40] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x41] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x42] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x43] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x44] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x45] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x46] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x47] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+
 [0x50] = X86_OP_ENTRY3(MOVMSK, G,y, None,None, U,x, vex7 p_00_66),
 [0x51] = X86_OP_GROUP3(sse_unary,  V,x, H,x, W,x, vex2_rep3 
p_00_66_f3_f2), /* sqrtps */
 [0x52] = X86_OP_GROUP3(sse_unary,  V,x, H,x, W,x, vex4_rep5 p_00_f3), /* 
rsqrtps */
@@ -1020,6 +1029,24 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x76] = X86_OP_ENTRY3(PCMPEQD,V,x, H,x, W,x,  vex4 mmx avx2_256 
p_00_66),
 [0x77] = X86_OP_GROUP0(0F77),
 
+[0x80] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x81] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x82] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x83] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x84] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x85] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x86] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x87] = X86_OP_ENTRYr(Jcc, J,z_f64),
+
+[0x90] = X86_OP_ENTRYw(SETcc, E,b),
+[0x91] = X86_OP_ENTRYw(SETcc, E,b),
+[0x92] = X86_OP_ENTRYw(SETcc, E,b),
+[0x93] = X86_OP_ENTRYw(SETcc, E,b),
+[0x94] = X86_OP_ENTRYw(SETcc, E,b),
+[0x95] = X86_OP_ENTRYw(SETcc, E,b),
+[0x96] = X86_OP_ENTRYw(SETcc, E,b),
+[0x97] = X86_OP_ENTRYw(SETcc, E,b),
+
 [0x28] = X86_OP_ENTRY3(MOVDQ,  V,x,  None,None, W,x, vex1 p_00_66), /* 
MOVAPS */
 [0x29] = X86_OP_ENTRY3(MOVDQ,  W,x,  None,None, V,x, vex1 p_00_66), /* 
MOVAPS */
 [0x2A] = X86_OP_GROUP0(0F2A),
@@ -1032,6 +1059,15 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x38] = X86_OP_GROUP0(0F38),
 [0x3a] = X86_OP_GROUP0(0F3A),
 
+[0x48] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x49] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4a] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4b] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4c] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4d] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4e] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+[0x4f] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
+
 [0x58] = X86_OP_ENTRY3(VADD,   V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
 [0x59] = X86_OP_ENTRY3(VMUL,   V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
 [0x5a] = X86_OP_GROUP0(0F5A),
@@ -1057,6 +1093,24 @@ static const X86OpEntry opcodes_0F[256] = {
 [0x7e] = X86_OP_GROUP0(0F7E),
 [0x7f] = X86_OP_GROUP0(0F7F),
 
+[0x88] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x89] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8a] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8b] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8c] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8d] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8e] = X86_OP_ENTRYr(Jcc, J,z_f64),
+[0x8f] = X86_OP_ENTRYr(Jcc, J,z_f64),
+
+[0x98] = 

[PATCH v2 20/25] target/i386: move BSWAP to new decoder

2024-05-06 Thread Paolo Bonzini
Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c  |  4 +++-
 target/i386/tcg/decode-new.c.inc |  9 +
 target/i386/tcg/emit.c.inc   | 11 +++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index a80021930bf..87ecf082316 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3206,7 +3206,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 #ifndef CONFIG_USER_ONLY
 use_new &= b <= limit;
 #endif
-if (use_new && (b >= 0x138 && b <= 0x19f)) {
+if (use_new &&
+((b >= 0x138 && b <= 0x19f) ||
+ (b >= 0x1c8 && b <= 0x1cf))) {
 disas_insn_new(s, cpu, b);
 return true;
 }
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 7528e9e4f07..e65fa208a43 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1118,6 +1118,15 @@ static const X86OpEntry opcodes_0F[256] = {
 [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b,   vex5 mmx p_00_66),
 [0xc6] = X86_OP_ENTRY4(VSHUF,  V,x, H,x, W,x,   vex4 p_00_66),
 
+[0xc8] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xc9] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xca] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcb] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcc] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcd] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xce] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+[0xcf] = X86_OP_ENTRY1(BSWAP, LoBits,y),
+
 [0xd0] = X86_OP_ENTRY3(VADDSUB,   V,x, H,x, W,x,vex2 cpuid(SSE3) 
p_66_f2),
 [0xd1] = X86_OP_ENTRY3(PSRLW_r,   V,x, H,x, W,x,vex4 mmx avx2_256 
p_00_66),
 [0xd2] = X86_OP_ENTRY3(PSRLD_r,   V,x, H,x, W,x,vex4 mmx avx2_256 
p_00_66),
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index a48ff1536a4..c826ad8 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1310,6 +1310,17 @@ static void gen_BOUND(DisasContext *s, CPUX86State *env, 
X86DecodedInsn *decode)
 }
 }
 
+static void gen_BSWAP(DisasContext *s, CPUX86State *env, X86DecodedInsn 
*decode)
+{
+#ifdef TARGET_X86_64
+if (s->dflag == MO_64) {
+tcg_gen_bswap64_i64(s->T0, s->T0);
+return;
+}
+#endif
+tcg_gen_bswap32_tl(s->T0, s->T0, TCG_BSWAP_OZ);
+}
+
 static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
 {
 MemOp ot = decode->op[0].ot;
-- 
2.45.0




[PATCH v2 13/25] target/i386: extract gen_far_call/jmp, reordering temporaries

2024-05-06 Thread Paolo Bonzini
Extract the code into new functions, and swap T0/T1 so that T0 corresponds
to the first immediate in the instruction stream.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 93 +
 1 file changed, 53 insertions(+), 40 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 8a9c265ae51..4069bd4f125 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2511,12 +2511,13 @@ static inline void gen_op_movl_T0_seg(DisasContext *s, 
X86Seg seg_reg)
  offsetof(CPUX86State,segs[seg_reg].selector));
 }
 
-static inline void gen_op_movl_seg_T0_vm(DisasContext *s, X86Seg seg_reg)
+static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
 {
-tcg_gen_ext16u_tl(s->T0, s->T0);
-tcg_gen_st32_tl(s->T0, tcg_env,
+TCGv selector = tcg_temp_new();
+tcg_gen_ext16u_tl(selector, seg);
+tcg_gen_st32_tl(selector, tcg_env,
 offsetof(CPUX86State,segs[seg_reg].selector));
-tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
+tcg_gen_shli_tl(cpu_seg_base[seg_reg], selector, 4);
 }
 
 /* move T0 to seg_reg and compute if the CPU state may change. Never
@@ -2536,13 +2537,45 @@ static void gen_movl_seg_T0(DisasContext *s, X86Seg 
seg_reg)
 s->base.is_jmp = DISAS_EOB_NEXT;
 }
 } else {
-gen_op_movl_seg_T0_vm(s, seg_reg);
+gen_op_movl_seg_real(s, seg_reg, s->T0);
 if (seg_reg == R_SS) {
 s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
 }
 }
 }
 
+static void gen_far_call(DisasContext *s)
+{
+TCGv_i32 new_cs = tcg_temp_new_i32();
+tcg_gen_trunc_tl_i32(new_cs, s->T1);
+if (PE(s) && !VM86(s)) {
+gen_helper_lcall_protected(tcg_env, new_cs, s->T0,
+   tcg_constant_i32(s->dflag - 1),
+   eip_next_tl(s));
+} else {
+TCGv_i32 new_eip = tcg_temp_new_i32();
+tcg_gen_trunc_tl_i32(new_eip, s->T0);
+gen_helper_lcall_real(tcg_env, new_cs, new_eip,
+  tcg_constant_i32(s->dflag - 1),
+  eip_next_i32(s));
+}
+s->base.is_jmp = DISAS_JUMP;
+}
+
+static void gen_far_jmp(DisasContext *s)
+{
+if (PE(s) && !VM86(s)) {
+TCGv_i32 new_cs = tcg_temp_new_i32();
+tcg_gen_trunc_tl_i32(new_cs, s->T1);
+gen_helper_ljmp_protected(tcg_env, new_cs, s->T0,
+  eip_next_tl(s));
+} else {
+gen_op_movl_seg_real(s, R_CS, s->T1);
+gen_op_jmp_v(s, s->T0);
+}
+s->base.is_jmp = DISAS_JUMP;
+}
+
 static void gen_svm_check_intercept(DisasContext *s, uint32_t type)
 {
 /* no SVM activated; fast case */
@@ -3653,23 +3686,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 if (mod == 3) {
 goto illegal_op;
 }
-gen_op_ld_v(s, ot, s->T1, s->A0);
+gen_op_ld_v(s, ot, s->T0, s->A0);
 gen_add_A0_im(s, 1 << ot);
-gen_op_ld_v(s, MO_16, s->T0, s->A0);
-do_lcall:
-if (PE(s) && !VM86(s)) {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-gen_helper_lcall_protected(tcg_env, s->tmp2_i32, s->T1,
-   tcg_constant_i32(dflag - 1),
-   eip_next_tl(s));
-} else {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
-gen_helper_lcall_real(tcg_env, s->tmp2_i32, s->tmp3_i32,
-  tcg_constant_i32(dflag - 1),
-  eip_next_i32(s));
-}
-s->base.is_jmp = DISAS_JUMP;
+gen_op_ld_v(s, MO_16, s->T1, s->A0);
+gen_far_call(s);
 break;
 case 4: /* jmp Ev */
 if (dflag == MO_16) {
@@ -3683,19 +3703,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 if (mod == 3) {
 goto illegal_op;
 }
-gen_op_ld_v(s, ot, s->T1, s->A0);
+gen_op_ld_v(s, ot, s->T0, s->A0);
 gen_add_A0_im(s, 1 << ot);
-gen_op_ld_v(s, MO_16, s->T0, s->A0);
-do_ljmp:
-if (PE(s) && !VM86(s)) {
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-gen_helper_ljmp_protected(tcg_env, s->tmp2_i32, s->T1,
-  eip_next_tl(s));
-} else {
-gen_op_movl_seg_T0_vm(s, R_CS);
-gen_op_jmp_v(s, s->T1);
-}
-s->base.is_jmp = DISAS_JUMP;
+ 

[PATCH v2 18/25] target/i386: merge and enlarge a few ranges for call to disas_insn_new

2024-05-06 Thread Paolo Bonzini
Since new opcodes are not going to be added in translate.c, round the
case labels that call to disas_insn_new(), including whole sets of
eight opcodes when possible.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 79b6e2760fe..b94d9504090 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -6868,9 +6868,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 break;
 case 0x10e ... 0x117:
 case 0x128 ... 0x12f:
-case 0x138 ... 0x13a:
-case 0x150 ... 0x179:
-case 0x17c ... 0x17f:
+case 0x138 ... 0x13f:
+case 0x150 ... 0x17f:
 case 0x1c2:
 case 0x1c4 ... 0x1c6:
 case 0x1d0 ... 0x1fe:
-- 
2.45.0




[PATCH v2 06/25] target/i386: pull cc_op update to callers of gen_jmp_rel{, _csize}

2024-05-06 Thread Paolo Bonzini
gen_update_cc_op must be called before control flow splits.  Doing it
in gen_jmp_rel{,_csize} may hide bugs, instead assert that cc_op is
clean---even if that means a few more calls to gen_update_cc_op().

With this new invariant, setting cc_op to CC_OP_DYNAMIC is unnecessary
since the caller should have done it.

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 6b766f5dd3f..17bf85da0ce 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2852,6 +2852,8 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 target_ulong new_pc = s->pc + diff;
 target_ulong new_eip = new_pc - s->cs_base;
 
+assert(!s->cc_op_dirty);
+
 /* In 64-bit mode, operand size is fixed at 64 bits. */
 if (!CODE64(s)) {
 if (ot == MO_16) {
@@ -2865,9 +2867,6 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int 
diff, int tb_num)
 }
 new_eip &= mask;
 
-gen_update_cc_op(s);
-set_cc_op(s, CC_OP_DYNAMIC);
-
 if (tb_cflags(s->base.tb) & CF_PCREL) {
 tcg_gen_addi_tl(cpu_eip, cpu_eip, new_pc - s->pc_save);
 /*
@@ -5145,6 +5144,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 : (int16_t)insn_get(env, s, MO_16));
 gen_push_v(s, eip_next_tl(s));
 gen_bnd_jmp(s);
+gen_update_cc_op(s);
 gen_jmp_rel(s, dflag, diff, 0);
 }
 break;
@@ -5168,6 +5168,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 ? (int32_t)insn_get(env, s, MO_32)
 : (int16_t)insn_get(env, s, MO_16));
 gen_bnd_jmp(s);
+gen_update_cc_op(s);
 gen_jmp_rel(s, dflag, diff, 0);
 }
 break;
@@ -5188,6 +5189,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
 case 0xeb: /* jmp Jb */
 {
 int diff = (int8_t)insn_get(env, s, MO_8);
+gen_update_cc_op(s);
 gen_jmp_rel(s, dflag, diff, 0);
 }
 break;
-- 
2.45.0




[PATCH v2 08/25] target/i386: do not use s->T0 and s->T1 as scratch registers for CCPrepare

2024-05-06 Thread Paolo Bonzini
Instead of using s->T0 or s->T1, create a scratch register
when computing the C, NC, L or LE conditions.

Signed-off-by: Paolo Bonzini 
---
 target/i386/tcg/translate.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index d76f72c1b96..2cd7868d596 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -998,6 +998,9 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv 
reg)
/* The need to compute only C from CC_OP_DYNAMIC is important
   in efficiently implementing e.g. INC at the start of a TB.  */
gen_update_cc_op(s);
+   if (!reg) {
+   reg = tcg_temp_new();
+   }
gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
cpu_cc_src2, cpu_cc_op);
return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
@@ -1152,8 +1155,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 break;
 case JCC_L:
 gen_compute_eflags(s);
-if (reg == cpu_cc_src) {
-reg = s->tmp0;
+if (!reg || reg == cpu_cc_src) {
+reg = tcg_temp_new();
 }
 tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S);
 cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg,
@@ -1162,8 +1165,8 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, 
TCGv reg)
 default:
 case JCC_LE:
 gen_compute_eflags(s);
-if (reg == cpu_cc_src) {
-reg = s->tmp0;
+if (!reg || reg == cpu_cc_src) {
+reg = tcg_temp_new();
 }
 tcg_gen_addi_tl(reg, cpu_cc_src, CC_O - CC_S);
 cc = (CCPrepare) { .cond = TCG_COND_TSTNE, .reg = reg,
@@ -1208,7 +1211,7 @@ static inline void gen_compute_eflags_c(DisasContext *s, 
TCGv reg)
value 'b'. In the fast case, T0 is guaranteed not to be used. */
 static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
 {
-CCPrepare cc = gen_prepare_cc(s, b, s->T0);
+CCPrepare cc = gen_prepare_cc(s, b, NULL);
 
 if (cc.use_reg2) {
 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
@@ -1223,7 +1226,7 @@ static inline void gen_jcc1_noeob(DisasContext *s, int b, 
TCGLabel *l1)
cc_op is clean.  */
 static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
 {
-CCPrepare cc = gen_prepare_cc(s, b, s->T0);
+CCPrepare cc = gen_prepare_cc(s, b, NULL);
 
 gen_update_cc_op(s);
 if (cc.use_reg2) {
@@ -2492,7 +2495,7 @@ static void gen_jcc(DisasContext *s, int b, int diff)
 
 static void gen_cmovcc1(DisasContext *s, int b, TCGv dest, TCGv src)
 {
-CCPrepare cc = gen_prepare_cc(s, b, s->T1);
+CCPrepare cc = gen_prepare_cc(s, b, NULL);
 
 if (!cc.use_reg2) {
 cc.reg2 = tcg_constant_tl(cc.imm);
-- 
2.45.0




<    1   2   3   4   5   6   7   8   9   10   >