All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v5 00/12] i386 cleanup
@ 2020-11-24 16:21 Claudio Fontana
  2020-11-24 16:21 ` [RFC v5 01/12] i386: move kvm accel files into kvm/ Claudio Fontana
                   ` (12 more replies)
  0 siblings, 13 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:21 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Hi all, this is v5 of the i386 cleanup,
with the most interesting patches at the end.

I put in To: Emilio G. Cota, specifically because in patch 8
I (re)moved for user-mode the call to tcg_regions_init().

The call happens now inside the tcg AccelClass machine_init,
(so earlier). This seems to work fine, but thought to get the
author opinion on this.

v4 -> v5: centralized and simplified initializations


Rebased on "tcg-cpus: split into 3 tcg variants" series
(queued by Richard), to avoid some code churn:


https://lists.gnu.org/archive/html/qemu-devel/2020-10/msg04356.html


* Extended AccelClass to user-mode.

user-mode now does not call tcg_exec_init directly,
instead it uses the tcg accel class, and its init_machine method.

Since user-mode does not define or use a machine state,
the machine is just passed as NULL.

The immediate advantage is that now we can call current_accel()
from both user mode and softmmu, so we can work out the correct
class to use for accelerator initializations.

* QOMification of CpusAccelOps

simple QOMification of CpusAccelOps abstract class.

* Centralized all accel_cpu_init, so only one per cpu-arch,
  plus one for all accels will remain.

  So we can expect accel_cpu_init() to be limited to:
  
  softmmu/cpus.c - initializes the chosen softmmu accel ops for the cpus module.
  target/ARCH/cpu.c - initializes the chosen arch-specific cpu accelerator.
  
These changes are meant to address concerns/issues (Paolo):

1) the use of if (tcg_enabled()) and similar in the module_init call path

2) the excessive number of accel_cpu_init() to hunt down in the codebase.


* Fixed wrong use of host_cpu_class_init (Eduardo)


v3 -> v4: QOMification of X86CPUAccelClass


In this version I basically QOMified X86CPUAccel, taking the
suggestions from Eduardo as the starting point,
but stopping just short of making it an actual QOM interface,
using a plain abstract class, and then subclasses for the
actual objects.

Initialization is still using the existing qemu initialization
framework (module_call_init), which is I still think is better
than the alternatives proposed, in the current state.

Possibly some improvements could be developed in the future here.
In this case, effort should be put in keeping things extendible,
in order not to be blocked once accelerators also become modules.

Motivation and higher level steps:

https://lists.gnu.org/archive/html/qemu-devel/2020-05/msg04628.html

Looking forward to your comments on this proposal,

Ciao,

Claudio

Claudio Fontana (12):
  i386: move kvm accel files into kvm/
  i386: move whpx accel files into whpx/
  i386: move hax accel files into hax/
  i386: hvf: remove stale MAINTAINERS entry for old hvf stubs
  i386: move TCG accel files into tcg/
  i386: move cpu dump out of helper.c into cpu-dump.c
  i386: move TCG cpu class initialization out of helper.c
  accel: extend AccelState and AccelClass to user-mode
  module: introduce MODULE_INIT_ACCEL_CPU
  i386: split cpu accelerators from cpu.c
  i386: centralize initialization of cpu accel interfaces
  accel: centralize initialization of CpusAccelOps

 MAINTAINERS                           |  14 +-
 accel/accel-common.c                  |  54 +++
 accel/{accel.c => accel-softmmu.c}    |  27 +-
 accel/accel-user.c                    |  28 ++
 accel/kvm/kvm-all.c                   |   2 -
 accel/kvm/kvm-cpus.c                  |  26 +-
 accel/kvm/kvm-cpus.h                  |   2 -
 accel/meson.build                     |   4 +-
 accel/qtest/qtest.c                   |  25 +-
 accel/tcg/meson.build                 |   3 +-
 accel/tcg/tcg-all.c                   |  11 +-
 accel/tcg/tcg-cpus-icount.c           |  11 +-
 accel/tcg/tcg-cpus-icount.h           |   2 +
 accel/tcg/tcg-cpus-mttcg.c            |  12 +-
 accel/tcg/tcg-cpus-mttcg.h            |  19 +
 accel/tcg/tcg-cpus-rr.c               |   7 -
 accel/tcg/tcg-cpus.c                  |  43 ++
 accel/tcg/tcg-cpus.h                  |   4 -
 accel/xen/xen-all.c                   |  25 +-
 bsd-user/main.c                       |   9 +-
 hw/i386/fw_cfg.c                      |   2 +-
 hw/i386/intel_iommu.c                 |   2 +-
 hw/i386/kvm/apic.c                    |   2 +-
 hw/i386/kvm/clock.c                   |   2 +-
 hw/i386/microvm.c                     |   2 +-
 hw/i386/pc.c                          |   2 +-
 hw/i386/pc_piix.c                     |   1 +
 hw/i386/x86.c                         |   2 +-
 include/hw/boards.h                   |   2 +-
 include/{sysemu => qemu}/accel.h      |  15 +-
 include/qemu/module.h                 |   2 +
 include/sysemu/cpus.h                 |  39 +-
 include/sysemu/hvf.h                  |   2 +-
 include/sysemu/kvm.h                  |   2 +-
 include/sysemu/kvm_int.h              |   2 +-
 linux-user/main.c                     |   9 +-
 meson.build                           |   1 +
 roms/qboot                            |   2 +-
 softmmu/cpus.c                        |  51 ++-
 softmmu/memory.c                      |   2 +-
 softmmu/qtest.c                       |   2 +-
 softmmu/vl.c                          |   8 +-
 target/i386/cpu-dump.c                | 538 +++++++++++++++++++++++++
 target/i386/cpu-qom.h                 |  26 ++
 target/i386/cpu.c                     | 446 ++++-----------------
 target/i386/cpu.h                     | 120 +-----
 target/i386/{ => hax}/hax-all.c       |   5 +-
 target/i386/{ => hax}/hax-cpus.c      |  29 +-
 target/i386/{ => hax}/hax-cpus.h      |   2 -
 target/i386/{ => hax}/hax-i386.h      |   6 +-
 target/i386/{ => hax}/hax-interface.h |   0
 target/i386/{ => hax}/hax-mem.c       |   0
 target/i386/{ => hax}/hax-posix.c     |   0
 target/i386/{ => hax}/hax-posix.h     |   0
 target/i386/{ => hax}/hax-windows.c   |   0
 target/i386/{ => hax}/hax-windows.h   |   0
 target/i386/hax/meson.build           |   7 +
 target/i386/helper-tcg.h              | 112 ++++++
 target/i386/helper.c                  | 539 +-------------------------
 target/i386/host-cpu.c                | 198 ++++++++++
 target/i386/host-cpu.h                |  19 +
 target/i386/hvf/cpu.c                 |  67 ++++
 target/i386/hvf/hvf-cpus.c            |  27 +-
 target/i386/hvf/hvf-cpus.h            |   2 -
 target/i386/hvf/hvf-i386.h            |   2 +-
 target/i386/hvf/hvf.c                 |   3 +-
 target/i386/hvf/meson.build           |   1 +
 target/i386/hvf/x86_task.c            |   2 +-
 target/i386/kvm/cpu.c                 | 149 +++++++
 target/i386/{ => kvm}/hyperv-proto.h  |   0
 target/i386/{ => kvm}/hyperv-stub.c   |   0
 target/i386/{ => kvm}/hyperv.c        |   0
 target/i386/{ => kvm}/hyperv.h        |   0
 target/i386/kvm/kvm-cpu.h             |  41 ++
 target/i386/{ => kvm}/kvm-stub.c      |   0
 target/i386/{ => kvm}/kvm.c           |   3 +-
 target/i386/{ => kvm}/kvm_i386.h      |   0
 target/i386/kvm/meson.build           |   8 +
 target/i386/kvm/trace-events          |   7 +
 target/i386/kvm/trace.h               |   1 +
 target/i386/machine.c                 |   4 +-
 target/i386/meson.build               |  39 +-
 target/i386/{ => tcg}/bpt_helper.c    |   1 +
 target/i386/{ => tcg}/cc_helper.c     |   1 +
 target/i386/tcg/cpu.c                 | 172 ++++++++
 target/i386/{ => tcg}/excp_helper.c   |   1 +
 target/i386/{ => tcg}/fpu_helper.c    |  33 +-
 target/i386/{ => tcg}/int_helper.c    |   1 +
 target/i386/{ => tcg}/mem_helper.c    |   1 +
 target/i386/tcg/meson.build           |  14 +
 target/i386/{ => tcg}/misc_helper.c   |   1 +
 target/i386/{ => tcg}/mpx_helper.c    |   1 +
 target/i386/{ => tcg}/seg_helper.c    |   1 +
 target/i386/{ => tcg}/smm_helper.c    |   2 +
 target/i386/{ => tcg}/svm_helper.c    |   1 +
 target/i386/{ => tcg}/tcg-stub.c      |   0
 target/i386/{ => tcg}/translate.c     |   1 +
 target/i386/trace-events              |   6 -
 target/i386/whpx/meson.build          |   4 +
 target/i386/{ => whpx}/whp-dispatch.h |   0
 target/i386/{ => whpx}/whpx-all.c     |   4 +-
 target/i386/{ => whpx}/whpx-cpus.c    |  29 +-
 target/i386/{ => whpx}/whpx-cpus.h    |   2 -
 103 files changed, 1914 insertions(+), 1247 deletions(-)
 create mode 100644 accel/accel-common.c
 rename accel/{accel.c => accel-softmmu.c} (75%)
 create mode 100644 accel/accel-user.c
 create mode 100644 accel/tcg/tcg-cpus-mttcg.h
 rename include/{sysemu => qemu}/accel.h (95%)
 create mode 100644 target/i386/cpu-dump.c
 rename target/i386/{ => hax}/hax-all.c (99%)
 rename target/i386/{ => hax}/hax-cpus.c (70%)
 rename target/i386/{ => hax}/hax-cpus.h (95%)
 rename target/i386/{ => hax}/hax-i386.h (95%)
 rename target/i386/{ => hax}/hax-interface.h (100%)
 rename target/i386/{ => hax}/hax-mem.c (100%)
 rename target/i386/{ => hax}/hax-posix.c (100%)
 rename target/i386/{ => hax}/hax-posix.h (100%)
 rename target/i386/{ => hax}/hax-windows.c (100%)
 rename target/i386/{ => hax}/hax-windows.h (100%)
 create mode 100644 target/i386/hax/meson.build
 create mode 100644 target/i386/helper-tcg.h
 create mode 100644 target/i386/host-cpu.c
 create mode 100644 target/i386/host-cpu.h
 create mode 100644 target/i386/hvf/cpu.c
 create mode 100644 target/i386/kvm/cpu.c
 rename target/i386/{ => kvm}/hyperv-proto.h (100%)
 rename target/i386/{ => kvm}/hyperv-stub.c (100%)
 rename target/i386/{ => kvm}/hyperv.c (100%)
 rename target/i386/{ => kvm}/hyperv.h (100%)
 create mode 100644 target/i386/kvm/kvm-cpu.h
 rename target/i386/{ => kvm}/kvm-stub.c (100%)
 rename target/i386/{ => kvm}/kvm.c (99%)
 rename target/i386/{ => kvm}/kvm_i386.h (100%)
 create mode 100644 target/i386/kvm/meson.build
 create mode 100644 target/i386/kvm/trace-events
 create mode 100644 target/i386/kvm/trace.h
 rename target/i386/{ => tcg}/bpt_helper.c (99%)
 rename target/i386/{ => tcg}/cc_helper.c (99%)
 create mode 100644 target/i386/tcg/cpu.c
 rename target/i386/{ => tcg}/excp_helper.c (99%)
 rename target/i386/{ => tcg}/fpu_helper.c (99%)
 rename target/i386/{ => tcg}/int_helper.c (99%)
 rename target/i386/{ => tcg}/mem_helper.c (99%)
 create mode 100644 target/i386/tcg/meson.build
 rename target/i386/{ => tcg}/misc_helper.c (99%)
 rename target/i386/{ => tcg}/mpx_helper.c (99%)
 rename target/i386/{ => tcg}/seg_helper.c (99%)
 rename target/i386/{ => tcg}/smm_helper.c (99%)
 rename target/i386/{ => tcg}/svm_helper.c (99%)
 rename target/i386/{ => tcg}/tcg-stub.c (100%)
 rename target/i386/{ => tcg}/translate.c (99%)
 create mode 100644 target/i386/whpx/meson.build
 rename target/i386/{ => whpx}/whp-dispatch.h (100%)
 rename target/i386/{ => whpx}/whpx-all.c (99%)
 rename target/i386/{ => whpx}/whpx-cpus.c (73%)
 rename target/i386/{ => whpx}/whpx-cpus.h (96%)

-- 
2.26.2



^ permalink raw reply	[flat|nested] 51+ messages in thread

* [RFC v5 01/12] i386: move kvm accel files into kvm/
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
@ 2020-11-24 16:21 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 02/12] i386: move whpx accel files into whpx/ Claudio Fontana
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:21 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                          | 2 +-
 hw/i386/fw_cfg.c                     | 2 +-
 hw/i386/intel_iommu.c                | 2 +-
 hw/i386/kvm/apic.c                   | 2 +-
 hw/i386/kvm/clock.c                  | 2 +-
 hw/i386/microvm.c                    | 2 +-
 hw/i386/pc.c                         | 2 +-
 hw/i386/x86.c                        | 2 +-
 meson.build                          | 1 +
 target/i386/cpu.c                    | 2 +-
 target/i386/cpu.h                    | 2 +-
 target/i386/helper.c                 | 2 +-
 target/i386/{ => kvm}/hyperv-proto.h | 0
 target/i386/{ => kvm}/hyperv-stub.c  | 0
 target/i386/{ => kvm}/hyperv.c       | 0
 target/i386/{ => kvm}/hyperv.h       | 0
 target/i386/{ => kvm}/kvm-stub.c     | 0
 target/i386/{ => kvm}/kvm.c          | 0
 target/i386/{ => kvm}/kvm_i386.h     | 0
 target/i386/kvm/meson.build          | 3 +++
 target/i386/kvm/trace-events         | 7 +++++++
 target/i386/kvm/trace.h              | 1 +
 target/i386/machine.c                | 4 ++--
 target/i386/meson.build              | 4 +---
 target/i386/trace-events             | 6 ------
 25 files changed, 26 insertions(+), 22 deletions(-)
 rename target/i386/{ => kvm}/hyperv-proto.h (100%)
 rename target/i386/{ => kvm}/hyperv-stub.c (100%)
 rename target/i386/{ => kvm}/hyperv.c (100%)
 rename target/i386/{ => kvm}/hyperv.h (100%)
 rename target/i386/{ => kvm}/kvm-stub.c (100%)
 rename target/i386/{ => kvm}/kvm.c (100%)
 rename target/i386/{ => kvm}/kvm_i386.h (100%)
 create mode 100644 target/i386/kvm/meson.build
 create mode 100644 target/i386/kvm/trace-events
 create mode 100644 target/i386/kvm/trace.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2e018a0c1d..6a77faccf6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -424,7 +424,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
 M: Marcelo Tosatti <mtosatti@redhat.com>
 L: kvm@vger.kernel.org
 S: Supported
-F: target/i386/kvm.c
+F: target/i386/kvm/
 F: scripts/kvm/vmxcap
 
 Guest CPU Cores (other accelerators)
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index e06579490c..fae1bb380f 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -21,7 +21,7 @@
 #include "hw/timer/hpet.h"
 #include "hw/nvram/fw_cfg.h"
 #include "e820_memory_layout.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #include CONFIG_DEVICES
 
 struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 70ac837733..361b6cd238 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -37,7 +37,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/apic_internal.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #include "migration/vmstate.h"
 #include "trace.h"
 
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index dd29906061..07bebc1282 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -17,7 +17,7 @@
 #include "hw/pci/msi.h"
 #include "sysemu/hw_accel.h"
 #include "sysemu/kvm.h"
-#include "target/i386/kvm_i386.h"
+#include "kvm/kvm_i386.h"
 
 static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
                                     int reg_id, uint32_t val)
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index 24fe5091b6..2d8a366369 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -20,7 +20,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/runstate.h"
 #include "sysemu/hw_accel.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #include "migration/vmstate.h"
 #include "hw/sysbus.h"
 #include "hw/kvm/clock.h"
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 5428448b70..3ed6adff83 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -51,7 +51,7 @@
 
 #include "cpu.h"
 #include "elf.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #include "hw/xen/start_info.h"
 
 #define MICROVM_QBOOT_FILENAME "qboot.rom"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 17b514d1da..299aaba8e9 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -61,7 +61,7 @@
 #include "sysemu/qtest.h"
 #include "sysemu/reset.h"
 #include "sysemu/runstate.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #include "hw/xen/xen.h"
 #include "hw/xen/start_info.h"
 #include "ui/qemu-spice.h"
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 5944fc44ed..88d0c70e12 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -52,7 +52,7 @@
 #include "elf.h"
 #include "standard-headers/asm-x86/bootparam.h"
 #include CONFIG_DEVICES
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 
 #define BIOS_FILENAME "bios.bin"
 
diff --git a/meson.build b/meson.build
index 5062407c70..d6158172b0 100644
--- a/meson.build
+++ b/meson.build
@@ -1468,6 +1468,7 @@ trace_events_subdirs += [
   'target/arm',
   'target/hppa',
   'target/i386',
+  'target/i386/kvm',
   'target/mips',
   'target/ppc',
   'target/riscv',
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5a8c96072e..b9bd249c8f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -30,7 +30,7 @@
 #include "sysemu/hvf.h"
 #include "sysemu/cpus.h"
 #include "sysemu/xen.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #include "sev_i386.h"
 
 #include "qemu/error-report.h"
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 88e8586f8f..9ecda75aec 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -22,7 +22,7 @@
 
 #include "sysemu/tcg.h"
 #include "cpu-qom.h"
-#include "hyperv-proto.h"
+#include "kvm/hyperv-proto.h"
 #include "exec/cpu-defs.h"
 #include "qapi/qapi-types-common.h"
 
diff --git a/target/i386/helper.c b/target/i386/helper.c
index 034f46bcc2..a1b3367ab2 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -24,7 +24,7 @@
 #include "qemu/qemu-print.h"
 #include "sysemu/kvm.h"
 #include "sysemu/runstate.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/tcg.h"
 #include "sysemu/hw_accel.h"
diff --git a/target/i386/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h
similarity index 100%
rename from target/i386/hyperv-proto.h
rename to target/i386/kvm/hyperv-proto.h
diff --git a/target/i386/hyperv-stub.c b/target/i386/kvm/hyperv-stub.c
similarity index 100%
rename from target/i386/hyperv-stub.c
rename to target/i386/kvm/hyperv-stub.c
diff --git a/target/i386/hyperv.c b/target/i386/kvm/hyperv.c
similarity index 100%
rename from target/i386/hyperv.c
rename to target/i386/kvm/hyperv.c
diff --git a/target/i386/hyperv.h b/target/i386/kvm/hyperv.h
similarity index 100%
rename from target/i386/hyperv.h
rename to target/i386/kvm/hyperv.h
diff --git a/target/i386/kvm-stub.c b/target/i386/kvm/kvm-stub.c
similarity index 100%
rename from target/i386/kvm-stub.c
rename to target/i386/kvm/kvm-stub.c
diff --git a/target/i386/kvm.c b/target/i386/kvm/kvm.c
similarity index 100%
rename from target/i386/kvm.c
rename to target/i386/kvm/kvm.c
diff --git a/target/i386/kvm_i386.h b/target/i386/kvm/kvm_i386.h
similarity index 100%
rename from target/i386/kvm_i386.h
rename to target/i386/kvm/kvm_i386.h
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
new file mode 100644
index 0000000000..1d66559187
--- /dev/null
+++ b/target/i386/kvm/meson.build
@@ -0,0 +1,3 @@
+i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
+i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
+i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
new file mode 100644
index 0000000000..b4e2d9e4ea
--- /dev/null
+++ b/target/i386/kvm/trace-events
@@ -0,0 +1,7 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# kvm.c
+kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %" PRIu32
+kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
+kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
+kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
diff --git a/target/i386/kvm/trace.h b/target/i386/kvm/trace.h
new file mode 100644
index 0000000000..46b75c6942
--- /dev/null
+++ b/target/i386/kvm/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-target_i386_kvm.h"
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 233e46bb70..1614e8c2f8 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -3,9 +3,9 @@
 #include "exec/exec-all.h"
 #include "hw/isa/isa.h"
 #include "migration/cpu.h"
-#include "hyperv.h"
+#include "kvm/hyperv.h"
 #include "hw/i386/x86.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
 
 #include "sysemu/kvm.h"
 #include "sysemu/tcg.h"
diff --git a/target/i386/meson.build b/target/i386/meson.build
index a1a02f3e99..0209542a8a 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -18,7 +18,6 @@ i386_ss.add(when: 'CONFIG_TCG', if_true: files(
   'smm_helper.c',
   'svm_helper.c',
   'translate.c'), if_false: files('tcg-stub.c'))
-i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
 i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-stub.c'))
 
 i386_softmmu_ss = ss.source_set()
@@ -28,8 +27,6 @@ i386_softmmu_ss.add(files(
   'machine.c',
   'monitor.c',
 ))
-i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
-i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
 i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files(
   'whpx-all.c',
   'whpx-cpus.c',
@@ -42,6 +39,7 @@ i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files(
 i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-posix.c'))
 i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c'))
 
+subdir('kvm')
 subdir('hvf')
 
 target_arch += {'i386': i386_ss}
diff --git a/target/i386/trace-events b/target/i386/trace-events
index 789c700d4a..d166f9d5e0 100644
--- a/target/i386/trace-events
+++ b/target/i386/trace-events
@@ -1,11 +1,5 @@
 # See docs/devel/tracing.txt for syntax documentation.
 
-# kvm.c
-kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %" PRIu32
-kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
-kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
-kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
-
 # sev.c
 kvm_sev_init(void) ""
 kvm_memcrypt_register_region(void *addr, size_t len) "addr %p len 0x%zu"
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 02/12] i386: move whpx accel files into whpx/
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
  2020-11-24 16:21 ` [RFC v5 01/12] i386: move kvm accel files into kvm/ Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 03/12] i386: move hax accel files into hax/ Claudio Fontana
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                           | 5 +----
 target/i386/meson.build               | 5 +----
 target/i386/whpx/meson.build          | 4 ++++
 target/i386/{ => whpx}/whp-dispatch.h | 0
 target/i386/{ => whpx}/whpx-all.c     | 0
 target/i386/{ => whpx}/whpx-cpus.c    | 0
 target/i386/{ => whpx}/whpx-cpus.h    | 0
 7 files changed, 6 insertions(+), 8 deletions(-)
 create mode 100644 target/i386/whpx/meson.build
 rename target/i386/{ => whpx}/whp-dispatch.h (100%)
 rename target/i386/{ => whpx}/whpx-all.c (100%)
 rename target/i386/{ => whpx}/whpx-cpus.c (100%)
 rename target/i386/{ => whpx}/whpx-cpus.h (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 6a77faccf6..02bc29ea2b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -450,10 +450,7 @@ F: include/sysemu/hvf.h
 WHPX CPUs
 M: Sunil Muthuswamy <sunilmut@microsoft.com>
 S: Supported
-F: target/i386/whpx-all.c
-F: target/i386/whpx-cpus.c
-F: target/i386/whp-dispatch.h
-F: accel/stubs/whpx-stub.c
+F: target/i386/whpx/
 F: include/sysemu/whpx.h
 
 Guest CPU Cores (Xen)
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 0209542a8a..62cd042915 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -27,10 +27,6 @@ i386_softmmu_ss.add(files(
   'machine.c',
   'monitor.c',
 ))
-i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files(
-  'whpx-all.c',
-  'whpx-cpus.c',
-))
 i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files(
   'hax-all.c',
   'hax-mem.c',
@@ -40,6 +36,7 @@ i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-po
 i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c'))
 
 subdir('kvm')
+subdir('whpx')
 subdir('hvf')
 
 target_arch += {'i386': i386_ss}
diff --git a/target/i386/whpx/meson.build b/target/i386/whpx/meson.build
new file mode 100644
index 0000000000..94a72c8efc
--- /dev/null
+++ b/target/i386/whpx/meson.build
@@ -0,0 +1,4 @@
+i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files(
+  'whpx-all.c',
+  'whpx-cpus.c',
+))
diff --git a/target/i386/whp-dispatch.h b/target/i386/whpx/whp-dispatch.h
similarity index 100%
rename from target/i386/whp-dispatch.h
rename to target/i386/whpx/whp-dispatch.h
diff --git a/target/i386/whpx-all.c b/target/i386/whpx/whpx-all.c
similarity index 100%
rename from target/i386/whpx-all.c
rename to target/i386/whpx/whpx-all.c
diff --git a/target/i386/whpx-cpus.c b/target/i386/whpx/whpx-cpus.c
similarity index 100%
rename from target/i386/whpx-cpus.c
rename to target/i386/whpx/whpx-cpus.c
diff --git a/target/i386/whpx-cpus.h b/target/i386/whpx/whpx-cpus.h
similarity index 100%
rename from target/i386/whpx-cpus.h
rename to target/i386/whpx/whpx-cpus.h
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 03/12] i386: move hax accel files into hax/
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
  2020-11-24 16:21 ` [RFC v5 01/12] i386: move kvm accel files into kvm/ Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 02/12] i386: move whpx accel files into whpx/ Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 04/12] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                           | 2 +-
 target/i386/{ => hax}/hax-all.c       | 0
 target/i386/{ => hax}/hax-cpus.c      | 0
 target/i386/{ => hax}/hax-cpus.h      | 0
 target/i386/{ => hax}/hax-i386.h      | 6 +++---
 target/i386/{ => hax}/hax-interface.h | 0
 target/i386/{ => hax}/hax-mem.c       | 0
 target/i386/{ => hax}/hax-posix.c     | 0
 target/i386/{ => hax}/hax-posix.h     | 0
 target/i386/{ => hax}/hax-windows.c   | 0
 target/i386/{ => hax}/hax-windows.h   | 0
 target/i386/hax/meson.build           | 7 +++++++
 target/i386/meson.build               | 8 +-------
 13 files changed, 12 insertions(+), 11 deletions(-)
 rename target/i386/{ => hax}/hax-all.c (100%)
 rename target/i386/{ => hax}/hax-cpus.c (100%)
 rename target/i386/{ => hax}/hax-cpus.h (100%)
 rename target/i386/{ => hax}/hax-i386.h (95%)
 rename target/i386/{ => hax}/hax-interface.h (100%)
 rename target/i386/{ => hax}/hax-mem.c (100%)
 rename target/i386/{ => hax}/hax-posix.c (100%)
 rename target/i386/{ => hax}/hax-posix.h (100%)
 rename target/i386/{ => hax}/hax-windows.c (100%)
 rename target/i386/{ => hax}/hax-windows.h (100%)
 create mode 100644 target/i386/hax/meson.build

diff --git a/MAINTAINERS b/MAINTAINERS
index 02bc29ea2b..463317784c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -490,7 +490,7 @@ W: https://github.com/intel/haxm/issues
 S: Maintained
 F: accel/stubs/hax-stub.c
 F: include/sysemu/hax.h
-F: target/i386/hax-*
+F: target/i386/hax/
 
 Hosts
 -----
diff --git a/target/i386/hax-all.c b/target/i386/hax/hax-all.c
similarity index 100%
rename from target/i386/hax-all.c
rename to target/i386/hax/hax-all.c
diff --git a/target/i386/hax-cpus.c b/target/i386/hax/hax-cpus.c
similarity index 100%
rename from target/i386/hax-cpus.c
rename to target/i386/hax/hax-cpus.c
diff --git a/target/i386/hax-cpus.h b/target/i386/hax/hax-cpus.h
similarity index 100%
rename from target/i386/hax-cpus.h
rename to target/i386/hax/hax-cpus.h
diff --git a/target/i386/hax-i386.h b/target/i386/hax/hax-i386.h
similarity index 95%
rename from target/i386/hax-i386.h
rename to target/i386/hax/hax-i386.h
index 48c4abe14e..efbb346238 100644
--- a/target/i386/hax-i386.h
+++ b/target/i386/hax/hax-i386.h
@@ -84,13 +84,13 @@ void hax_memory_init(void);
 
 
 #ifdef CONFIG_POSIX
-#include "target/i386/hax-posix.h"
+#include "hax-posix.h"
 #endif
 
 #ifdef CONFIG_WIN32
-#include "target/i386/hax-windows.h"
+#include "hax-windows.h"
 #endif
 
-#include "target/i386/hax-interface.h"
+#include "hax-interface.h"
 
 #endif
diff --git a/target/i386/hax-interface.h b/target/i386/hax/hax-interface.h
similarity index 100%
rename from target/i386/hax-interface.h
rename to target/i386/hax/hax-interface.h
diff --git a/target/i386/hax-mem.c b/target/i386/hax/hax-mem.c
similarity index 100%
rename from target/i386/hax-mem.c
rename to target/i386/hax/hax-mem.c
diff --git a/target/i386/hax-posix.c b/target/i386/hax/hax-posix.c
similarity index 100%
rename from target/i386/hax-posix.c
rename to target/i386/hax/hax-posix.c
diff --git a/target/i386/hax-posix.h b/target/i386/hax/hax-posix.h
similarity index 100%
rename from target/i386/hax-posix.h
rename to target/i386/hax/hax-posix.h
diff --git a/target/i386/hax-windows.c b/target/i386/hax/hax-windows.c
similarity index 100%
rename from target/i386/hax-windows.c
rename to target/i386/hax/hax-windows.c
diff --git a/target/i386/hax-windows.h b/target/i386/hax/hax-windows.h
similarity index 100%
rename from target/i386/hax-windows.h
rename to target/i386/hax/hax-windows.h
diff --git a/target/i386/hax/meson.build b/target/i386/hax/meson.build
new file mode 100644
index 0000000000..77ea431b30
--- /dev/null
+++ b/target/i386/hax/meson.build
@@ -0,0 +1,7 @@
+i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files(
+  'hax-all.c',
+  'hax-mem.c',
+  'hax-cpus.c',
+))
+i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-posix.c'))
+i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c'))
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 62cd042915..284d52ab81 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -27,15 +27,9 @@ i386_softmmu_ss.add(files(
   'machine.c',
   'monitor.c',
 ))
-i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files(
-  'hax-all.c',
-  'hax-mem.c',
-  'hax-cpus.c',
-))
-i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-posix.c'))
-i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c'))
 
 subdir('kvm')
+subdir('hax')
 subdir('whpx')
 subdir('hvf')
 
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 04/12] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (2 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 03/12] i386: move hax accel files into hax/ Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 05/12] i386: move TCG accel files into tcg/ Claudio Fontana
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS | 1 -
 1 file changed, 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 463317784c..e892dd2220 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -443,7 +443,6 @@ M: Cameron Esfahani <dirty@apple.com>
 M: Roman Bolshakov <r.bolshakov@yadro.com>
 W: https://wiki.qemu.org/Features/HVF
 S: Maintained
-F: accel/stubs/hvf-stub.c
 F: target/i386/hvf/
 F: include/sysemu/hvf.h
 
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 05/12] i386: move TCG accel files into tcg/
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (3 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 04/12] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 06/12] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 target/i386/meson.build             | 14 +-------------
 target/i386/{ => tcg}/bpt_helper.c  |  0
 target/i386/{ => tcg}/cc_helper.c   |  0
 target/i386/{ => tcg}/excp_helper.c |  0
 target/i386/{ => tcg}/fpu_helper.c  |  0
 target/i386/{ => tcg}/int_helper.c  |  0
 target/i386/{ => tcg}/mem_helper.c  |  0
 target/i386/tcg/meson.build         | 13 +++++++++++++
 target/i386/{ => tcg}/misc_helper.c |  0
 target/i386/{ => tcg}/mpx_helper.c  |  0
 target/i386/{ => tcg}/seg_helper.c  |  0
 target/i386/{ => tcg}/smm_helper.c  |  0
 target/i386/{ => tcg}/svm_helper.c  |  0
 target/i386/{ => tcg}/tcg-stub.c    |  0
 target/i386/{ => tcg}/translate.c   |  0
 15 files changed, 14 insertions(+), 13 deletions(-)
 rename target/i386/{ => tcg}/bpt_helper.c (100%)
 rename target/i386/{ => tcg}/cc_helper.c (100%)
 rename target/i386/{ => tcg}/excp_helper.c (100%)
 rename target/i386/{ => tcg}/fpu_helper.c (100%)
 rename target/i386/{ => tcg}/int_helper.c (100%)
 rename target/i386/{ => tcg}/mem_helper.c (100%)
 create mode 100644 target/i386/tcg/meson.build
 rename target/i386/{ => tcg}/misc_helper.c (100%)
 rename target/i386/{ => tcg}/mpx_helper.c (100%)
 rename target/i386/{ => tcg}/seg_helper.c (100%)
 rename target/i386/{ => tcg}/smm_helper.c (100%)
 rename target/i386/{ => tcg}/svm_helper.c (100%)
 rename target/i386/{ => tcg}/tcg-stub.c (100%)
 rename target/i386/{ => tcg}/translate.c (100%)

diff --git a/target/i386/meson.build b/target/i386/meson.build
index 284d52ab81..750471c9f3 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -5,19 +5,6 @@ i386_ss.add(files(
   'helper.c',
   'xsave_helper.c',
 ))
-i386_ss.add(when: 'CONFIG_TCG', if_true: files(
-  'bpt_helper.c',
-  'cc_helper.c',
-  'excp_helper.c',
-  'fpu_helper.c',
-  'int_helper.c',
-  'mem_helper.c',
-  'misc_helper.c',
-  'mpx_helper.c',
-  'seg_helper.c',
-  'smm_helper.c',
-  'svm_helper.c',
-  'translate.c'), if_false: files('tcg-stub.c'))
 i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-stub.c'))
 
 i386_softmmu_ss = ss.source_set()
@@ -32,6 +19,7 @@ subdir('kvm')
 subdir('hax')
 subdir('whpx')
 subdir('hvf')
+subdir('tcg')
 
 target_arch += {'i386': i386_ss}
 target_softmmu_arch += {'i386': i386_softmmu_ss}
diff --git a/target/i386/bpt_helper.c b/target/i386/tcg/bpt_helper.c
similarity index 100%
rename from target/i386/bpt_helper.c
rename to target/i386/tcg/bpt_helper.c
diff --git a/target/i386/cc_helper.c b/target/i386/tcg/cc_helper.c
similarity index 100%
rename from target/i386/cc_helper.c
rename to target/i386/tcg/cc_helper.c
diff --git a/target/i386/excp_helper.c b/target/i386/tcg/excp_helper.c
similarity index 100%
rename from target/i386/excp_helper.c
rename to target/i386/tcg/excp_helper.c
diff --git a/target/i386/fpu_helper.c b/target/i386/tcg/fpu_helper.c
similarity index 100%
rename from target/i386/fpu_helper.c
rename to target/i386/tcg/fpu_helper.c
diff --git a/target/i386/int_helper.c b/target/i386/tcg/int_helper.c
similarity index 100%
rename from target/i386/int_helper.c
rename to target/i386/tcg/int_helper.c
diff --git a/target/i386/mem_helper.c b/target/i386/tcg/mem_helper.c
similarity index 100%
rename from target/i386/mem_helper.c
rename to target/i386/tcg/mem_helper.c
diff --git a/target/i386/tcg/meson.build b/target/i386/tcg/meson.build
new file mode 100644
index 0000000000..02794226c2
--- /dev/null
+++ b/target/i386/tcg/meson.build
@@ -0,0 +1,13 @@
+i386_ss.add(when: 'CONFIG_TCG', if_true: files(
+  'bpt_helper.c',
+  'cc_helper.c',
+  'excp_helper.c',
+  'fpu_helper.c',
+  'int_helper.c',
+  'mem_helper.c',
+  'misc_helper.c',
+  'mpx_helper.c',
+  'seg_helper.c',
+  'smm_helper.c',
+  'svm_helper.c',
+  'translate.c'), if_false: files('tcg-stub.c'))
diff --git a/target/i386/misc_helper.c b/target/i386/tcg/misc_helper.c
similarity index 100%
rename from target/i386/misc_helper.c
rename to target/i386/tcg/misc_helper.c
diff --git a/target/i386/mpx_helper.c b/target/i386/tcg/mpx_helper.c
similarity index 100%
rename from target/i386/mpx_helper.c
rename to target/i386/tcg/mpx_helper.c
diff --git a/target/i386/seg_helper.c b/target/i386/tcg/seg_helper.c
similarity index 100%
rename from target/i386/seg_helper.c
rename to target/i386/tcg/seg_helper.c
diff --git a/target/i386/smm_helper.c b/target/i386/tcg/smm_helper.c
similarity index 100%
rename from target/i386/smm_helper.c
rename to target/i386/tcg/smm_helper.c
diff --git a/target/i386/svm_helper.c b/target/i386/tcg/svm_helper.c
similarity index 100%
rename from target/i386/svm_helper.c
rename to target/i386/tcg/svm_helper.c
diff --git a/target/i386/tcg-stub.c b/target/i386/tcg/tcg-stub.c
similarity index 100%
rename from target/i386/tcg-stub.c
rename to target/i386/tcg/tcg-stub.c
diff --git a/target/i386/translate.c b/target/i386/tcg/translate.c
similarity index 100%
rename from target/i386/translate.c
rename to target/i386/tcg/translate.c
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 06/12] i386: move cpu dump out of helper.c into cpu-dump.c
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (4 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 05/12] i386: move TCG accel files into tcg/ Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 07/12] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 target/i386/cpu-dump.c  | 538 ++++++++++++++++++++++++++++++++++++++++
 target/i386/cpu.h       |   1 +
 target/i386/helper.c    | 514 --------------------------------------
 target/i386/meson.build |   1 +
 4 files changed, 540 insertions(+), 514 deletions(-)
 create mode 100644 target/i386/cpu-dump.c

diff --git a/target/i386/cpu-dump.c b/target/i386/cpu-dump.c
new file mode 100644
index 0000000000..1ddc47fb0c
--- /dev/null
+++ b/target/i386/cpu-dump.c
@@ -0,0 +1,538 @@
+/*
+ *  i386 CPU dump to FILE
+ *
+ *  Copyright (c) 2003 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 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu/qemu-print.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/i386/apic_internal.h"
+#endif
+
+/***********************************************************/
+/* x86 debug */
+
+static const char *cc_op_str[CC_OP_NB] = {
+    "DYNAMIC",
+    "EFLAGS",
+
+    "MULB",
+    "MULW",
+    "MULL",
+    "MULQ",
+
+    "ADDB",
+    "ADDW",
+    "ADDL",
+    "ADDQ",
+
+    "ADCB",
+    "ADCW",
+    "ADCL",
+    "ADCQ",
+
+    "SUBB",
+    "SUBW",
+    "SUBL",
+    "SUBQ",
+
+    "SBBB",
+    "SBBW",
+    "SBBL",
+    "SBBQ",
+
+    "LOGICB",
+    "LOGICW",
+    "LOGICL",
+    "LOGICQ",
+
+    "INCB",
+    "INCW",
+    "INCL",
+    "INCQ",
+
+    "DECB",
+    "DECW",
+    "DECL",
+    "DECQ",
+
+    "SHLB",
+    "SHLW",
+    "SHLL",
+    "SHLQ",
+
+    "SARB",
+    "SARW",
+    "SARL",
+    "SARQ",
+
+    "BMILGB",
+    "BMILGW",
+    "BMILGL",
+    "BMILGQ",
+
+    "ADCX",
+    "ADOX",
+    "ADCOX",
+
+    "CLR",
+};
+
+static void
+cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f,
+                       const char *name, struct SegmentCache *sc)
+{
+#ifdef TARGET_X86_64
+    if (env->hflags & HF_CS64_MASK) {
+        qemu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
+                     sc->selector, sc->base, sc->limit,
+                     sc->flags & 0x00ffff00);
+    } else
+#endif
+    {
+        qemu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
+                     (uint32_t)sc->base, sc->limit,
+                     sc->flags & 0x00ffff00);
+    }
+
+    if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
+        goto done;
+
+    qemu_fprintf(f, " DPL=%d ",
+                 (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
+    if (sc->flags & DESC_S_MASK) {
+        if (sc->flags & DESC_CS_MASK) {
+            qemu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
+                         ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
+            qemu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
+                         (sc->flags & DESC_R_MASK) ? 'R' : '-');
+        } else {
+            qemu_fprintf(f, (sc->flags & DESC_B_MASK
+                             || env->hflags & HF_LMA_MASK)
+                         ? "DS  " : "DS16");
+            qemu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
+                         (sc->flags & DESC_W_MASK) ? 'W' : '-');
+        }
+        qemu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
+    } else {
+        static const char *sys_type_name[2][16] = {
+            { /* 32 bit mode */
+                "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
+                "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
+                "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
+                "CallGate32", "Reserved", "IntGate32", "TrapGate32"
+            },
+            { /* 64 bit mode */
+                "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
+                "Reserved", "Reserved", "Reserved", "Reserved",
+                "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
+                "Reserved", "IntGate64", "TrapGate64"
+            }
+        };
+        qemu_fprintf(f, "%s",
+                     sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
+                     [(sc->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT]);
+    }
+done:
+    qemu_fprintf(f, "\n");
+}
+
+#ifndef CONFIG_USER_ONLY
+
+/* ARRAY_SIZE check is not required because
+ * DeliveryMode(dm) has a size of 3 bit.
+ */
+static inline const char *dm2str(uint32_t dm)
+{
+    static const char *str[] = {
+        "Fixed",
+        "...",
+        "SMI",
+        "...",
+        "NMI",
+        "INIT",
+        "...",
+        "ExtINT"
+    };
+    return str[dm];
+}
+
+static void dump_apic_lvt(const char *name, uint32_t lvt, bool is_timer)
+{
+    uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
+    qemu_printf("%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
+                name, lvt,
+                lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
+                lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
+                lvt & APIC_LVT_MASKED ? "masked" : "",
+                lvt & APIC_LVT_DELIV_STS ? "pending" : "",
+                !is_timer ?
+                    "" : lvt & APIC_LVT_TIMER_PERIODIC ?
+                            "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
+                                            "tsc-deadline" : "one-shot",
+                dm2str(dm));
+    if (dm != APIC_DM_NMI) {
+        qemu_printf(" (vec %u)\n", lvt & APIC_VECTOR_MASK);
+    } else {
+        qemu_printf("\n");
+    }
+}
+
+/* ARRAY_SIZE check is not required because
+ * destination shorthand has a size of 2 bit.
+ */
+static inline const char *shorthand2str(uint32_t shorthand)
+{
+    const char *str[] = {
+        "no-shorthand", "self", "all-self", "all"
+    };
+    return str[shorthand];
+}
+
+static inline uint8_t divider_conf(uint32_t divide_conf)
+{
+    uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
+
+    return divide_val == 7 ? 1 : 2 << divide_val;
+}
+
+static inline void mask2str(char *str, uint32_t val, uint8_t size)
+{
+    while (size--) {
+        *str++ = (val >> size) & 1 ? '1' : '0';
+    }
+    *str = 0;
+}
+
+#define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
+
+static void dump_apic_icr(APICCommonState *s, CPUX86State *env)
+{
+    uint32_t icr = s->icr[0], icr2 = s->icr[1];
+    uint8_t dest_shorthand = \
+        (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
+    bool logical_mod = icr & APIC_ICR_DEST_MOD;
+    char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
+    uint32_t dest_field;
+    bool x2apic;
+
+    qemu_printf("ICR\t 0x%08x %s %s %s %s\n",
+                icr,
+                logical_mod ? "logical" : "physical",
+                icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
+                icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
+                shorthand2str(dest_shorthand));
+
+    qemu_printf("ICR2\t 0x%08x", icr2);
+    if (dest_shorthand != 0) {
+        qemu_printf("\n");
+        return;
+    }
+    x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
+    dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
+
+    if (!logical_mod) {
+        if (x2apic) {
+            qemu_printf(" cpu %u (X2APIC ID)\n", dest_field);
+        } else {
+            qemu_printf(" cpu %u (APIC ID)\n",
+                        dest_field & APIC_LOGDEST_XAPIC_ID);
+        }
+        return;
+    }
+
+    if (s->dest_mode == 0xf) { /* flat mode */
+        mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
+        qemu_printf(" mask %s (APIC ID)\n", apic_id_str);
+    } else if (s->dest_mode == 0) { /* cluster mode */
+        if (x2apic) {
+            mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
+            qemu_printf(" cluster %u mask %s (X2APIC ID)\n",
+                        dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
+        } else {
+            mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
+            qemu_printf(" cluster %u mask %s (APIC ID)\n",
+                        dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
+        }
+    }
+}
+
+static void dump_apic_interrupt(const char *name, uint32_t *ireg_tab,
+                                uint32_t *tmr_tab)
+{
+    int i, empty = true;
+
+    qemu_printf("%s\t ", name);
+    for (i = 0; i < 256; i++) {
+        if (apic_get_bit(ireg_tab, i)) {
+            qemu_printf("%u%s ", i,
+                        apic_get_bit(tmr_tab, i) ? "(level)" : "");
+            empty = false;
+        }
+    }
+    qemu_printf("%s\n", empty ? "(none)" : "");
+}
+
+void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    APICCommonState *s = APIC_COMMON(cpu->apic_state);
+    if (!s) {
+        qemu_printf("local apic state not available\n");
+        return;
+    }
+    uint32_t *lvt = s->lvt;
+
+    qemu_printf("dumping local APIC state for CPU %-2u\n\n",
+                CPU(cpu)->cpu_index);
+    dump_apic_lvt("LVT0", lvt[APIC_LVT_LINT0], false);
+    dump_apic_lvt("LVT1", lvt[APIC_LVT_LINT1], false);
+    dump_apic_lvt("LVTPC", lvt[APIC_LVT_PERFORM], false);
+    dump_apic_lvt("LVTERR", lvt[APIC_LVT_ERROR], false);
+    dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false);
+    dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true);
+
+    qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u"
+                " current_count = %u\n",
+                s->divide_conf & APIC_DCR_MASK,
+                divider_conf(s->divide_conf),
+                s->initial_count, apic_get_current_count(s));
+
+    qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
+                s->spurious_vec,
+                s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
+                s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
+                s->spurious_vec & APIC_VECTOR_MASK);
+
+    dump_apic_icr(s, &cpu->env);
+
+    qemu_printf("ESR\t 0x%08x\n", s->esr);
+
+    dump_apic_interrupt("ISR", s->isr, s->tmr);
+    dump_apic_interrupt("IRR", s->irr, s->tmr);
+
+    qemu_printf("\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
+                s->arb_id, s->tpr, s->dest_mode, s->log_dest);
+    if (s->dest_mode == 0) {
+        qemu_printf("(cluster %u: id %u)",
+                    s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
+                    s->log_dest & APIC_LOGDEST_XAPIC_ID);
+    }
+    qemu_printf(" PPR 0x%02x\n", apic_get_ppr(s));
+}
+#else
+void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
+{
+}
+#endif /* !CONFIG_USER_ONLY */
+
+#define DUMP_CODE_BYTES_TOTAL    50
+#define DUMP_CODE_BYTES_BACKWARD 20
+
+void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+    int eflags, i, nb;
+    char cc_op_name[32];
+    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
+
+    eflags = cpu_compute_eflags(env);
+#ifdef TARGET_X86_64
+    if (env->hflags & HF_CS64_MASK) {
+        qemu_fprintf(f, "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
+                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
+                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
+                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
+                     "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
+                     env->regs[R_EAX],
+                     env->regs[R_EBX],
+                     env->regs[R_ECX],
+                     env->regs[R_EDX],
+                     env->regs[R_ESI],
+                     env->regs[R_EDI],
+                     env->regs[R_EBP],
+                     env->regs[R_ESP],
+                     env->regs[8],
+                     env->regs[9],
+                     env->regs[10],
+                     env->regs[11],
+                     env->regs[12],
+                     env->regs[13],
+                     env->regs[14],
+                     env->regs[15],
+                     env->eip, eflags,
+                     eflags & DF_MASK ? 'D' : '-',
+                     eflags & CC_O ? 'O' : '-',
+                     eflags & CC_S ? 'S' : '-',
+                     eflags & CC_Z ? 'Z' : '-',
+                     eflags & CC_A ? 'A' : '-',
+                     eflags & CC_P ? 'P' : '-',
+                     eflags & CC_C ? 'C' : '-',
+                     env->hflags & HF_CPL_MASK,
+                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
+                     (env->a20_mask >> 20) & 1,
+                     (env->hflags >> HF_SMM_SHIFT) & 1,
+                     cs->halted);
+    } else
+#endif
+    {
+        qemu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
+                     "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
+                     "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
+                     (uint32_t)env->regs[R_EAX],
+                     (uint32_t)env->regs[R_EBX],
+                     (uint32_t)env->regs[R_ECX],
+                     (uint32_t)env->regs[R_EDX],
+                     (uint32_t)env->regs[R_ESI],
+                     (uint32_t)env->regs[R_EDI],
+                     (uint32_t)env->regs[R_EBP],
+                     (uint32_t)env->regs[R_ESP],
+                     (uint32_t)env->eip, eflags,
+                     eflags & DF_MASK ? 'D' : '-',
+                     eflags & CC_O ? 'O' : '-',
+                     eflags & CC_S ? 'S' : '-',
+                     eflags & CC_Z ? 'Z' : '-',
+                     eflags & CC_A ? 'A' : '-',
+                     eflags & CC_P ? 'P' : '-',
+                     eflags & CC_C ? 'C' : '-',
+                     env->hflags & HF_CPL_MASK,
+                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
+                     (env->a20_mask >> 20) & 1,
+                     (env->hflags >> HF_SMM_SHIFT) & 1,
+                     cs->halted);
+    }
+
+    for(i = 0; i < 6; i++) {
+        cpu_x86_dump_seg_cache(env, f, seg_name[i], &env->segs[i]);
+    }
+    cpu_x86_dump_seg_cache(env, f, "LDT", &env->ldt);
+    cpu_x86_dump_seg_cache(env, f, "TR", &env->tr);
+
+#ifdef TARGET_X86_64
+    if (env->hflags & HF_LMA_MASK) {
+        qemu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
+                     env->gdt.base, env->gdt.limit);
+        qemu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
+                     env->idt.base, env->idt.limit);
+        qemu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
+                     (uint32_t)env->cr[0],
+                     env->cr[2],
+                     env->cr[3],
+                     (uint32_t)env->cr[4]);
+        for(i = 0; i < 4; i++)
+            qemu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
+        qemu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
+                     env->dr[6], env->dr[7]);
+    } else
+#endif
+    {
+        qemu_fprintf(f, "GDT=     %08x %08x\n",
+                     (uint32_t)env->gdt.base, env->gdt.limit);
+        qemu_fprintf(f, "IDT=     %08x %08x\n",
+                     (uint32_t)env->idt.base, env->idt.limit);
+        qemu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
+                     (uint32_t)env->cr[0],
+                     (uint32_t)env->cr[2],
+                     (uint32_t)env->cr[3],
+                     (uint32_t)env->cr[4]);
+        for(i = 0; i < 4; i++) {
+            qemu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
+        }
+        qemu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
+                     env->dr[6], env->dr[7]);
+    }
+    if (flags & CPU_DUMP_CCOP) {
+        if ((unsigned)env->cc_op < CC_OP_NB)
+            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
+        else
+            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
+#ifdef TARGET_X86_64
+        if (env->hflags & HF_CS64_MASK) {
+            qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
+                         env->cc_src, env->cc_dst,
+                         cc_op_name);
+        } else
+#endif
+        {
+            qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
+                         (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
+                         cc_op_name);
+        }
+    }
+    qemu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
+    if (flags & CPU_DUMP_FPU) {
+        int fptag;
+        fptag = 0;
+        for(i = 0; i < 8; i++) {
+            fptag |= ((!env->fptags[i]) << i);
+        }
+        update_mxcsr_from_sse_status(env);
+        qemu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
+                     env->fpuc,
+                     (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
+                     env->fpstt,
+                     fptag,
+                     env->mxcsr);
+        for(i=0;i<8;i++) {
+            CPU_LDoubleU u;
+            u.d = env->fpregs[i].d;
+            qemu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
+                         i, u.l.lower, u.l.upper);
+            if ((i & 1) == 1)
+                qemu_fprintf(f, "\n");
+            else
+                qemu_fprintf(f, " ");
+        }
+        if (env->hflags & HF_CS64_MASK)
+            nb = 16;
+        else
+            nb = 8;
+        for(i=0;i<nb;i++) {
+            qemu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
+                         i,
+                         env->xmm_regs[i].ZMM_L(3),
+                         env->xmm_regs[i].ZMM_L(2),
+                         env->xmm_regs[i].ZMM_L(1),
+                         env->xmm_regs[i].ZMM_L(0));
+            if ((i & 1) == 1)
+                qemu_fprintf(f, "\n");
+            else
+                qemu_fprintf(f, " ");
+        }
+    }
+    if (flags & CPU_DUMP_CODE) {
+        target_ulong base = env->segs[R_CS].base + env->eip;
+        target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
+        uint8_t code;
+        char codestr[3];
+
+        qemu_fprintf(f, "Code=");
+        for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
+            if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
+                snprintf(codestr, sizeof(codestr), "%02x", code);
+            } else {
+                snprintf(codestr, sizeof(codestr), "??");
+            }
+            qemu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
+                         i == offs ? "<" : "", codestr, i == offs ? ">" : "");
+        }
+        qemu_fprintf(f, "\n");
+    }
+}
+
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9ecda75aec..d6ed45c5d7 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2232,6 +2232,7 @@ void enable_compat_apic_id_mode(void);
 #define APIC_DEFAULT_ADDRESS 0xfee00000
 #define APIC_SPACE_SIZE      0x100000
 
+/* cpu-dump.c */
 void x86_cpu_dump_local_apic_state(CPUState *cs, int flags);
 
 /* cpu.c */
diff --git a/target/i386/helper.c b/target/i386/helper.c
index a1b3367ab2..6e7e0f507c 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -21,8 +21,6 @@
 #include "qapi/qapi-events-run-state.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
-#include "qemu/qemu-print.h"
-#include "sysemu/kvm.h"
 #include "sysemu/runstate.h"
 #include "kvm/kvm_i386.h"
 #ifndef CONFIG_USER_ONLY
@@ -88,518 +86,6 @@ int cpu_x86_support_mca_broadcast(CPUX86State *env)
     return 0;
 }
 
-/***********************************************************/
-/* x86 debug */
-
-static const char *cc_op_str[CC_OP_NB] = {
-    "DYNAMIC",
-    "EFLAGS",
-
-    "MULB",
-    "MULW",
-    "MULL",
-    "MULQ",
-
-    "ADDB",
-    "ADDW",
-    "ADDL",
-    "ADDQ",
-
-    "ADCB",
-    "ADCW",
-    "ADCL",
-    "ADCQ",
-
-    "SUBB",
-    "SUBW",
-    "SUBL",
-    "SUBQ",
-
-    "SBBB",
-    "SBBW",
-    "SBBL",
-    "SBBQ",
-
-    "LOGICB",
-    "LOGICW",
-    "LOGICL",
-    "LOGICQ",
-
-    "INCB",
-    "INCW",
-    "INCL",
-    "INCQ",
-
-    "DECB",
-    "DECW",
-    "DECL",
-    "DECQ",
-
-    "SHLB",
-    "SHLW",
-    "SHLL",
-    "SHLQ",
-
-    "SARB",
-    "SARW",
-    "SARL",
-    "SARQ",
-
-    "BMILGB",
-    "BMILGW",
-    "BMILGL",
-    "BMILGQ",
-
-    "ADCX",
-    "ADOX",
-    "ADCOX",
-
-    "CLR",
-};
-
-static void
-cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f,
-                       const char *name, struct SegmentCache *sc)
-{
-#ifdef TARGET_X86_64
-    if (env->hflags & HF_CS64_MASK) {
-        qemu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
-                     sc->selector, sc->base, sc->limit,
-                     sc->flags & 0x00ffff00);
-    } else
-#endif
-    {
-        qemu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
-                     (uint32_t)sc->base, sc->limit,
-                     sc->flags & 0x00ffff00);
-    }
-
-    if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
-        goto done;
-
-    qemu_fprintf(f, " DPL=%d ",
-                 (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
-    if (sc->flags & DESC_S_MASK) {
-        if (sc->flags & DESC_CS_MASK) {
-            qemu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
-                         ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
-            qemu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
-                         (sc->flags & DESC_R_MASK) ? 'R' : '-');
-        } else {
-            qemu_fprintf(f, (sc->flags & DESC_B_MASK
-                             || env->hflags & HF_LMA_MASK)
-                         ? "DS  " : "DS16");
-            qemu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
-                         (sc->flags & DESC_W_MASK) ? 'W' : '-');
-        }
-        qemu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
-    } else {
-        static const char *sys_type_name[2][16] = {
-            { /* 32 bit mode */
-                "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
-                "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
-                "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
-                "CallGate32", "Reserved", "IntGate32", "TrapGate32"
-            },
-            { /* 64 bit mode */
-                "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
-                "Reserved", "Reserved", "Reserved", "Reserved",
-                "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
-                "Reserved", "IntGate64", "TrapGate64"
-            }
-        };
-        qemu_fprintf(f, "%s",
-                     sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
-                     [(sc->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT]);
-    }
-done:
-    qemu_fprintf(f, "\n");
-}
-
-#ifndef CONFIG_USER_ONLY
-
-/* ARRAY_SIZE check is not required because
- * DeliveryMode(dm) has a size of 3 bit.
- */
-static inline const char *dm2str(uint32_t dm)
-{
-    static const char *str[] = {
-        "Fixed",
-        "...",
-        "SMI",
-        "...",
-        "NMI",
-        "INIT",
-        "...",
-        "ExtINT"
-    };
-    return str[dm];
-}
-
-static void dump_apic_lvt(const char *name, uint32_t lvt, bool is_timer)
-{
-    uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
-    qemu_printf("%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s",
-                name, lvt,
-                lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi",
-                lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge",
-                lvt & APIC_LVT_MASKED ? "masked" : "",
-                lvt & APIC_LVT_DELIV_STS ? "pending" : "",
-                !is_timer ?
-                    "" : lvt & APIC_LVT_TIMER_PERIODIC ?
-                            "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ?
-                                            "tsc-deadline" : "one-shot",
-                dm2str(dm));
-    if (dm != APIC_DM_NMI) {
-        qemu_printf(" (vec %u)\n", lvt & APIC_VECTOR_MASK);
-    } else {
-        qemu_printf("\n");
-    }
-}
-
-/* ARRAY_SIZE check is not required because
- * destination shorthand has a size of 2 bit.
- */
-static inline const char *shorthand2str(uint32_t shorthand)
-{
-    const char *str[] = {
-        "no-shorthand", "self", "all-self", "all"
-    };
-    return str[shorthand];
-}
-
-static inline uint8_t divider_conf(uint32_t divide_conf)
-{
-    uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3);
-
-    return divide_val == 7 ? 1 : 2 << divide_val;
-}
-
-static inline void mask2str(char *str, uint32_t val, uint8_t size)
-{
-    while (size--) {
-        *str++ = (val >> size) & 1 ? '1' : '0';
-    }
-    *str = 0;
-}
-
-#define MAX_LOGICAL_APIC_ID_MASK_SIZE 16
-
-static void dump_apic_icr(APICCommonState *s, CPUX86State *env)
-{
-    uint32_t icr = s->icr[0], icr2 = s->icr[1];
-    uint8_t dest_shorthand = \
-        (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT;
-    bool logical_mod = icr & APIC_ICR_DEST_MOD;
-    char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1];
-    uint32_t dest_field;
-    bool x2apic;
-
-    qemu_printf("ICR\t 0x%08x %s %s %s %s\n",
-                icr,
-                logical_mod ? "logical" : "physical",
-                icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge",
-                icr & APIC_ICR_LEVEL ? "assert" : "de-assert",
-                shorthand2str(dest_shorthand));
-
-    qemu_printf("ICR2\t 0x%08x", icr2);
-    if (dest_shorthand != 0) {
-        qemu_printf("\n");
-        return;
-    }
-    x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC;
-    dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT;
-
-    if (!logical_mod) {
-        if (x2apic) {
-            qemu_printf(" cpu %u (X2APIC ID)\n", dest_field);
-        } else {
-            qemu_printf(" cpu %u (APIC ID)\n",
-                        dest_field & APIC_LOGDEST_XAPIC_ID);
-        }
-        return;
-    }
-
-    if (s->dest_mode == 0xf) { /* flat mode */
-        mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8);
-        qemu_printf(" mask %s (APIC ID)\n", apic_id_str);
-    } else if (s->dest_mode == 0) { /* cluster mode */
-        if (x2apic) {
-            mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16);
-            qemu_printf(" cluster %u mask %s (X2APIC ID)\n",
-                        dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str);
-        } else {
-            mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4);
-            qemu_printf(" cluster %u mask %s (APIC ID)\n",
-                        dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str);
-        }
-    }
-}
-
-static void dump_apic_interrupt(const char *name, uint32_t *ireg_tab,
-                                uint32_t *tmr_tab)
-{
-    int i, empty = true;
-
-    qemu_printf("%s\t ", name);
-    for (i = 0; i < 256; i++) {
-        if (apic_get_bit(ireg_tab, i)) {
-            qemu_printf("%u%s ", i,
-                        apic_get_bit(tmr_tab, i) ? "(level)" : "");
-            empty = false;
-        }
-    }
-    qemu_printf("%s\n", empty ? "(none)" : "");
-}
-
-void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    APICCommonState *s = APIC_COMMON(cpu->apic_state);
-    if (!s) {
-        qemu_printf("local apic state not available\n");
-        return;
-    }
-    uint32_t *lvt = s->lvt;
-
-    qemu_printf("dumping local APIC state for CPU %-2u\n\n",
-                CPU(cpu)->cpu_index);
-    dump_apic_lvt("LVT0", lvt[APIC_LVT_LINT0], false);
-    dump_apic_lvt("LVT1", lvt[APIC_LVT_LINT1], false);
-    dump_apic_lvt("LVTPC", lvt[APIC_LVT_PERFORM], false);
-    dump_apic_lvt("LVTERR", lvt[APIC_LVT_ERROR], false);
-    dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false);
-    dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true);
-
-    qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u"
-                " current_count = %u\n",
-                s->divide_conf & APIC_DCR_MASK,
-                divider_conf(s->divide_conf),
-                s->initial_count, apic_get_current_count(s));
-
-    qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
-                s->spurious_vec,
-                s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled",
-                s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off",
-                s->spurious_vec & APIC_VECTOR_MASK);
-
-    dump_apic_icr(s, &cpu->env);
-
-    qemu_printf("ESR\t 0x%08x\n", s->esr);
-
-    dump_apic_interrupt("ISR", s->isr, s->tmr);
-    dump_apic_interrupt("IRR", s->irr, s->tmr);
-
-    qemu_printf("\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x",
-                s->arb_id, s->tpr, s->dest_mode, s->log_dest);
-    if (s->dest_mode == 0) {
-        qemu_printf("(cluster %u: id %u)",
-                    s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT,
-                    s->log_dest & APIC_LOGDEST_XAPIC_ID);
-    }
-    qemu_printf(" PPR 0x%02x\n", apic_get_ppr(s));
-}
-#else
-void x86_cpu_dump_local_apic_state(CPUState *cs, int flags)
-{
-}
-#endif /* !CONFIG_USER_ONLY */
-
-#define DUMP_CODE_BYTES_TOTAL    50
-#define DUMP_CODE_BYTES_BACKWARD 20
-
-void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-    int eflags, i, nb;
-    char cc_op_name[32];
-    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
-
-    eflags = cpu_compute_eflags(env);
-#ifdef TARGET_X86_64
-    if (env->hflags & HF_CS64_MASK) {
-        qemu_fprintf(f, "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
-                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
-                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
-                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
-                     "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
-                     env->regs[R_EAX],
-                     env->regs[R_EBX],
-                     env->regs[R_ECX],
-                     env->regs[R_EDX],
-                     env->regs[R_ESI],
-                     env->regs[R_EDI],
-                     env->regs[R_EBP],
-                     env->regs[R_ESP],
-                     env->regs[8],
-                     env->regs[9],
-                     env->regs[10],
-                     env->regs[11],
-                     env->regs[12],
-                     env->regs[13],
-                     env->regs[14],
-                     env->regs[15],
-                     env->eip, eflags,
-                     eflags & DF_MASK ? 'D' : '-',
-                     eflags & CC_O ? 'O' : '-',
-                     eflags & CC_S ? 'S' : '-',
-                     eflags & CC_Z ? 'Z' : '-',
-                     eflags & CC_A ? 'A' : '-',
-                     eflags & CC_P ? 'P' : '-',
-                     eflags & CC_C ? 'C' : '-',
-                     env->hflags & HF_CPL_MASK,
-                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
-                     (env->a20_mask >> 20) & 1,
-                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                     cs->halted);
-    } else
-#endif
-    {
-        qemu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
-                     "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
-                     "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
-                     (uint32_t)env->regs[R_EAX],
-                     (uint32_t)env->regs[R_EBX],
-                     (uint32_t)env->regs[R_ECX],
-                     (uint32_t)env->regs[R_EDX],
-                     (uint32_t)env->regs[R_ESI],
-                     (uint32_t)env->regs[R_EDI],
-                     (uint32_t)env->regs[R_EBP],
-                     (uint32_t)env->regs[R_ESP],
-                     (uint32_t)env->eip, eflags,
-                     eflags & DF_MASK ? 'D' : '-',
-                     eflags & CC_O ? 'O' : '-',
-                     eflags & CC_S ? 'S' : '-',
-                     eflags & CC_Z ? 'Z' : '-',
-                     eflags & CC_A ? 'A' : '-',
-                     eflags & CC_P ? 'P' : '-',
-                     eflags & CC_C ? 'C' : '-',
-                     env->hflags & HF_CPL_MASK,
-                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
-                     (env->a20_mask >> 20) & 1,
-                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                     cs->halted);
-    }
-
-    for(i = 0; i < 6; i++) {
-        cpu_x86_dump_seg_cache(env, f, seg_name[i], &env->segs[i]);
-    }
-    cpu_x86_dump_seg_cache(env, f, "LDT", &env->ldt);
-    cpu_x86_dump_seg_cache(env, f, "TR", &env->tr);
-
-#ifdef TARGET_X86_64
-    if (env->hflags & HF_LMA_MASK) {
-        qemu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
-                     env->gdt.base, env->gdt.limit);
-        qemu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
-                     env->idt.base, env->idt.limit);
-        qemu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
-                     (uint32_t)env->cr[0],
-                     env->cr[2],
-                     env->cr[3],
-                     (uint32_t)env->cr[4]);
-        for(i = 0; i < 4; i++)
-            qemu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
-        qemu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
-                     env->dr[6], env->dr[7]);
-    } else
-#endif
-    {
-        qemu_fprintf(f, "GDT=     %08x %08x\n",
-                     (uint32_t)env->gdt.base, env->gdt.limit);
-        qemu_fprintf(f, "IDT=     %08x %08x\n",
-                     (uint32_t)env->idt.base, env->idt.limit);
-        qemu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
-                     (uint32_t)env->cr[0],
-                     (uint32_t)env->cr[2],
-                     (uint32_t)env->cr[3],
-                     (uint32_t)env->cr[4]);
-        for(i = 0; i < 4; i++) {
-            qemu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
-        }
-        qemu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
-                     env->dr[6], env->dr[7]);
-    }
-    if (flags & CPU_DUMP_CCOP) {
-        if ((unsigned)env->cc_op < CC_OP_NB)
-            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
-        else
-            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
-#ifdef TARGET_X86_64
-        if (env->hflags & HF_CS64_MASK) {
-            qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
-                         env->cc_src, env->cc_dst,
-                         cc_op_name);
-        } else
-#endif
-        {
-            qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
-                         (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
-                         cc_op_name);
-        }
-    }
-    qemu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
-    if (flags & CPU_DUMP_FPU) {
-        int fptag;
-        fptag = 0;
-        for(i = 0; i < 8; i++) {
-            fptag |= ((!env->fptags[i]) << i);
-        }
-        update_mxcsr_from_sse_status(env);
-        qemu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
-                     env->fpuc,
-                     (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
-                     env->fpstt,
-                     fptag,
-                     env->mxcsr);
-        for(i=0;i<8;i++) {
-            CPU_LDoubleU u;
-            u.d = env->fpregs[i].d;
-            qemu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
-                         i, u.l.lower, u.l.upper);
-            if ((i & 1) == 1)
-                qemu_fprintf(f, "\n");
-            else
-                qemu_fprintf(f, " ");
-        }
-        if (env->hflags & HF_CS64_MASK)
-            nb = 16;
-        else
-            nb = 8;
-        for(i=0;i<nb;i++) {
-            qemu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
-                         i,
-                         env->xmm_regs[i].ZMM_L(3),
-                         env->xmm_regs[i].ZMM_L(2),
-                         env->xmm_regs[i].ZMM_L(1),
-                         env->xmm_regs[i].ZMM_L(0));
-            if ((i & 1) == 1)
-                qemu_fprintf(f, "\n");
-            else
-                qemu_fprintf(f, " ");
-        }
-    }
-    if (flags & CPU_DUMP_CODE) {
-        target_ulong base = env->segs[R_CS].base + env->eip;
-        target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
-        uint8_t code;
-        char codestr[3];
-
-        qemu_fprintf(f, "Code=");
-        for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
-            if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) {
-                snprintf(codestr, sizeof(codestr), "%02x", code);
-            } else {
-                snprintf(codestr, sizeof(codestr), "??");
-            }
-            qemu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
-                         i == offs ? "<" : "", codestr, i == offs ? ">" : "");
-        }
-        qemu_fprintf(f, "\n");
-    }
-}
-
 /***********************************************************/
 /* x86 mmu */
 /* XXX: add PGE support */
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 750471c9f3..c4bf20b319 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -4,6 +4,7 @@ i386_ss.add(files(
   'gdbstub.c',
   'helper.c',
   'xsave_helper.c',
+  'cpu-dump.c',
 ))
 i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-stub.c'))
 
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 07/12] i386: move TCG cpu class initialization out of helper.c
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (5 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 06/12] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode Claudio Fontana
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 target/i386/cpu.c             |  33 ++++------
 target/i386/cpu.h             |  97 ++---------------------------
 target/i386/helper-tcg.h      | 112 ++++++++++++++++++++++++++++++++++
 target/i386/helper.c          |  23 -------
 target/i386/meson.build       |   1 +
 target/i386/tcg-cpu.c         |  71 +++++++++++++++++++++
 target/i386/tcg-cpu.h         |  15 +++++
 target/i386/tcg/bpt_helper.c  |   1 +
 target/i386/tcg/cc_helper.c   |   1 +
 target/i386/tcg/excp_helper.c |   1 +
 target/i386/tcg/fpu_helper.c  |  33 +++++-----
 target/i386/tcg/int_helper.c  |   1 +
 target/i386/tcg/mem_helper.c  |   1 +
 target/i386/tcg/misc_helper.c |   1 +
 target/i386/tcg/mpx_helper.c  |   1 +
 target/i386/tcg/seg_helper.c  |   1 +
 target/i386/tcg/smm_helper.c  |   2 +
 target/i386/tcg/svm_helper.c  |   1 +
 target/i386/tcg/translate.c   |   1 +
 19 files changed, 244 insertions(+), 153 deletions(-)
 create mode 100644 target/i386/helper-tcg.h
 create mode 100644 target/i386/tcg-cpu.c
 create mode 100644 target/i386/tcg-cpu.h

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b9bd249c8f..3462d0143f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -24,6 +24,8 @@
 #include "qemu/qemu-print.h"
 
 #include "cpu.h"
+#include "tcg-cpu.h"
+#include "helper-tcg.h"
 #include "exec/exec-all.h"
 #include "sysemu/kvm.h"
 #include "sysemu/reset.h"
@@ -1495,7 +1497,8 @@ static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
            cpu->env.features[FEAT_XSAVE_COMP_LO];
 }
 
-const char *get_register_name_32(unsigned int reg)
+/* Return name of 32-bit register, from a R_* constant */
+static const char *get_register_name_32(unsigned int reg)
 {
     if (reg >= CPU_NB_REGS32) {
         return NULL;
@@ -7012,13 +7015,6 @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.eip = value;
 }
 
-static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
-{
-    X86CPU *cpu = X86_CPU(cs);
-
-    cpu->env.eip = tb->pc - tb->cs_base;
-}
-
 int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request)
 {
     X86CPU *cpu = X86_CPU(cs);
@@ -7252,17 +7248,18 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     cc->class_by_name = x86_cpu_class_by_name;
     cc->parse_features = x86_cpu_parse_featurestr;
     cc->has_work = x86_cpu_has_work;
+
 #ifdef CONFIG_TCG
-    cc->do_interrupt = x86_cpu_do_interrupt;
-    cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
-#endif
+    tcg_cpu_common_class_init(cc);
+#endif /* CONFIG_TCG */
+
     cc->dump_state = x86_cpu_dump_state;
     cc->set_pc = x86_cpu_set_pc;
-    cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
     cc->gdb_read_register = x86_cpu_gdb_read_register;
     cc->gdb_write_register = x86_cpu_gdb_write_register;
     cc->get_arch_id = x86_cpu_get_arch_id;
     cc->get_paging_enabled = x86_cpu_get_paging_enabled;
+
 #ifndef CONFIG_USER_ONLY
     cc->asidx_from_attrs = x86_asidx_from_attrs;
     cc->get_memory_mapping = x86_cpu_get_memory_mapping;
@@ -7273,7 +7270,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     cc->write_elf32_note = x86_cpu_write_elf32_note;
     cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
     cc->vmsd = &vmstate_x86_cpu;
-#endif
+#endif /* !CONFIG_USER_ONLY */
+
     cc->gdb_arch_name = x86_gdb_arch_name;
 #ifdef TARGET_X86_64
     cc->gdb_core_xml_file = "i386-64bit.xml";
@@ -7281,15 +7279,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 #else
     cc->gdb_core_xml_file = "i386-32bit.xml";
     cc->gdb_num_core_regs = 50;
-#endif
-#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
-    cc->debug_excp_handler = breakpoint_handler;
-#endif
-    cc->cpu_exec_enter = x86_cpu_exec_enter;
-    cc->cpu_exec_exit = x86_cpu_exec_exit;
-#ifdef CONFIG_TCG
-    cc->tcg_initialize = tcg_x86_init;
-    cc->tlb_fill = x86_cpu_tlb_fill;
 #endif
     cc->disas_set_info = x86_disas_set_info;
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d6ed45c5d7..a0d64613dc 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -31,9 +31,6 @@
 
 #define KVM_HAVE_MCE_INJECTION 1
 
-/* Maximum instruction code size */
-#define TARGET_MAX_INSN_SIZE 16
-
 /* support for self modifying code even if the modified instruction is
    close to the modifying instruction */
 #define TARGET_HAS_PRECISE_SMC
@@ -1037,6 +1034,12 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
  * using this information. Condition codes are not generated if they
  * are only needed for conditional branches.
  */
+
+#define CC_DST  (env->cc_dst)
+#define CC_SRC  (env->cc_src)
+#define CC_SRC2 (env->cc_src2)
+#define CC_OP   (env->cc_op)
+
 typedef enum {
     CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
     CC_OP_EFLAGS,  /* all cc are explicitly computed, CC_SRC = flags */
@@ -1765,12 +1768,6 @@ struct X86CPU {
 extern VMStateDescription vmstate_x86_cpu;
 #endif
 
-/**
- * x86_cpu_do_interrupt:
- * @cpu: vCPU the interrupt is to be handled by.
- */
-void x86_cpu_do_interrupt(CPUState *cpu);
-bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
 int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
 
 int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
@@ -1793,9 +1790,6 @@ hwaddr x86_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
 int x86_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
-void x86_cpu_exec_enter(CPUState *cpu);
-void x86_cpu_exec_exit(CPUState *cpu);
-
 void x86_cpu_list(void);
 int cpu_x86_support_mca_broadcast(CPUX86State *env);
 
@@ -1920,9 +1914,6 @@ void host_cpuid(uint32_t function, uint32_t count,
 void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);
 
 /* helper.c */
-bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
-                      MMUAccessType access_type, int mmu_idx,
-                      bool probe, uintptr_t retaddr);
 void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
 
 #ifndef CONFIG_USER_ONLY
@@ -1947,8 +1938,6 @@ void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val);
 void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val);
 #endif
 
-void breakpoint_handler(CPUState *cs);
-
 /* will be suppressed */
 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
@@ -1958,16 +1947,6 @@ void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7);
 /* hw/pc.c */
 uint64_t cpu_get_tsc(CPUX86State *env);
 
-/* XXX: This value should match the one returned by CPUID
- * and in exec.c */
-# if defined(TARGET_X86_64)
-# define TCG_PHYS_ADDR_BITS 40
-# else
-# define TCG_PHYS_ADDR_BITS 36
-# endif
-
-#define PHYS_ADDR_MASK MAKE_64BIT_MASK(0, TCG_PHYS_ADDR_BITS)
-
 #define X86_CPU_TYPE_SUFFIX "-" TYPE_X86_CPU
 #define X86_CPU_TYPE_NAME(name) (name X86_CPU_TYPE_SUFFIX)
 #define CPU_RESOLVING_TYPE TYPE_X86_CPU
@@ -1999,30 +1978,6 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
         ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
 }
 
-#define CC_DST  (env->cc_dst)
-#define CC_SRC  (env->cc_src)
-#define CC_SRC2 (env->cc_src2)
-#define CC_OP   (env->cc_op)
-
-/* n must be a constant to be efficient */
-static inline target_long lshift(target_long x, int n)
-{
-    if (n >= 0) {
-        return x << n;
-    } else {
-        return x >> (-n);
-    }
-}
-
-/* float macros */
-#define FT0    (env->ft0)
-#define ST0    (env->fpregs[env->fpstt].d)
-#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7].d)
-#define ST1    ST(1)
-
-/* translate.c */
-void tcg_x86_init(void);
-
 typedef CPUX86State CPUArchState;
 typedef X86CPU ArchCPU;
 
@@ -2052,19 +2007,6 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
                         uint64_t misc, int flags);
 
-/* excp_helper.c */
-void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index);
-void QEMU_NORETURN raise_exception_ra(CPUX86State *env, int exception_index,
-                                      uintptr_t retaddr);
-void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index,
-                                       int error_code);
-void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index,
-                                          int error_code, uintptr_t retaddr);
-void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int,
-                                   int error_code, int next_eip_addend);
-
-/* cc_helper.c */
-extern const uint8_t parity_table[256];
 uint32_t cpu_cc_compute_all(CPUX86State *env1, int op);
 
 static inline uint32_t cpu_compute_eflags(CPUX86State *env)
@@ -2076,18 +2018,6 @@ static inline uint32_t cpu_compute_eflags(CPUX86State *env)
     return eflags;
 }
 
-/* NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
- * after generating a call to a helper that uses this.
- */
-static inline void cpu_load_eflags(CPUX86State *env, int eflags,
-                                   int update_mask)
-{
-    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    CC_OP = CC_OP_EFLAGS;
-    env->df = 1 - (2 * ((eflags >> 10) & 1));
-    env->eflags = (env->eflags & ~update_mask) |
-        (eflags & update_mask) | 0x2;
-}
 
 /* load efer and update the corresponding hflags. XXX: do consistency
    checks with cpuid bits? */
@@ -2176,16 +2106,6 @@ void helper_lock_init(void);
 /* svm_helper.c */
 void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
                                    uint64_t param, uintptr_t retaddr);
-void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code,
-                              uint64_t exit_info_1, uintptr_t retaddr);
-void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1);
-
-/* seg_helper.c */
-void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
-
-/* smm_helper.c */
-void do_smm_enter(X86CPU *cpu);
-
 /* apic.c */
 void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
 void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
@@ -2224,11 +2144,6 @@ typedef int X86CPUVersion;
  */
 void x86_cpu_set_default_version(X86CPUVersion version);
 
-/* Return name of 32-bit register, from a R_* constant */
-const char *get_register_name_32(unsigned int reg);
-
-void enable_compat_apic_id_mode(void);
-
 #define APIC_DEFAULT_ADDRESS 0xfee00000
 #define APIC_SPACE_SIZE      0x100000
 
diff --git a/target/i386/helper-tcg.h b/target/i386/helper-tcg.h
new file mode 100644
index 0000000000..57b4391a7d
--- /dev/null
+++ b/target/i386/helper-tcg.h
@@ -0,0 +1,112 @@
+/*
+ * TCG specific prototypes for helpers
+ *
+ *  Copyright (c) 2003 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 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef I386_HELPER_TCG_H
+#define I386_HELPER_TCG_H
+
+#include "exec/exec-all.h"
+
+/* Maximum instruction code size */
+#define TARGET_MAX_INSN_SIZE 16
+
+/*
+ * XXX: This value should match the one returned by CPUID
+ * and in exec.c
+ */
+# if defined(TARGET_X86_64)
+# define TCG_PHYS_ADDR_BITS 40
+# else
+# define TCG_PHYS_ADDR_BITS 36
+# endif
+
+#define PHYS_ADDR_MASK MAKE_64BIT_MASK(0, TCG_PHYS_ADDR_BITS)
+
+/**
+ * x86_cpu_do_interrupt:
+ * @cpu: vCPU the interrupt is to be handled by.
+ */
+void x86_cpu_do_interrupt(CPUState *cpu);
+bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req);
+
+/* helper.c */
+bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
+                      MMUAccessType access_type, int mmu_idx,
+                      bool probe, uintptr_t retaddr);
+
+void breakpoint_handler(CPUState *cs);
+
+/* n must be a constant to be efficient */
+static inline target_long lshift(target_long x, int n)
+{
+    if (n >= 0) {
+        return x << n;
+    } else {
+        return x >> (-n);
+    }
+}
+
+/* float macros */
+#define FT0    (env->ft0)
+#define ST0    (env->fpregs[env->fpstt].d)
+#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7].d)
+#define ST1    ST(1)
+
+/* translate.c */
+void tcg_x86_init(void);
+
+/* excp_helper.c */
+void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index);
+void QEMU_NORETURN raise_exception_ra(CPUX86State *env, int exception_index,
+                                      uintptr_t retaddr);
+void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index,
+                                       int error_code);
+void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index,
+                                          int error_code, uintptr_t retaddr);
+void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int,
+                                   int error_code, int next_eip_addend);
+
+/* cc_helper.c */
+extern const uint8_t parity_table[256];
+
+/*
+ * NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
+ * after generating a call to a helper that uses this.
+ */
+static inline void cpu_load_eflags(CPUX86State *env, int eflags,
+                                   int update_mask)
+{
+    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    CC_OP = CC_OP_EFLAGS;
+    env->df = 1 - (2 * ((eflags >> 10) & 1));
+    env->eflags = (env->eflags & ~update_mask) |
+        (eflags & update_mask) | 0x2;
+}
+
+/* svm_helper.c */
+void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code,
+                              uint64_t exit_info_1, uintptr_t retaddr);
+void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1);
+
+/* seg_helper.c */
+void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
+
+/* smm_helper.c */
+void do_smm_enter(X86CPU *cpu);
+
+#endif /* I386_HELPER_TCG_H */
diff --git a/target/i386/helper.c b/target/i386/helper.c
index 6e7e0f507c..6bb0c53182 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -24,10 +24,8 @@
 #include "sysemu/runstate.h"
 #include "kvm/kvm_i386.h"
 #ifndef CONFIG_USER_ONLY
-#include "sysemu/tcg.h"
 #include "sysemu/hw_accel.h"
 #include "monitor/monitor.h"
-#include "hw/i386/apic_internal.h"
 #endif
 
 void cpu_sync_bndcs_hflags(CPUX86State *env)
@@ -572,27 +570,6 @@ void do_cpu_sipi(X86CPU *cpu)
 }
 #endif
 
-/* Frob eflags into and out of the CPU temporary format.  */
-
-void x86_cpu_exec_enter(CPUState *cs)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    env->df = 1 - (2 * ((env->eflags >> 10) & 1));
-    CC_OP = CC_OP_EFLAGS;
-    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-}
-
-void x86_cpu_exec_exit(CPUState *cs)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    env->eflags = cpu_compute_eflags(env);
-}
-
 #ifndef CONFIG_USER_ONLY
 uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
 {
diff --git a/target/i386/meson.build b/target/i386/meson.build
index c4bf20b319..9c20208e5a 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -6,6 +6,7 @@ i386_ss.add(files(
   'xsave_helper.c',
   'cpu-dump.c',
 ))
+i386_ss.add(when: 'CONFIG_TCG', if_true: files('tcg-cpu.c'))
 i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-stub.c'))
 
 i386_softmmu_ss = ss.source_set()
diff --git a/target/i386/tcg-cpu.c b/target/i386/tcg-cpu.c
new file mode 100644
index 0000000000..628dd29fe7
--- /dev/null
+++ b/target/i386/tcg-cpu.c
@@ -0,0 +1,71 @@
+/*
+ * i386 TCG cpu class initialization
+ *
+ *  Copyright (c) 2003 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 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "tcg-cpu.h"
+#include "exec/exec-all.h"
+#include "sysemu/runstate.h"
+#include "helper-tcg.h"
+
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/i386/apic.h"
+#endif
+
+/* Frob eflags into and out of the CPU temporary format.  */
+
+static void x86_cpu_exec_enter(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    env->df = 1 - (2 * ((env->eflags >> 10) & 1));
+    CC_OP = CC_OP_EFLAGS;
+    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+}
+
+static void x86_cpu_exec_exit(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    env->eflags = cpu_compute_eflags(env);
+}
+
+static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    X86CPU *cpu = X86_CPU(cs);
+
+    cpu->env.eip = tb->pc - tb->cs_base;
+}
+
+void tcg_cpu_common_class_init(CPUClass *cc)
+{
+    cc->do_interrupt = x86_cpu_do_interrupt;
+    cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
+    cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
+    cc->cpu_exec_enter = x86_cpu_exec_enter;
+    cc->cpu_exec_exit = x86_cpu_exec_exit;
+    cc->tcg_initialize = tcg_x86_init;
+    cc->tlb_fill = x86_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
+    cc->debug_excp_handler = breakpoint_handler;
+#endif
+}
diff --git a/target/i386/tcg-cpu.h b/target/i386/tcg-cpu.h
new file mode 100644
index 0000000000..81f02e562e
--- /dev/null
+++ b/target/i386/tcg-cpu.h
@@ -0,0 +1,15 @@
+/*
+ * i386 TCG CPU class initialization
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TCG_CPU_H
+#define TCG_CPU_H
+
+void tcg_cpu_common_class_init(CPUClass *cc);
+
+#endif /* TCG_CPU_H */
diff --git a/target/i386/tcg/bpt_helper.c b/target/i386/tcg/bpt_helper.c
index e6cc2921e2..979230ac12 100644
--- a/target/i386/tcg/bpt_helper.c
+++ b/target/i386/tcg/bpt_helper.c
@@ -21,6 +21,7 @@
 #include "cpu.h"
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
+#include "helper-tcg.h"
 
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target/i386/tcg/cc_helper.c b/target/i386/tcg/cc_helper.c
index 924dd3cd57..cc7ea9e8b9 100644
--- a/target/i386/tcg/cc_helper.c
+++ b/target/i386/tcg/cc_helper.c
@@ -20,6 +20,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "helper-tcg.h"
 
 const uint8_t parity_table[256] = {
     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c
index 191471749f..a0f44431fe 100644
--- a/target/i386/tcg/excp_helper.c
+++ b/target/i386/tcg/excp_helper.c
@@ -23,6 +23,7 @@
 #include "qemu/log.h"
 #include "sysemu/runstate.h"
 #include "exec/helper-proto.h"
+#include "helper-tcg.h"
 
 void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend)
 {
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 03b35443a6..13f31b6ac7 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -26,6 +26,7 @@
 #include "exec/cpu_ldst.h"
 #include "fpu/softfloat.h"
 #include "fpu/softfloat-macros.h"
+#include "helper-tcg.h"
 
 #ifdef CONFIG_SOFTMMU
 #include "hw/irq.h"
@@ -2986,23 +2987,21 @@ void update_mxcsr_status(CPUX86State *env)
 
 void update_mxcsr_from_sse_status(CPUX86State *env)
 {
-    if (tcg_enabled()) {
-        uint8_t flags = get_float_exception_flags(&env->sse_status);
-        /*
-         * The MXCSR denormal flag has opposite semantics to
-         * float_flag_input_denormal (the softfloat code sets that flag
-         * only when flushing input denormals to zero, but SSE sets it
-         * only when not flushing them to zero), so is not converted
-         * here.
-         */
-        env->mxcsr |= ((flags & float_flag_invalid ? FPUS_IE : 0) |
-                       (flags & float_flag_divbyzero ? FPUS_ZE : 0) |
-                       (flags & float_flag_overflow ? FPUS_OE : 0) |
-                       (flags & float_flag_underflow ? FPUS_UE : 0) |
-                       (flags & float_flag_inexact ? FPUS_PE : 0) |
-                       (flags & float_flag_output_denormal ? FPUS_UE | FPUS_PE :
-                        0));
-    }
+    uint8_t flags = get_float_exception_flags(&env->sse_status);
+    /*
+     * The MXCSR denormal flag has opposite semantics to
+     * float_flag_input_denormal (the softfloat code sets that flag
+     * only when flushing input denormals to zero, but SSE sets it
+     * only when not flushing them to zero), so is not converted
+     * here.
+     */
+    env->mxcsr |= ((flags & float_flag_invalid ? FPUS_IE : 0) |
+                   (flags & float_flag_divbyzero ? FPUS_ZE : 0) |
+                   (flags & float_flag_overflow ? FPUS_OE : 0) |
+                   (flags & float_flag_underflow ? FPUS_UE : 0) |
+                   (flags & float_flag_inexact ? FPUS_PE : 0) |
+                   (flags & float_flag_output_denormal ? FPUS_UE | FPUS_PE :
+                    0));
 }
 
 void helper_update_mxcsr(CPUX86State *env)
diff --git a/target/i386/tcg/int_helper.c b/target/i386/tcg/int_helper.c
index 4f89436b53..87fa7280ee 100644
--- a/target/i386/tcg/int_helper.c
+++ b/target/i386/tcg/int_helper.c
@@ -24,6 +24,7 @@
 #include "exec/helper-proto.h"
 #include "qapi/error.h"
 #include "qemu/guest-random.h"
+#include "helper-tcg.h"
 
 //#define DEBUG_MULDIV
 
diff --git a/target/i386/tcg/mem_helper.c b/target/i386/tcg/mem_helper.c
index 21ca3e3e88..e5cd2de1bf 100644
--- a/target/i386/tcg/mem_helper.c
+++ b/target/i386/tcg/mem_helper.c
@@ -25,6 +25,7 @@
 #include "qemu/int128.h"
 #include "qemu/atomic128.h"
 #include "tcg/tcg.h"
+#include "helper-tcg.h"
 
 void helper_cmpxchg8b_unlocked(CPUX86State *env, target_ulong a0)
 {
diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c
index ae259d9145..c99370e5e3 100644
--- a/target/i386/tcg/misc_helper.c
+++ b/target/i386/tcg/misc_helper.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 #include "exec/address-spaces.h"
+#include "helper-tcg.h"
 
 void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
 {
diff --git a/target/i386/tcg/mpx_helper.c b/target/i386/tcg/mpx_helper.c
index fd966174b4..22423eedcd 100644
--- a/target/i386/tcg/mpx_helper.c
+++ b/target/i386/tcg/mpx_helper.c
@@ -22,6 +22,7 @@
 #include "exec/helper-proto.h"
 #include "exec/cpu_ldst.h"
 #include "exec/exec-all.h"
+#include "helper-tcg.h"
 
 
 void helper_bndck(CPUX86State *env, uint32_t fail)
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 09b6554660..ed3e04a187 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -25,6 +25,7 @@
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 #include "exec/log.h"
+#include "helper-tcg.h"
 
 //#define DEBUG_PCALL
 
diff --git a/target/i386/tcg/smm_helper.c b/target/i386/tcg/smm_helper.c
index d20e8edfdf..62d027abd3 100644
--- a/target/i386/tcg/smm_helper.c
+++ b/target/i386/tcg/smm_helper.c
@@ -22,6 +22,8 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "exec/log.h"
+#include "helper-tcg.h"
+
 
 /* SMM support */
 
diff --git a/target/i386/tcg/svm_helper.c b/target/i386/tcg/svm_helper.c
index 38931586e5..097bb9b83d 100644
--- a/target/i386/tcg/svm_helper.c
+++ b/target/i386/tcg/svm_helper.c
@@ -22,6 +22,7 @@
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
+#include "helper-tcg.h"
 
 /* Secure Virtual Machine helpers */
 
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4c57307e42..5988ea0289 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -28,6 +28,7 @@
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
+#include "helper-tcg.h"
 
 #include "trace-tcg.h"
 #include "exec/log.h"
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (6 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 07/12] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 17:56   ` Eduardo Habkost
  2020-11-24 16:22 ` [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                        |  2 +-
 accel/accel-common.c               | 54 ++++++++++++++++++++++++++++++
 accel/{accel.c => accel-softmmu.c} | 27 ++-------------
 accel/accel-user.c                 | 28 ++++++++++++++++
 accel/meson.build                  |  4 ++-
 accel/qtest/qtest.c                |  2 +-
 accel/tcg/meson.build              |  3 +-
 accel/tcg/tcg-all.c                |  3 +-
 accel/xen/xen-all.c                |  2 +-
 bsd-user/main.c                    |  8 +++--
 include/hw/boards.h                |  2 +-
 include/{sysemu => qemu}/accel.h   | 15 +++++----
 include/sysemu/hvf.h               |  2 +-
 include/sysemu/kvm.h               |  2 +-
 include/sysemu/kvm_int.h           |  2 +-
 linux-user/main.c                  |  8 +++--
 softmmu/memory.c                   |  2 +-
 softmmu/qtest.c                    |  2 +-
 softmmu/vl.c                       |  2 +-
 target/i386/hax/hax-all.c          |  2 +-
 target/i386/hvf/hvf-i386.h         |  2 +-
 target/i386/hvf/hvf.c              |  2 +-
 target/i386/hvf/x86_task.c         |  2 +-
 target/i386/whpx/whpx-all.c        |  2 +-
 24 files changed, 124 insertions(+), 56 deletions(-)
 create mode 100644 accel/accel-common.c
 rename accel/{accel.c => accel-softmmu.c} (75%)
 create mode 100644 accel/accel-user.c
 rename include/{sysemu => qemu}/accel.h (95%)

diff --git a/MAINTAINERS b/MAINTAINERS
index e892dd2220..d7c212843c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -433,7 +433,7 @@ Overall
 M: Richard Henderson <richard.henderson@linaro.org>
 R: Paolo Bonzini <pbonzini@redhat.com>
 S: Maintained
-F: include/sysemu/accel.h
+F: include/qemu/accel.h
 F: accel/accel.c
 F: accel/Makefile.objs
 F: accel/stubs/Makefile.objs
diff --git a/accel/accel-common.c b/accel/accel-common.c
new file mode 100644
index 0000000000..d9115b7072
--- /dev/null
+++ b/accel/accel-common.c
@@ -0,0 +1,54 @@
+/*
+ * QEMU accel class, components common to system emulation and user mode
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2014 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/accel.h"
+#include "hw/boards.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/sysemu.h"
+#include "qom/object.h"
+
+static const TypeInfo accel_type = {
+    .name = TYPE_ACCEL,
+    .parent = TYPE_OBJECT,
+    .class_size = sizeof(AccelClass),
+    .instance_size = sizeof(AccelState),
+};
+
+/* Lookup AccelClass from opt_name. Returns NULL if not found */
+AccelClass *accel_find(const char *opt_name)
+{
+    char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
+    AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
+    g_free(class_name);
+    return ac;
+}
+
+static void register_accel_types(void)
+{
+    type_register_static(&accel_type);
+}
+
+type_init(register_accel_types);
diff --git a/accel/accel.c b/accel/accel-softmmu.c
similarity index 75%
rename from accel/accel.c
rename to accel/accel-softmmu.c
index cb555e3b06..f89da8f9d1 100644
--- a/accel/accel.c
+++ b/accel/accel-softmmu.c
@@ -1,5 +1,5 @@
 /*
- * QEMU System Emulator, accelerator interfaces
+ * QEMU accel class, system emulation components
  *
  * Copyright (c) 2003-2008 Fabrice Bellard
  * Copyright (c) 2014 Red Hat Inc.
@@ -24,28 +24,12 @@
  */
 
 #include "qemu/osdep.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "hw/boards.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/sysemu.h"
 #include "qom/object.h"
 
-static const TypeInfo accel_type = {
-    .name = TYPE_ACCEL,
-    .parent = TYPE_OBJECT,
-    .class_size = sizeof(AccelClass),
-    .instance_size = sizeof(AccelState),
-};
-
-/* Lookup AccelClass from opt_name. Returns NULL if not found */
-AccelClass *accel_find(const char *opt_name)
-{
-    char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
-    AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
-    g_free(class_name);
-    return ac;
-}
-
 int accel_init_machine(AccelState *accel, MachineState *ms)
 {
     AccelClass *acc = ACCEL_GET_CLASS(accel);
@@ -76,10 +60,3 @@ void accel_setup_post(MachineState *ms)
         acc->setup_post(ms, accel);
     }
 }
-
-static void register_accel_types(void)
-{
-    type_register_static(&accel_type);
-}
-
-type_init(register_accel_types);
diff --git a/accel/accel-user.c b/accel/accel-user.c
new file mode 100644
index 0000000000..52369ce2ca
--- /dev/null
+++ b/accel/accel-user.c
@@ -0,0 +1,28 @@
+/*
+ * QEMU accel class, user-mode components
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/accel.h"
+#include "hw/boards.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/sysemu.h"
+#include "qom/object.h"
+
+AccelState *current_accel(void)
+{
+    static AccelState *accel;
+
+    if (!accel) {
+        AccelClass *ac = accel_find("tcg");
+
+        g_assert(ac != NULL);
+        accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac)));
+    }
+    return accel;
+}
diff --git a/accel/meson.build b/accel/meson.build
index b26cca227a..0208b48d3b 100644
--- a/accel/meson.build
+++ b/accel/meson.build
@@ -1,4 +1,6 @@
-softmmu_ss.add(files('accel.c'))
+common_ss.add(files('accel-common.c'))
+softmmu_ss.add(files('accel-softmmu.c'))
+user_ss.add(files('accel-user.c'))
 
 subdir('qtest')
 subdir('kvm')
diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
index b282cea5cf..b4e731cb2b 100644
--- a/accel/qtest/qtest.c
+++ b/accel/qtest/qtest.c
@@ -17,7 +17,7 @@
 #include "qemu/module.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/qtest.h"
 #include "sysemu/cpus.h"
 #include "sysemu/cpu-timers.h"
diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
index f39aab0a0c..bcc54e1466 100644
--- a/accel/tcg/meson.build
+++ b/accel/tcg/meson.build
@@ -1,5 +1,6 @@
 tcg_ss = ss.source_set()
 tcg_ss.add(files(
+  'tcg-all.c',
   'cpu-exec-common.c',
   'cpu-exec.c',
   'tcg-runtime-gvec.c',
@@ -11,9 +12,7 @@ tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
 tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c'))
 tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
 specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
-
 specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
-  'tcg-all.c',
   'cputlb.c',
   'tcg-cpus.c',
   'tcg-cpus-mttcg.c',
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index 1ac0b76515..ef91d13669 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -30,9 +30,8 @@
 #include "tcg/tcg.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
-#include "hw/boards.h"
+#include "qemu/accel.h"
 #include "qapi/qapi-builtin-visit.h"
-#include "tcg-cpus.h"
 
 struct TCGState {
     AccelState parent_obj;
diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 878a4089d9..594aaf6b49 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -15,7 +15,7 @@
 #include "hw/xen/xen-legacy-backend.h"
 #include "hw/xen/xen_pt.h"
 #include "chardev/char.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/cpus.h"
 #include "sysemu/xen.h"
 #include "sysemu/runstate.h"
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0a918e8f74..c6a6cd291b 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -20,6 +20,7 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/units.h"
+#include "qemu/accel.h"
 #include "sysemu/tcg.h"
 #include "qemu-version.h"
 #include <machine/trap.h>
@@ -908,8 +909,12 @@ int main(int argc, char **argv)
     }
 
     /* init tcg before creating CPUs and to get qemu_host_page_size */
-    tcg_exec_init(0);
+    {
+        AccelClass *ac = accel_find("tcg");
 
+        g_assert(ac != NULL);
+        ac->init_machine(NULL);
+    }
     cpu_type = parse_cpu_option(cpu_model);
     cpu = cpu_create(cpu_type);
     env = cpu->env_ptr;
@@ -988,7 +993,6 @@ int main(int argc, char **argv)
        generating the prologue until now so that the prologue can take
        the real value of GUEST_BASE into account.  */
     tcg_prologue_init(tcg_ctx);
-    tcg_region_init();
 
     /* build Task State */
     memset(ts, 0, sizeof(TaskState));
diff --git a/include/hw/boards.h b/include/hw/boards.h
index a49e3a6b44..b754504afe 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -6,7 +6,7 @@
 #include "exec/memory.h"
 #include "sysemu/hostmem.h"
 #include "sysemu/blockdev.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "qapi/qapi-types-machine.h"
 #include "qemu/module.h"
 #include "qom/object.h"
diff --git a/include/sysemu/accel.h b/include/qemu/accel.h
similarity index 95%
rename from include/sysemu/accel.h
rename to include/qemu/accel.h
index e08b8ab8fa..f7abac98bb 100644
--- a/include/sysemu/accel.h
+++ b/include/qemu/accel.h
@@ -20,8 +20,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#ifndef HW_ACCEL_H
-#define HW_ACCEL_H
+#ifndef QEMU_ACCEL_H
+#define QEMU_ACCEL_H
 
 #include "qom/object.h"
 #include "exec/hwaddr.h"
@@ -37,8 +37,8 @@ typedef struct AccelClass {
     /*< public >*/
 
     const char *name;
-#ifndef CONFIG_USER_ONLY
     int (*init_machine)(MachineState *ms);
+#ifndef CONFIG_USER_ONLY
     void (*setup_post)(MachineState *ms, AccelState *accel);
     bool (*has_memory)(MachineState *ms, AddressSpace *as,
                        hwaddr start_addr, hwaddr size);
@@ -67,11 +67,12 @@ typedef struct AccelClass {
     OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL)
 
 AccelClass *accel_find(const char *opt_name);
+AccelState *current_accel(void);
+
+#ifndef CONFIG_USER_ONLY
 int accel_init_machine(AccelState *accel, MachineState *ms);
-
 /* Called just before os_setup_post (ie just before drop OS privs) */
 void accel_setup_post(MachineState *ms);
+#endif /* !CONFIG_USER_ONLY */
 
-AccelState *current_accel(void);
-
-#endif
+#endif /* QEMU_ACCEL_H */
diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
index f893768df9..c98636bc81 100644
--- a/include/sysemu/hvf.h
+++ b/include/sysemu/hvf.h
@@ -13,7 +13,7 @@
 #ifndef HVF_H
 #define HVF_H
 
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "qom/object.h"
 
 #ifdef CONFIG_HVF
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index bb5d5cf497..739682f3c3 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -17,7 +17,7 @@
 #include "qemu/queue.h"
 #include "hw/core/cpu.h"
 #include "exec/memattrs.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "qom/object.h"
 
 #ifdef NEED_CPU_H
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
index 65740806da..ccb8869f01 100644
--- a/include/sysemu/kvm_int.h
+++ b/include/sysemu/kvm_int.h
@@ -10,7 +10,7 @@
 #define QEMU_KVM_INT_H
 
 #include "exec/memory.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/kvm.h"
 
 typedef struct KVMSlot
diff --git a/linux-user/main.c b/linux-user/main.c
index 24d1eb73ad..ae6be5e81f 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -20,6 +20,7 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/units.h"
+#include "qemu/accel.h"
 #include "sysemu/tcg.h"
 #include "qemu-version.h"
 #include <sys/syscall.h>
@@ -703,8 +704,12 @@ int main(int argc, char **argv, char **envp)
     cpu_type = parse_cpu_option(cpu_model);
 
     /* init tcg before creating CPUs and to get qemu_host_page_size */
-    tcg_exec_init(0);
+    {
+        AccelClass *ac = accel_find("tcg");
 
+        g_assert(ac != NULL);
+        ac->init_machine(NULL);
+    }
     cpu = cpu_create(cpu_type);
     env = cpu->env_ptr;
     cpu_reset(cpu);
@@ -846,7 +851,6 @@ int main(int argc, char **argv, char **envp)
        generating the prologue until now so that the prologue can take
        the real value of GUEST_BASE into account.  */
     tcg_prologue_init(tcg_ctx);
-    tcg_region_init();
 
     target_cpu_copy_regs(env, regs);
 
diff --git a/softmmu/memory.c b/softmmu/memory.c
index aa393f1bb0..92c8b4fc1f 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -32,7 +32,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/runstate.h"
 #include "sysemu/tcg.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "hw/boards.h"
 #include "migration/vmstate.h"
 
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
index 7965dc9a16..130c366615 100644
--- a/softmmu/qtest.c
+++ b/softmmu/qtest.c
@@ -20,7 +20,7 @@
 #include "exec/ioport.h"
 #include "exec/memory.h"
 #include "hw/irq.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/cpu-timers.h"
 #include "qemu/config-file.h"
 #include "qemu/option.h"
diff --git a/softmmu/vl.c b/softmmu/vl.c
index e6e0ad5a92..bc20c526d2 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -40,7 +40,7 @@
 
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "hw/usb.h"
 #include "hw/isa/isa.h"
 #include "hw/scsi/scsi.h"
diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
index fecfe8cd6e..d7f4bb44a7 100644
--- a/target/i386/hax/hax-all.c
+++ b/target/i386/hax/hax-all.c
@@ -28,7 +28,7 @@
 #include "exec/address-spaces.h"
 
 #include "qemu-common.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/reset.h"
 #include "sysemu/runstate.h"
 #include "hw/boards.h"
diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.h
index e0edffd077..50b914fd67 100644
--- a/target/i386/hvf/hvf-i386.h
+++ b/target/i386/hvf/hvf-i386.h
@@ -16,7 +16,7 @@
 #ifndef HVF_I386_H
 #define HVF_I386_H
 
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/hvf.h"
 #include "cpu.h"
 #include "x86.h"
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ed9356565c..ffc9efa40f 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -69,7 +69,7 @@
 #include "exec/address-spaces.h"
 #include "hw/i386/apic_internal.h"
 #include "qemu/main-loop.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "target/i386/cpu.h"
 
 #include "hvf-cpus.h"
diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c
index 6f04478b3a..d66dfd7669 100644
--- a/target/i386/hvf/x86_task.c
+++ b/target/i386/hvf/x86_task.c
@@ -28,7 +28,7 @@
 
 #include "hw/i386/apic_internal.h"
 #include "qemu/main-loop.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "target/i386/cpu.h"
 
 // TODO: taskswitch handling
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index f4f3e33eac..ee6b606194 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -13,7 +13,7 @@
 #include "exec/address-spaces.h"
 #include "exec/ioport.h"
 #include "qemu-common.h"
-#include "sysemu/accel.h"
+#include "qemu/accel.h"
 #include "sysemu/whpx.h"
 #include "sysemu/cpus.h"
 #include "sysemu/runstate.h"
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (7 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 17:08   ` Eduardo Habkost
  2020-11-26 11:25   ` Philippe Mathieu-Daudé
  2020-11-24 16:22 ` [RFC v5 10/12] i386: split cpu accelerators from cpu.c Claudio Fontana
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

apply this to the registration of the cpus accel interfaces,

but this will be also in preparation for later use of this
new module init step to also register per-accel x86 cpu type
interfaces.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 accel/kvm/kvm-all.c         | 11 +++++++++--
 accel/qtest/qtest.c         | 10 +++++++++-
 accel/tcg/tcg-all.c         |  8 --------
 accel/tcg/tcg-cpus.c        | 15 +++++++++++++++
 accel/xen/xen-all.c         | 12 +++++++++---
 include/qemu/module.h       |  2 ++
 roms/qboot                  |  2 +-
 softmmu/vl.c                |  6 ++++++
 target/i386/hax/hax-all.c   | 12 +++++++++---
 target/i386/hvf/hvf.c       | 10 +++++++++-
 target/i386/whpx/whpx-all.c | 11 +++++++++--
 11 files changed, 78 insertions(+), 21 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 9ef5daf4c5..509b249f52 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -2251,8 +2251,6 @@ static int kvm_init(MachineState *ms)
         ret = ram_block_discard_disable(true);
         assert(!ret);
     }
-
-    cpus_register_accel(&kvm_cpus);
     return 0;
 
 err:
@@ -3236,3 +3234,12 @@ static void kvm_type_init(void)
 }
 
 type_init(kvm_type_init);
+
+static void kvm_accel_cpu_init(void)
+{
+    if (kvm_enabled()) {
+        cpus_register_accel(&kvm_cpus);
+    }
+}
+
+accel_cpu_init(kvm_accel_cpu_init);
diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
index b4e731cb2b..482f89729f 100644
--- a/accel/qtest/qtest.c
+++ b/accel/qtest/qtest.c
@@ -32,7 +32,6 @@ const CpusAccel qtest_cpus = {
 
 static int qtest_init_accel(MachineState *ms)
 {
-    cpus_register_accel(&qtest_cpus);
     return 0;
 }
 
@@ -58,3 +57,12 @@ static void qtest_type_init(void)
 }
 
 type_init(qtest_type_init);
+
+static void qtest_accel_cpu_init(void)
+{
+    if (qtest_enabled()) {
+        cpus_register_accel(&qtest_cpus);
+    }
+}
+
+accel_cpu_init(qtest_accel_cpu_init);
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index ef91d13669..2b86df9ba0 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -108,14 +108,6 @@ static int tcg_init(MachineState *ms)
      * Initialize TCG regions
      */
     tcg_region_init();
-
-    if (mttcg_enabled) {
-        cpus_register_accel(&tcg_cpus_mttcg);
-    } else if (icount_enabled()) {
-        cpus_register_accel(&tcg_cpus_icount);
-    } else {
-        cpus_register_accel(&tcg_cpus_rr);
-    }
     return 0;
 }
 
diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c
index e335f9f155..c9e662f06e 100644
--- a/accel/tcg/tcg-cpus.c
+++ b/accel/tcg/tcg-cpus.c
@@ -80,3 +80,18 @@ void tcg_cpus_handle_interrupt(CPUState *cpu, int mask)
         qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
     }
 }
+
+static void tcg_accel_cpu_init(void)
+{
+    if (tcg_enabled()) {
+        if (qemu_tcg_mttcg_enabled()) {
+            cpus_register_accel(&tcg_cpus_mttcg);
+        } else if (icount_enabled()) {
+            cpus_register_accel(&tcg_cpus_icount);
+        } else {
+            cpus_register_accel(&tcg_cpus_rr);
+        }
+    }
+}
+
+accel_cpu_init(tcg_accel_cpu_init);
diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 594aaf6b49..be09b6ec22 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -185,9 +185,6 @@ static int xen_init(MachineState *ms)
      * opt out of system RAM being allocated by generic code
      */
     mc->default_ram_id = NULL;
-
-    cpus_register_accel(&xen_cpus);
-
     return 0;
 }
 
@@ -228,3 +225,12 @@ static void xen_type_init(void)
 }
 
 type_init(xen_type_init);
+
+static void xen_accel_cpu_init(void)
+{
+    if (xen_enabled()) {
+        cpus_register_accel(&xen_cpus);
+    }
+}
+
+accel_cpu_init(xen_accel_cpu_init);
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 944d403cbd..485eda986a 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -44,6 +44,7 @@ typedef enum {
     MODULE_INIT_BLOCK,
     MODULE_INIT_OPTS,
     MODULE_INIT_QOM,
+    MODULE_INIT_ACCEL_CPU,
     MODULE_INIT_TRACE,
     MODULE_INIT_XEN_BACKEND,
     MODULE_INIT_LIBQOS,
@@ -54,6 +55,7 @@ typedef enum {
 #define block_init(function) module_init(function, MODULE_INIT_BLOCK)
 #define opts_init(function) module_init(function, MODULE_INIT_OPTS)
 #define type_init(function) module_init(function, MODULE_INIT_QOM)
+#define accel_cpu_init(function) module_init(function, MODULE_INIT_ACCEL_CPU)
 #define trace_init(function) module_init(function, MODULE_INIT_TRACE)
 #define xen_backend_init(function) module_init(function, \
                                                MODULE_INIT_XEN_BACKEND)
diff --git a/roms/qboot b/roms/qboot
index a5300c4949..cb1c49e0cf 160000
--- a/roms/qboot
+++ b/roms/qboot
@@ -1 +1 @@
-Subproject commit a5300c4949b8d4de2d34bedfaed66793f48ec948
+Subproject commit cb1c49e0cfac99b9961d136ac0194da62c28cf64
diff --git a/softmmu/vl.c b/softmmu/vl.c
index bc20c526d2..fb92132222 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4173,6 +4173,12 @@ void qemu_init(int argc, char **argv, char **envp)
      */
     configure_accelerators(argv[0]);
 
+    /*
+     * accelerator has been chosen and initialized, now it is time to
+     * register the cpu accel interface.
+     */
+    module_call_init(MODULE_INIT_ACCEL_CPU);
+
     /*
      * Beware, QOM objects created before this point miss global and
      * compat properties.
diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
index d7f4bb44a7..77c365311c 100644
--- a/target/i386/hax/hax-all.c
+++ b/target/i386/hax/hax-all.c
@@ -364,9 +364,6 @@ static int hax_accel_init(MachineState *ms)
                 !ret ? "working" : "not working",
                 !ret ? "fast virt" : "emulation");
     }
-    if (ret == 0) {
-        cpus_register_accel(&hax_cpus);
-    }
     return ret;
 }
 
@@ -1141,3 +1138,12 @@ static void hax_type_init(void)
 }
 
 type_init(hax_type_init);
+
+static void hax_accel_cpu_init(void)
+{
+    if (hax_enabled()) {
+        cpus_register_accel(&hax_cpus);
+    }
+}
+
+accel_cpu_init(hax_accel_cpu_init);
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ffc9efa40f..58794c35ae 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -887,7 +887,6 @@ static int hvf_accel_init(MachineState *ms)
   
     hvf_state = s;
     memory_listener_register(&hvf_memory_listener, &address_space_memory);
-    cpus_register_accel(&hvf_cpus);
     return 0;
 }
 
@@ -911,3 +910,12 @@ static void hvf_type_init(void)
 }
 
 type_init(hvf_type_init);
+
+static void hvf_accel_cpu_init(void)
+{
+    if (hvf_enabled()) {
+        cpus_register_accel(&hvf_cpus);
+    }
+}
+
+accel_cpu_init(hvf_accel_cpu_init);
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index ee6b606194..097d6f5e60 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1642,8 +1642,6 @@ static int whpx_accel_init(MachineState *ms)
 
     whpx_memory_init();
 
-    cpus_register_accel(&whpx_cpus);
-
     printf("Windows Hypervisor Platform accelerator is operational\n");
     return 0;
 
@@ -1713,3 +1711,12 @@ error:
 }
 
 type_init(whpx_type_init);
+
+static void whpx_accel_cpu_init(void)
+{
+    if (whpx_enabled()) {
+        cpus_register_accel(&whpx_cpus);
+    }
+}
+
+accel_cpu_init(whpx_accel_cpu_init);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 10/12] i386: split cpu accelerators from cpu.c
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (8 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:22 ` [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces Claudio Fontana
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

split cpu.c into:

cpu.c            cpuid and common x86 cpu functionality
host-cpu.c       host x86 cpu functions and "host" cpu type
kvm/cpu.c        KVM x86 cpu type
hvf/cpu.c        HVF x86 cpu type
tcg/cpu.c        TCG x86 cpu type

The link to the accel class is set in the X86CPUClass classes
at MODULE_INIT_ACCEL_CPU time, when the accelerator is known.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                 |   2 +-
 bsd-user/main.c             |   1 +
 hw/i386/pc_piix.c           |   1 +
 linux-user/main.c           |   1 +
 target/i386/cpu-qom.h       |  28 +++
 target/i386/cpu.c           | 408 ++++++------------------------------
 target/i386/cpu.h           |  20 +-
 target/i386/host-cpu.c      | 198 +++++++++++++++++
 target/i386/host-cpu.h      |  19 ++
 target/i386/hvf/cpu.c       |  76 +++++++
 target/i386/hvf/meson.build |   1 +
 target/i386/kvm/cpu.c       | 157 ++++++++++++++
 target/i386/kvm/kvm-cpu.h   |  41 ++++
 target/i386/kvm/kvm.c       |   3 +-
 target/i386/kvm/meson.build |   7 +-
 target/i386/meson.build     |   8 +-
 target/i386/tcg-cpu.c       |  71 -------
 target/i386/tcg-cpu.h       |  15 --
 target/i386/tcg/cpu.c       | 181 ++++++++++++++++
 target/i386/tcg/meson.build |   3 +-
 20 files changed, 792 insertions(+), 449 deletions(-)
 create mode 100644 target/i386/host-cpu.c
 create mode 100644 target/i386/host-cpu.h
 create mode 100644 target/i386/hvf/cpu.c
 create mode 100644 target/i386/kvm/cpu.c
 create mode 100644 target/i386/kvm/kvm-cpu.h
 delete mode 100644 target/i386/tcg-cpu.c
 delete mode 100644 target/i386/tcg-cpu.h
 create mode 100644 target/i386/tcg/cpu.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d7c212843c..f2efdd80b2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -336,7 +336,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
 M: Richard Henderson <richard.henderson@linaro.org>
 M: Eduardo Habkost <ehabkost@redhat.com>
 S: Maintained
-F: target/i386/
+F: target/i386/tcg/
 F: tests/tcg/i386/
 F: tests/tcg/x86_64/
 F: hw/i386/
diff --git a/bsd-user/main.c b/bsd-user/main.c
index c6a6cd291b..f56962f3c5 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -915,6 +915,7 @@ int main(int argc, char **argv)
         g_assert(ac != NULL);
         ac->init_machine(NULL);
     }
+    module_call_init(MODULE_INIT_ACCEL_CPU);
     cpu_type = parse_cpu_option(cpu_model);
     cpu = cpu_create(cpu_type);
     env = cpu->env_ptr;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 13d1628f13..d3f013f3a1 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -64,6 +64,7 @@
 #include "hw/hyperv/vmbus-bridge.h"
 #include "hw/mem/nvdimm.h"
 #include "hw/i386/acpi-build.h"
+#include "kvm/kvm-cpu.h"
 
 #define MAX_IDE_BUS 2
 
diff --git a/linux-user/main.c b/linux-user/main.c
index ae6be5e81f..f17e40ed26 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -710,6 +710,7 @@ int main(int argc, char **argv, char **envp)
         g_assert(ac != NULL);
         ac->init_machine(NULL);
     }
+    module_call_init(MODULE_INIT_ACCEL_CPU);
     cpu = cpu_create(cpu_type);
     env = cpu->env_ptr;
     cpu_reset(cpu);
diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
index f9923cee04..9316e78e71 100644
--- a/target/i386/cpu-qom.h
+++ b/target/i386/cpu-qom.h
@@ -33,6 +33,12 @@
 OBJECT_DECLARE_TYPE(X86CPU, X86CPUClass,
                     X86_CPU)
 
+
+#define TYPE_X86_CPU_ACCEL "accel-" TYPE_X86_CPU
+#define X86_CPU_ACCEL_TYPE_NAME(name) (name "-" TYPE_X86_CPU_ACCEL)
+typedef struct X86CPUAccelClass X86CPUAccelClass;
+DECLARE_CLASS_CHECKERS(X86CPUAccelClass, X86_CPU_ACCEL, TYPE_X86_CPU_ACCEL)
+
 typedef struct X86CPUModel X86CPUModel;
 
 /**
@@ -69,7 +75,29 @@ struct X86CPUClass {
     DeviceRealize parent_realize;
     DeviceUnrealize parent_unrealize;
     DeviceReset parent_reset;
+
+    const X86CPUAccelClass *accel;
+};
+
+/**
+ * X86CPUAccelClass:
+ * @name: string name of the X86 CPU Accelerator
+ *
+ * @common_class_init: initializer for the common cpu
+ * @instance_init: cpu instance initialization
+ * @realizefn: realize function, called first in x86 cpu realize
+ *
+ * X86 CPU accelerator-specific CPU initializations
+ */
+
+struct X86CPUAccelClass {
+    ObjectClass parent_class;
+
+    void (*cpu_common_class_init)(X86CPUClass *xcc);
+    void (*cpu_instance_init)(X86CPU *cpu);
+    void (*cpu_realizefn)(X86CPU *cpu, Error **errp);
 };
 
+void x86_cpu_accel_init(const char *accel_name);
 
 #endif
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 3462d0143f..b799723e53 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -22,9 +22,7 @@
 #include "qemu/cutils.h"
 #include "qemu/bitops.h"
 #include "qemu/qemu-print.h"
-
 #include "cpu.h"
-#include "tcg-cpu.h"
 #include "helper-tcg.h"
 #include "exec/exec-all.h"
 #include "sysemu/kvm.h"
@@ -34,25 +32,14 @@
 #include "sysemu/xen.h"
 #include "kvm/kvm_i386.h"
 #include "sev_i386.h"
-
-#include "qemu/error-report.h"
 #include "qemu/module.h"
-#include "qemu/option.h"
-#include "qemu/config-file.h"
-#include "qapi/error.h"
 #include "qapi/qapi-visit-machine.h"
 #include "qapi/qapi-visit-run-state.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
-#include "qapi/visitor.h"
 #include "qom/qom-qobject.h"
-#include "sysemu/arch_init.h"
 #include "qapi/qapi-commands-machine-target.h"
-
 #include "standard-headers/asm-x86/kvm_para.h"
-
-#include "sysemu/sysemu.h"
-#include "sysemu/tcg.h"
 #include "hw/qdev-properties.h"
 #include "hw/i386/topology.h"
 #ifndef CONFIG_USER_ONLY
@@ -594,8 +581,8 @@ static CPUCacheInfo legacy_l3_cache = {
 #define INTEL_PT_CYCLE_BITMAP    0x1fff         /* Support 0,2^(0~11) */
 #define INTEL_PT_PSB_BITMAP      (0x003f << 16) /* Support 2K,4K,8K,16K,32K,64K */
 
-static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
-                                     uint32_t vendor2, uint32_t vendor3)
+void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
+                              uint32_t vendor2, uint32_t vendor3)
 {
     int i;
     for (i = 0; i < 4; i++) {
@@ -1563,25 +1550,6 @@ void host_cpuid(uint32_t function, uint32_t count,
         *edx = vec[3];
 }
 
-void host_vendor_fms(char *vendor, int *family, int *model, int *stepping)
-{
-    uint32_t eax, ebx, ecx, edx;
-
-    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
-    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
-
-    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
-    if (family) {
-        *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
-    }
-    if (model) {
-        *model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
-    }
-    if (stepping) {
-        *stepping = eax & 0x0F;
-    }
-}
-
 /* CPU class name definitions: */
 
 /* Return type name for a given CPU model name
@@ -1606,10 +1574,6 @@ static char *x86_cpu_class_get_model_name(X86CPUClass *cc)
                      strlen(class_name) - strlen(X86_CPU_TYPE_SUFFIX));
 }
 
-typedef struct PropValue {
-    const char *prop, *value;
-} PropValue;
-
 typedef struct X86CPUVersionDefinition {
     X86CPUVersion version;
     const char *alias;
@@ -4106,31 +4070,6 @@ static X86CPUDefinition builtin_x86_defs[] = {
     },
 };
 
-/* KVM-specific features that are automatically added/removed
- * from all CPU models when KVM is enabled.
- */
-static PropValue kvm_default_props[] = {
-    { "kvmclock", "on" },
-    { "kvm-nopiodelay", "on" },
-    { "kvm-asyncpf", "on" },
-    { "kvm-steal-time", "on" },
-    { "kvm-pv-eoi", "on" },
-    { "kvmclock-stable-bit", "on" },
-    { "x2apic", "on" },
-    { "acpi", "off" },
-    { "monitor", "off" },
-    { "svm", "off" },
-    { NULL, NULL },
-};
-
-/* TCG-specific defaults that override all CPU models when using TCG
- */
-static PropValue tcg_default_props[] = {
-    { "vme", "off" },
-    { NULL, NULL },
-};
-
-
 /*
  * We resolve CPU model aliases using -v1 when using "-machine
  * none", but this is just for compatibility while libvirt isn't
@@ -4172,61 +4111,6 @@ static X86CPUVersion x86_cpu_model_resolve_version(const X86CPUModel *model)
     return v;
 }
 
-void x86_cpu_change_kvm_default(const char *prop, const char *value)
-{
-    PropValue *pv;
-    for (pv = kvm_default_props; pv->prop; pv++) {
-        if (!strcmp(pv->prop, prop)) {
-            pv->value = value;
-            break;
-        }
-    }
-
-    /* It is valid to call this function only for properties that
-     * are already present in the kvm_default_props table.
-     */
-    assert(pv->prop);
-}
-
-static bool lmce_supported(void)
-{
-    uint64_t mce_cap = 0;
-
-#ifdef CONFIG_KVM
-    if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) {
-        return false;
-    }
-#endif
-
-    return !!(mce_cap & MCG_LMCE_P);
-}
-
-#define CPUID_MODEL_ID_SZ 48
-
-/**
- * cpu_x86_fill_model_id:
- * Get CPUID model ID string from host CPU.
- *
- * @str should have at least CPUID_MODEL_ID_SZ bytes
- *
- * The function does NOT add a null terminator to the string
- * automatically.
- */
-static int cpu_x86_fill_model_id(char *str)
-{
-    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
-    int i;
-
-    for (i = 0; i < 3; i++) {
-        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
-        memcpy(str + i * 16 +  0, &eax, 4);
-        memcpy(str + i * 16 +  4, &ebx, 4);
-        memcpy(str + i * 16 +  8, &ecx, 4);
-        memcpy(str + i * 16 + 12, &edx, 4);
-    }
-    return 0;
-}
-
 static Property max_x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
     DEFINE_PROP_BOOL("host-cache-info", X86CPU, cache_info_passthrough, false),
@@ -4249,61 +4133,25 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
 static void max_x86_cpu_initfn(Object *obj)
 {
     X86CPU *cpu = X86_CPU(obj);
-    CPUX86State *env = &cpu->env;
-    KVMState *s = kvm_state;
 
     /* We can't fill the features array here because we don't know yet if
      * "migratable" is true or false.
      */
     cpu->max_features = true;
-
-    if (accel_uses_host_cpuid()) {
-        char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
-        char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 };
-        int family, model, stepping;
-
-        host_vendor_fms(vendor, &family, &model, &stepping);
-        cpu_x86_fill_model_id(model_id);
-
-        object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
-        object_property_set_int(OBJECT(cpu), "family", family, &error_abort);
-        object_property_set_int(OBJECT(cpu), "model", model, &error_abort);
-        object_property_set_int(OBJECT(cpu), "stepping", stepping,
-                                &error_abort);
-        object_property_set_str(OBJECT(cpu), "model-id", model_id,
-                                &error_abort);
-
-        if (kvm_enabled()) {
-            env->cpuid_min_level =
-                kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
-            env->cpuid_min_xlevel =
-                kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
-            env->cpuid_min_xlevel2 =
-                kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
-        } else {
-            env->cpuid_min_level =
-                hvf_get_supported_cpuid(0x0, 0, R_EAX);
-            env->cpuid_min_xlevel =
-                hvf_get_supported_cpuid(0x80000000, 0, R_EAX);
-            env->cpuid_min_xlevel2 =
-                hvf_get_supported_cpuid(0xC0000000, 0, R_EAX);
-        }
-
-        if (lmce_supported()) {
-            object_property_set_bool(OBJECT(cpu), "lmce", true, &error_abort);
-        }
-    } else {
-        object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
-                                &error_abort);
-        object_property_set_int(OBJECT(cpu), "family", 6, &error_abort);
-        object_property_set_int(OBJECT(cpu), "model", 6, &error_abort);
-        object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort);
-        object_property_set_str(OBJECT(cpu), "model-id",
-                                "QEMU TCG CPU version " QEMU_HW_VERSION,
-                                &error_abort);
-    }
-
     object_property_set_bool(OBJECT(cpu), "pmu", true, &error_abort);
+
+    /*
+     * these defaults are used for TCG and all other accelerators
+     * besides KVM and HVF, which overwrite these values
+     */
+    object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
+                            &error_abort);
+    object_property_set_int(OBJECT(cpu), "family", 6, &error_abort);
+    object_property_set_int(OBJECT(cpu), "model", 6, &error_abort);
+    object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort);
+    object_property_set_str(OBJECT(cpu), "model-id",
+                            "QEMU TCG CPU version " QEMU_HW_VERSION,
+                            &error_abort);
 }
 
 static const TypeInfo max_x86_cpu_type_info = {
@@ -4313,31 +4161,6 @@ static const TypeInfo max_x86_cpu_type_info = {
     .class_init = max_x86_cpu_class_init,
 };
 
-#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
-static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
-{
-    X86CPUClass *xcc = X86_CPU_CLASS(oc);
-
-    xcc->host_cpuid_required = true;
-    xcc->ordering = 8;
-
-#if defined(CONFIG_KVM)
-    xcc->model_description =
-        "KVM processor with all supported host features ";
-#elif defined(CONFIG_HVF)
-    xcc->model_description =
-        "HVF processor with all supported host features ";
-#endif
-}
-
-static const TypeInfo host_x86_cpu_type_info = {
-    .name = X86_CPU_TYPE_NAME("host"),
-    .parent = X86_CPU_TYPE_NAME("max"),
-    .class_init = host_x86_cpu_class_init,
-};
-
-#endif
-
 static char *feature_word_description(FeatureWordInfo *f, uint32_t bit)
 {
     assert(f->type == CPUID_FEATURE_WORD || f->type == MSR_FEATURE_WORD);
@@ -5063,7 +4886,7 @@ static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
     return r;
 }
 
-static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
+void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
 {
     PropValue *pv;
     for (pv = props; pv->prop; pv++) {
@@ -5110,8 +4933,6 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
 {
     X86CPUDefinition *def = model->cpudef;
     CPUX86State *env = &cpu->env;
-    const char *vendor;
-    char host_vendor[CPUID_VENDOR_SZ + 1];
     FeatureWord w;
 
     /*NOTE: any property set by this function should be returned by
@@ -5138,18 +4959,6 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
     /* legacy-cache defaults to 'off' if CPU model provides cache info */
     cpu->legacy_cache = !def->cache_info;
 
-    /* Special cases not set in the X86CPUDefinition structs: */
-    /* TODO: in-kernel irqchip for hvf */
-    if (kvm_enabled()) {
-        if (!kvm_irqchip_in_kernel()) {
-            x86_cpu_change_kvm_default("x2apic", "off");
-        }
-
-        x86_cpu_apply_props(cpu, kvm_default_props);
-    } else if (tcg_enabled()) {
-        x86_cpu_apply_props(cpu, tcg_default_props);
-    }
-
     env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
 
     /* sysenter isn't supported in compatibility mode on AMD,
@@ -5159,15 +4968,12 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
      * KVM's sysenter/syscall emulation in compatibility mode and
      * when doing cross vendor migration
      */
-    vendor = def->vendor;
-    if (accel_uses_host_cpuid()) {
-        uint32_t  ebx = 0, ecx = 0, edx = 0;
-        host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
-        x86_cpu_vendor_words2str(host_vendor, ebx, edx, ecx);
-        vendor = host_vendor;
-    }
 
-    object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
+    /*
+     * vendor property is set here but then overloaded with the
+     * host cpu vendor for KVM and HVF.
+     */
+    object_property_set_str(OBJECT(cpu), "vendor", def->vendor, &error_abort);
 
     x86_cpu_apply_version_props(cpu, model);
 
@@ -6192,53 +5998,12 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
         apic_mmio_map_once = true;
      }
 }
-
-static void x86_cpu_machine_done(Notifier *n, void *unused)
-{
-    X86CPU *cpu = container_of(n, X86CPU, machine_done);
-    MemoryRegion *smram =
-        (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
-
-    if (smram) {
-        cpu->smram = g_new(MemoryRegion, 1);
-        memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram",
-                                 smram, 0, 4 * GiB);
-        memory_region_set_enabled(cpu->smram, true);
-        memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->smram, 1);
-    }
-}
 #else
 static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
 {
 }
 #endif
 
-/* Note: Only safe for use on x86(-64) hosts */
-static uint32_t x86_host_phys_bits(void)
-{
-    uint32_t eax;
-    uint32_t host_phys_bits;
-
-    host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL);
-    if (eax >= 0x80000008) {
-        host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL);
-        /* Note: According to AMD doc 25481 rev 2.34 they have a field
-         * at 23:16 that can specify a maximum physical address bits for
-         * the guest that can override this value; but I've not seen
-         * anything with that set.
-         */
-        host_phys_bits = eax & 0xff;
-    } else {
-        /* It's an odd 64 bit machine that doesn't have the leaf for
-         * physical address bits; fall back to 36 that's most older
-         * Intel.
-         */
-        host_phys_bits = 36;
-    }
-
-    return host_phys_bits;
-}
-
 static void x86_cpu_adjust_level(X86CPU *cpu, uint32_t *min, uint32_t value)
 {
     if (*min < value) {
@@ -6521,27 +6286,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
     Error *local_err = NULL;
     static bool ht_warned;
 
-    if (xcc->host_cpuid_required) {
-        if (!accel_uses_host_cpuid()) {
-            g_autofree char *name = x86_cpu_class_get_model_name(xcc);
-            error_setg(&local_err, "CPU model '%s' requires KVM", name);
-            goto out;
-        }
+    /* The accelerator realizefn needs to be called first. */
+    if (xcc->accel) {
+        xcc->accel->cpu_realizefn(cpu, errp);
     }
 
-    if (cpu->max_features && accel_uses_host_cpuid()) {
-        if (enable_cpu_pm) {
-            host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
-                       &cpu->mwait.ecx, &cpu->mwait.edx);
-            env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
-            if (kvm_enabled() && kvm_has_waitpkg()) {
-                env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG;
-            }
-        }
-        if (kvm_enabled() && cpu->ucode_rev == 0) {
-            cpu->ucode_rev = kvm_arch_get_supported_msr_feature(kvm_state,
-                                                                MSR_IA32_UCODE_REV);
-        }
+    if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
+        g_autofree char *name = x86_cpu_class_get_model_name(xcc);
+        error_setg(&local_err, "CPU model '%s' requires KVM or HVF", name);
+        goto out;
     }
 
     if (cpu->ucode_rev == 0) {
@@ -6593,39 +6346,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
      * consumer AMD devices but nothing else.
      */
     if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
-        if (accel_uses_host_cpuid()) {
-            uint32_t host_phys_bits = x86_host_phys_bits();
-            static bool warned;
-
-            /* Print a warning if the user set it to a value that's not the
-             * host value.
-             */
-            if (cpu->phys_bits != host_phys_bits && cpu->phys_bits != 0 &&
-                !warned) {
-                warn_report("Host physical bits (%u)"
-                            " does not match phys-bits property (%u)",
-                            host_phys_bits, cpu->phys_bits);
-                warned = true;
-            }
-
-            if (cpu->host_phys_bits) {
-                /* The user asked for us to use the host physical bits */
-                cpu->phys_bits = host_phys_bits;
-                if (cpu->host_phys_bits_limit &&
-                    cpu->phys_bits > cpu->host_phys_bits_limit) {
-                    cpu->phys_bits = cpu->host_phys_bits_limit;
-                }
-            }
-
-            if (cpu->phys_bits &&
-                (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS ||
-                cpu->phys_bits < 32)) {
-                error_setg(errp, "phys-bits should be between 32 and %u "
-                                 " (but is %u)",
-                                 TARGET_PHYS_ADDR_SPACE_BITS, cpu->phys_bits);
-                return;
-            }
-        } else {
+        if (!accel_uses_host_cpuid()) {
             if (cpu->phys_bits && cpu->phys_bits != TCG_PHYS_ADDR_BITS) {
                 error_setg(errp, "TCG only supports phys-bits=%u",
                                   TCG_PHYS_ADDR_BITS);
@@ -6633,8 +6354,8 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
             }
         }
         /* 0 means it was not explicitly set by the user (or by machine
-         * compat_props or by the host code above). In this case, the default
-         * is the value used by TCG (40).
+         * compat_props or by the host code in host-cpu.c).
+         * In this case, the default is the value used by TCG (40).
          */
         if (cpu->phys_bits == 0) {
             cpu->phys_bits = TCG_PHYS_ADDR_BITS;
@@ -6704,33 +6425,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
 
     mce_init(cpu);
 
-#ifndef CONFIG_USER_ONLY
-    if (tcg_enabled()) {
-        cpu->cpu_as_mem = g_new(MemoryRegion, 1);
-        cpu->cpu_as_root = g_new(MemoryRegion, 1);
-
-        /* Outer container... */
-        memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
-        memory_region_set_enabled(cpu->cpu_as_root, true);
-
-        /* ... with two regions inside: normal system memory with low
-         * priority, and...
-         */
-        memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory",
-                                 get_system_memory(), 0, ~0ull);
-        memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
-        memory_region_set_enabled(cpu->cpu_as_mem, true);
-
-        cs->num_ases = 2;
-        cpu_address_space_init(cs, 0, "cpu-memory", cs->memory);
-        cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root);
-
-        /* ... SMRAM with higher priority, linked from /machine/smram.  */
-        cpu->machine_done.notify = x86_cpu_machine_done;
-        qemu_add_machine_init_done_notifier(&cpu->machine_done);
-    }
-#endif
-
     qemu_init_vcpu(cs);
 
     /*
@@ -6992,6 +6686,11 @@ static void x86_cpu_initfn(Object *obj)
     if (xcc->model) {
         x86_cpu_load_model(cpu, xcc->model);
     }
+
+    /* if required, do the accelerator-specific cpu initialization */
+    if (xcc->accel) {
+        xcc->accel->cpu_instance_init(cpu);
+    }
 }
 
 static int64_t x86_cpu_get_arch_id(CPUState *cs)
@@ -7248,11 +6947,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     cc->class_by_name = x86_cpu_class_by_name;
     cc->parse_features = x86_cpu_parse_featurestr;
     cc->has_work = x86_cpu_has_work;
-
-#ifdef CONFIG_TCG
-    tcg_cpu_common_class_init(cc);
-#endif /* CONFIG_TCG */
-
     cc->dump_state = x86_cpu_dump_state;
     cc->set_pc = x86_cpu_set_pc;
     cc->gdb_read_register = x86_cpu_gdb_read_register;
@@ -7347,6 +7041,13 @@ static const TypeInfo x86_base_cpu_type_info = {
         .class_init = x86_cpu_base_class_init,
 };
 
+static const TypeInfo x86_cpu_accel_type_info = {
+    .name = TYPE_X86_CPU_ACCEL,
+    .parent = TYPE_OBJECT,
+    .abstract = true,
+    .class_size = sizeof(X86CPUAccelClass),
+};
+
 static void x86_cpu_register_types(void)
 {
     int i;
@@ -7357,9 +7058,26 @@ static void x86_cpu_register_types(void)
     }
     type_register_static(&max_x86_cpu_type_info);
     type_register_static(&x86_base_cpu_type_info);
-#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
-    type_register_static(&host_x86_cpu_type_info);
-#endif
+    type_register_static(&x86_cpu_accel_type_info);
 }
 
 type_init(x86_cpu_register_types)
+
+static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
+{
+    X86CPUClass *xcc = X86_CPU_CLASS(klass);
+    const X86CPUAccelClass **accel = opaque;
+
+    xcc->accel = *accel;
+    xcc->accel->cpu_common_class_init(xcc);
+}
+
+void x86_cpu_accel_init(const char *accel_name)
+{
+    X86CPUAccelClass *acc;
+
+    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
+    g_assert(acc != NULL);
+
+    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
+}
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index a0d64613dc..b3e39fc631 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1905,13 +1905,20 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 
 /* cpu.c */
+void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
+                              uint32_t vendor2, uint32_t vendor3);
+typedef struct PropValue {
+    const char *prop, *value;
+} PropValue;
+void x86_cpu_apply_props(X86CPU *cpu, PropValue *props);
+
+/* cpu.c other functions (cpuid) */
 void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                    uint32_t *eax, uint32_t *ebx,
                    uint32_t *ecx, uint32_t *edx);
 void cpu_clear_apic_feature(CPUX86State *env);
 void host_cpuid(uint32_t function, uint32_t count,
                 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
-void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);
 
 /* helper.c */
 void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
@@ -2111,17 +2118,6 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
 void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
                                    TPRAccess access);
 
-
-/* Change the value of a KVM-specific default
- *
- * If value is NULL, no default will be set and the original
- * value from the CPU model table will be kept.
- *
- * It is valid to call this function only for properties that
- * are already present in the kvm_default_props table.
- */
-void x86_cpu_change_kvm_default(const char *prop, const char *value);
-
 /* Special values for X86CPUVersion: */
 
 /* Resolve to latest CPU version */
diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c
new file mode 100644
index 0000000000..f92ec8feb9
--- /dev/null
+++ b/target/i386/host-cpu.c
@@ -0,0 +1,198 @@
+/*
+ * x86 host CPU functions, and "host" cpu type initialization
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "host-cpu.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+
+/* Note: Only safe for use on x86(-64) hosts */
+static uint32_t host_cpu_phys_bits(void)
+{
+    uint32_t eax;
+    uint32_t host_phys_bits;
+
+    host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL);
+    if (eax >= 0x80000008) {
+        host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL);
+        /*
+         * Note: According to AMD doc 25481 rev 2.34 they have a field
+         * at 23:16 that can specify a maximum physical address bits for
+         * the guest that can override this value; but I've not seen
+         * anything with that set.
+         */
+        host_phys_bits = eax & 0xff;
+    } else {
+        /*
+         * It's an odd 64 bit machine that doesn't have the leaf for
+         * physical address bits; fall back to 36 that's most older
+         * Intel.
+         */
+        host_phys_bits = 36;
+    }
+
+    return host_phys_bits;
+}
+
+static void host_cpu_enable_cpu_pm(X86CPU *cpu)
+{
+    CPUX86State *env = &cpu->env;
+
+    host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
+               &cpu->mwait.ecx, &cpu->mwait.edx);
+    env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
+}
+
+static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu, Error **errp)
+{
+    uint32_t host_phys_bits = host_cpu_phys_bits();
+    uint32_t phys_bits = cpu->phys_bits;
+    static bool warned;
+
+    /*
+     * Print a warning if the user set it to a value that's not the
+     * host value.
+     */
+    if (phys_bits != host_phys_bits && phys_bits != 0 &&
+        !warned) {
+        warn_report("Host physical bits (%u)"
+                    " does not match phys-bits property (%u)",
+                    host_phys_bits, phys_bits);
+        warned = true;
+    }
+
+    if (cpu->host_phys_bits) {
+        /* The user asked for us to use the host physical bits */
+        phys_bits = host_phys_bits;
+        if (cpu->host_phys_bits_limit &&
+            phys_bits > cpu->host_phys_bits_limit) {
+            phys_bits = cpu->host_phys_bits_limit;
+        }
+    }
+
+    if (phys_bits &&
+        (phys_bits > TARGET_PHYS_ADDR_SPACE_BITS ||
+         phys_bits < 32)) {
+        error_setg(errp, "phys-bits should be between 32 and %u "
+                   " (but is %u)",
+                   TARGET_PHYS_ADDR_SPACE_BITS, phys_bits);
+    }
+
+    return phys_bits;
+}
+
+void host_cpu_realizefn(X86CPU *cpu, Error **errp)
+{
+    CPUX86State *env = &cpu->env;
+
+    if (cpu->max_features && enable_cpu_pm) {
+        host_cpu_enable_cpu_pm(cpu);
+    }
+    if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
+        cpu->phys_bits = host_cpu_adjust_phys_bits(cpu, errp);
+    }
+}
+
+#define CPUID_MODEL_ID_SZ 48
+/**
+ * cpu_x86_fill_model_id:
+ * Get CPUID model ID string from host CPU.
+ *
+ * @str should have at least CPUID_MODEL_ID_SZ bytes
+ *
+ * The function does NOT add a null terminator to the string
+ * automatically.
+ */
+static int host_cpu_fill_model_id(char *str)
+{
+    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
+        memcpy(str + i * 16 +  0, &eax, 4);
+        memcpy(str + i * 16 +  4, &ebx, 4);
+        memcpy(str + i * 16 +  8, &ecx, 4);
+        memcpy(str + i * 16 + 12, &edx, 4);
+    }
+    return 0;
+}
+
+void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping)
+{
+    uint32_t eax, ebx, ecx, edx;
+
+    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
+    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
+
+    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
+    if (family) {
+        *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
+    }
+    if (model) {
+        *model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
+    }
+    if (stepping) {
+        *stepping = eax & 0x0F;
+    }
+}
+
+void host_cpu_instance_init(X86CPU *cpu)
+{
+    uint32_t ebx = 0, ecx = 0, edx = 0;
+    char vendor[CPUID_VENDOR_SZ + 1];
+
+    host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
+    x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
+
+    object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
+}
+
+void host_cpu_max_instance_init(X86CPU *cpu)
+{
+    char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
+    char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 };
+    int family, model, stepping;
+
+    host_cpu_vendor_fms(vendor, &family, &model, &stepping);
+    host_cpu_fill_model_id(model_id);
+
+    object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
+    object_property_set_int(OBJECT(cpu), "family", family, &error_abort);
+    object_property_set_int(OBJECT(cpu), "model", model, &error_abort);
+    object_property_set_int(OBJECT(cpu), "stepping", stepping,
+                            &error_abort);
+    object_property_set_str(OBJECT(cpu), "model-id", model_id,
+                            &error_abort);
+}
+
+static void host_cpu_class_init(ObjectClass *oc, void *data)
+{
+    X86CPUClass *xcc = X86_CPU_CLASS(oc);
+
+    xcc->host_cpuid_required = true;
+    xcc->ordering = 8;
+    xcc->model_description =
+        g_strdup_printf("processor with all supported host features ");
+}
+
+static const TypeInfo host_cpu_type_info = {
+    .name = X86_CPU_TYPE_NAME("host"),
+    .parent = X86_CPU_TYPE_NAME("max"),
+    .class_init = host_cpu_class_init,
+};
+
+static void host_cpu_type_init(void)
+{
+    type_register_static(&host_cpu_type_info);
+}
+
+type_init(host_cpu_type_init);
diff --git a/target/i386/host-cpu.h b/target/i386/host-cpu.h
new file mode 100644
index 0000000000..cd10cbcf1f
--- /dev/null
+++ b/target/i386/host-cpu.h
@@ -0,0 +1,19 @@
+/*
+ * x86 host CPU type initialization and host CPU functions
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HOST_CPU_H
+#define HOST_CPU_H
+
+void host_cpu_instance_init(X86CPU *cpu);
+void host_cpu_max_instance_init(X86CPU *cpu);
+void host_cpu_realizefn(X86CPU *cpu, Error **errp);
+
+void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping);
+
+#endif /* HOST_CPU_H */
diff --git a/target/i386/hvf/cpu.c b/target/i386/hvf/cpu.c
new file mode 100644
index 0000000000..7e7dc044d3
--- /dev/null
+++ b/target/i386/hvf/cpu.c
@@ -0,0 +1,76 @@
+/*
+ * x86 HVF CPU type initialization
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "host-cpu.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "sysemu/hvf.h"
+
+static void hvf_cpu_common_class_init(X86CPUClass *xcc)
+{
+}
+
+static void hvf_cpu_max_instance_init(X86CPU *cpu)
+{
+    CPUX86State *env = &cpu->env;
+
+    host_cpu_max_instance_init(cpu);
+
+    env->cpuid_min_level =
+        hvf_get_supported_cpuid(0x0, 0, R_EAX);
+    env->cpuid_min_xlevel =
+        hvf_get_supported_cpuid(0x80000000, 0, R_EAX);
+    env->cpuid_min_xlevel2 =
+        hvf_get_supported_cpuid(0xC0000000, 0, R_EAX);
+}
+
+static void hvf_cpu_instance_init(X86CPU *cpu)
+{
+    host_cpu_instance_init(cpu);
+
+    /* Special cases not set in the X86CPUDefinition structs: */
+    /* TODO: in-kernel irqchip for hvf */
+
+    if (cpu->max_features) {
+        hvf_cpu_max_instance_init(cpu);
+    }
+}
+
+static void hvf_cpu_accel_class_init(ObjectClass *oc, void *data)
+{
+    X86CPUAccelClass *acc = X86_CPU_ACCEL_CLASS(oc);
+
+    acc->cpu_realizefn = host_cpu_realizefn;
+    acc->cpu_common_class_init = hvf_cpu_common_class_init;
+    acc->cpu_instance_init = hvf_cpu_instance_init;
+};
+static const TypeInfo hvf_cpu_accel_type_info = {
+    .name = X86_CPU_ACCEL_TYPE_NAME("hvf"),
+
+    .parent = TYPE_X86_CPU_ACCEL,
+    .class_init = hvf_cpu_accel_class_init,
+    .abstract = true,
+};
+static void hvf_cpu_accel_register_types(void)
+{
+    type_register_static(&hvf_cpu_accel_type_info);
+}
+type_init(hvf_cpu_accel_register_types);
+
+static void hvf_cpu_accel_init(void)
+{
+    if (hvf_enabled()) {
+        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("hvf"));
+    }
+}
+
+accel_cpu_init(hvf_cpu_accel_init);
diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.build
index 409c9a3f14..a7fba5724c 100644
--- a/target/i386/hvf/meson.build
+++ b/target/i386/hvf/meson.build
@@ -10,4 +10,5 @@ i386_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
   'x86_mmu.c',
   'x86_task.c',
   'x86hvf.c',
+  'cpu.c',
 ))
diff --git a/target/i386/kvm/cpu.c b/target/i386/kvm/cpu.c
new file mode 100644
index 0000000000..bc5f519479
--- /dev/null
+++ b/target/i386/kvm/cpu.c
@@ -0,0 +1,157 @@
+/*
+ * x86 KVM CPU type initialization
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "host-cpu.h"
+#include "kvm-cpu.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+
+#include "kvm_i386.h"
+
+static void kvm_cpu_realizefn(X86CPU *cpu, Error **errp)
+{
+    CPUX86State *env = &cpu->env;
+
+    /*
+     * The realize order is important, since x86_cpu_realize() checks if
+     * nothing else has been set by the user (or by accelerators) in
+     * cpu->ucode_rev and cpu->phys_bits.
+     *
+     * realize order:
+     * kvm_cpu -> host_cpu -> x86_cpu
+     */
+    if (cpu->max_features) {
+        if (enable_cpu_pm && kvm_has_waitpkg()) {
+            env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG;
+        }
+        if (cpu->ucode_rev == 0) {
+            cpu->ucode_rev =
+                kvm_arch_get_supported_msr_feature(kvm_state,
+                                                   MSR_IA32_UCODE_REV);
+        }
+    }
+    host_cpu_realizefn(cpu, errp);
+}
+
+static void kvm_cpu_common_class_init(X86CPUClass *xcc)
+{
+}
+
+/*
+ * KVM-specific features that are automatically added/removed
+ * from all CPU models when KVM is enabled.
+ */
+static PropValue kvm_default_props[] = {
+    { "kvmclock", "on" },
+    { "kvm-nopiodelay", "on" },
+    { "kvm-asyncpf", "on" },
+    { "kvm-steal-time", "on" },
+    { "kvm-pv-eoi", "on" },
+    { "kvmclock-stable-bit", "on" },
+    { "x2apic", "on" },
+    { "acpi", "off" },
+    { "monitor", "off" },
+    { "svm", "off" },
+    { NULL, NULL },
+};
+
+void x86_cpu_change_kvm_default(const char *prop, const char *value)
+{
+    PropValue *pv;
+    for (pv = kvm_default_props; pv->prop; pv++) {
+        if (!strcmp(pv->prop, prop)) {
+            pv->value = value;
+            break;
+        }
+    }
+
+    /*
+     * It is valid to call this function only for properties that
+     * are already present in the kvm_default_props table.
+     */
+    assert(pv->prop);
+}
+
+static bool lmce_supported(void)
+{
+    uint64_t mce_cap = 0;
+
+    if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) {
+        return false;
+    }
+    return !!(mce_cap & MCG_LMCE_P);
+}
+
+static void kvm_cpu_max_instance_init(X86CPU *cpu)
+{
+    CPUX86State *env = &cpu->env;
+    KVMState *s = kvm_state;
+
+    host_cpu_max_instance_init(cpu);
+
+    if (lmce_supported()) {
+        object_property_set_bool(OBJECT(cpu), "lmce", true, &error_abort);
+    }
+
+    env->cpuid_min_level =
+        kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
+    env->cpuid_min_xlevel =
+        kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
+    env->cpuid_min_xlevel2 =
+        kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
+}
+
+static void kvm_cpu_instance_init(X86CPU *cpu)
+{
+    host_cpu_instance_init(cpu);
+
+    if (!kvm_irqchip_in_kernel()) {
+        x86_cpu_change_kvm_default("x2apic", "off");
+    }
+
+    /* Special cases not set in the X86CPUDefinition structs: */
+
+    x86_cpu_apply_props(cpu, kvm_default_props);
+
+    if (cpu->max_features) {
+        kvm_cpu_max_instance_init(cpu);
+    }
+}
+
+static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
+{
+    X86CPUAccelClass *acc = X86_CPU_ACCEL_CLASS(oc);
+
+    acc->cpu_realizefn = kvm_cpu_realizefn;
+    acc->cpu_common_class_init = kvm_cpu_common_class_init;
+    acc->cpu_instance_init = kvm_cpu_instance_init;
+}
+static const TypeInfo kvm_cpu_accel_type_info = {
+    .name = X86_CPU_ACCEL_TYPE_NAME("kvm"),
+
+    .parent = TYPE_X86_CPU_ACCEL,
+    .class_init = kvm_cpu_accel_class_init,
+    .abstract = true,
+};
+static void kvm_cpu_accel_register_types(void)
+{
+    type_register_static(&kvm_cpu_accel_type_info);
+}
+type_init(kvm_cpu_accel_register_types);
+
+static void kvm_cpu_accel_init(void)
+{
+    if (kvm_enabled()) {
+        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("kvm"));
+    }
+}
+accel_cpu_init(kvm_cpu_accel_init);
diff --git a/target/i386/kvm/kvm-cpu.h b/target/i386/kvm/kvm-cpu.h
new file mode 100644
index 0000000000..e858ca21e5
--- /dev/null
+++ b/target/i386/kvm/kvm-cpu.h
@@ -0,0 +1,41 @@
+/*
+ * i386 KVM CPU type and functions
+ *
+ *  Copyright (c) 2003 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 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KVM_CPU_H
+#define KVM_CPU_H
+
+#ifdef CONFIG_KVM
+/*
+ * Change the value of a KVM-specific default
+ *
+ * If value is NULL, no default will be set and the original
+ * value from the CPU model table will be kept.
+ *
+ * It is valid to call this function only for properties that
+ * are already present in the kvm_default_props table.
+ */
+void x86_cpu_change_kvm_default(const char *prop, const char *value);
+
+#else /* !CONFIG_KVM */
+
+#define x86_cpu_change_kvm_default(a, b)
+
+#endif /* CONFIG_KVM */
+
+#endif /* KVM_CPU_H */
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index a2934dda02..35c86fdba6 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -22,6 +22,7 @@
 #include "standard-headers/asm-x86/kvm_para.h"
 
 #include "cpu.h"
+#include "host-cpu.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/hw_accel.h"
 #include "sysemu/kvm_int.h"
@@ -285,7 +286,7 @@ static bool host_tsx_broken(void)
     int family, model, stepping;\
     char vendor[CPUID_VENDOR_SZ + 1];
 
-    host_vendor_fms(vendor, &family, &model, &stepping);
+    host_cpu_vendor_fms(vendor, &family, &model, &stepping);
 
     /* Check if we are running on a Haswell host known to have broken TSX */
     return !strcmp(vendor, CPUID_VENDOR_INTEL) &&
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
index 1d66559187..0bc3724eb3 100644
--- a/target/i386/kvm/meson.build
+++ b/target/i386/kvm/meson.build
@@ -1,3 +1,8 @@
 i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
-i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
+
+i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files(
+  'kvm.c',
+  'cpu.c',
+))
+
 i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 9c20208e5a..4e6e915e7f 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -6,8 +6,12 @@ i386_ss.add(files(
   'xsave_helper.c',
   'cpu-dump.c',
 ))
-i386_ss.add(when: 'CONFIG_TCG', if_true: files('tcg-cpu.c'))
-i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-stub.c'))
+
+i386_ss.add(when: 'CONFIG_SEV', if_true: files('host-cpu.c', 'sev.c'), if_false: files('sev-stub.c'))
+
+# x86 cpu type
+i386_ss.add(when: 'CONFIG_KVM', if_true: files('host-cpu.c'))
+i386_ss.add(when: 'CONFIG_HVF', if_true: files('host-cpu.c'))
 
 i386_softmmu_ss = ss.source_set()
 i386_softmmu_ss.add(files(
diff --git a/target/i386/tcg-cpu.c b/target/i386/tcg-cpu.c
deleted file mode 100644
index 628dd29fe7..0000000000
--- a/target/i386/tcg-cpu.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * i386 TCG cpu class initialization
- *
- *  Copyright (c) 2003 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 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "tcg-cpu.h"
-#include "exec/exec-all.h"
-#include "sysemu/runstate.h"
-#include "helper-tcg.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "hw/i386/apic.h"
-#endif
-
-/* Frob eflags into and out of the CPU temporary format.  */
-
-static void x86_cpu_exec_enter(CPUState *cs)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    env->df = 1 - (2 * ((env->eflags >> 10) & 1));
-    CC_OP = CC_OP_EFLAGS;
-    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-}
-
-static void x86_cpu_exec_exit(CPUState *cs)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    env->eflags = cpu_compute_eflags(env);
-}
-
-static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
-{
-    X86CPU *cpu = X86_CPU(cs);
-
-    cpu->env.eip = tb->pc - tb->cs_base;
-}
-
-void tcg_cpu_common_class_init(CPUClass *cc)
-{
-    cc->do_interrupt = x86_cpu_do_interrupt;
-    cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
-    cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
-    cc->cpu_exec_enter = x86_cpu_exec_enter;
-    cc->cpu_exec_exit = x86_cpu_exec_exit;
-    cc->tcg_initialize = tcg_x86_init;
-    cc->tlb_fill = x86_cpu_tlb_fill;
-#ifndef CONFIG_USER_ONLY
-    cc->debug_excp_handler = breakpoint_handler;
-#endif
-}
diff --git a/target/i386/tcg-cpu.h b/target/i386/tcg-cpu.h
deleted file mode 100644
index 81f02e562e..0000000000
--- a/target/i386/tcg-cpu.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * i386 TCG CPU class initialization
- *
- * Copyright 2020 SUSE LLC
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef TCG_CPU_H
-#define TCG_CPU_H
-
-void tcg_cpu_common_class_init(CPUClass *cc);
-
-#endif /* TCG_CPU_H */
diff --git a/target/i386/tcg/cpu.c b/target/i386/tcg/cpu.c
new file mode 100644
index 0000000000..e7d4effdd0
--- /dev/null
+++ b/target/i386/tcg/cpu.c
@@ -0,0 +1,181 @@
+/*
+ * i386 TCG cpu class initialization
+ *
+ *  Copyright (c) 2003 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 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "cpu.h"
+#include "helper-tcg.h"
+#include "sysemu/sysemu.h"
+
+#ifndef CONFIG_USER_ONLY
+#include "exec/address-spaces.h"
+#endif
+
+/* Frob eflags into and out of the CPU temporary format.  */
+
+static void x86_cpu_exec_enter(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    env->df = 1 - (2 * ((env->eflags >> 10) & 1));
+    CC_OP = CC_OP_EFLAGS;
+    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+}
+
+static void x86_cpu_exec_exit(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    env->eflags = cpu_compute_eflags(env);
+}
+
+static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    X86CPU *cpu = X86_CPU(cs);
+
+    cpu->env.eip = tb->pc - tb->cs_base;
+}
+
+#ifndef CONFIG_USER_ONLY
+
+static void x86_cpu_machine_done(Notifier *n, void *unused)
+{
+    X86CPU *cpu = container_of(n, X86CPU, machine_done);
+    MemoryRegion *smram =
+        (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
+
+    if (smram) {
+        cpu->smram = g_new(MemoryRegion, 1);
+        memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram",
+                                 smram, 0, 4 * GiB);
+        memory_region_set_enabled(cpu->smram, true);
+        memory_region_add_subregion_overlap(cpu->cpu_as_root, 0,
+                                            cpu->smram, 1);
+    }
+}
+
+static void tcg_cpu_realizefn(X86CPU *cpu, Error **errp)
+{
+    CPUState *cs = CPU(cpu);
+
+    /*
+     * The realize order is important, since x86_cpu_realize() checks if
+     * nothing else has been set by the user (or by accelerators) in
+     * cpu->ucode_rev and cpu->phys_bits, and the memory regions
+     * initialized here are needed for the vcpu initialization.
+     *
+     * realize order:
+     * tcg_cpu -> host_cpu -> x86_cpu
+     */
+    cpu->cpu_as_mem = g_new(MemoryRegion, 1);
+    cpu->cpu_as_root = g_new(MemoryRegion, 1);
+
+    /* Outer container... */
+    memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
+    memory_region_set_enabled(cpu->cpu_as_root, true);
+
+    /*
+     * ... with two regions inside: normal system memory with low
+     * priority, and...
+     */
+    memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory",
+                             get_system_memory(), 0, ~0ull);
+    memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
+    memory_region_set_enabled(cpu->cpu_as_mem, true);
+
+    cs->num_ases = 2;
+    cpu_address_space_init(cs, 0, "cpu-memory", cs->memory);
+    cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root);
+
+    /* ... SMRAM with higher priority, linked from /machine/smram.  */
+    cpu->machine_done.notify = x86_cpu_machine_done;
+    qemu_add_machine_init_done_notifier(&cpu->machine_done);
+}
+
+#else /* CONFIG_USER_ONLY */
+
+static void tcg_cpu_realizefn(X86CPU *cpu, Error **errp)
+{
+}
+
+#endif /* !CONFIG_USER_ONLY */
+
+
+static void tcg_cpu_common_class_init(X86CPUClass *xcc)
+{
+    CPUClass *cc = CPU_CLASS(xcc);
+
+    cc->do_interrupt = x86_cpu_do_interrupt;
+    cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
+    cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
+    cc->cpu_exec_enter = x86_cpu_exec_enter;
+    cc->cpu_exec_exit = x86_cpu_exec_exit;
+    cc->tcg_initialize = tcg_x86_init;
+    cc->tlb_fill = x86_cpu_tlb_fill;
+#ifndef CONFIG_USER_ONLY
+    cc->debug_excp_handler = breakpoint_handler;
+#endif /* !CONFIG_USER_ONLY */
+}
+
+/*
+ * TCG-specific defaults that override all CPU models when using TCG
+ */
+static PropValue tcg_default_props[] = {
+    { "vme", "off" },
+    { NULL, NULL },
+};
+
+static void tcg_cpu_instance_init(X86CPU *cpu)
+{
+    /* Special cases not set in the X86CPUDefinition structs: */
+    x86_cpu_apply_props(cpu, tcg_default_props);
+}
+
+static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
+{
+    X86CPUAccelClass *acc = X86_CPU_ACCEL_CLASS(oc);
+
+    acc->cpu_realizefn = tcg_cpu_realizefn;
+    acc->cpu_common_class_init = tcg_cpu_common_class_init;
+    acc->cpu_instance_init = tcg_cpu_instance_init;
+}
+static const TypeInfo tcg_cpu_accel_type_info = {
+    .name = X86_CPU_ACCEL_TYPE_NAME("tcg"),
+
+    .parent = TYPE_X86_CPU_ACCEL,
+    .class_init = tcg_cpu_accel_class_init,
+    .abstract = true,
+};
+static void tcg_cpu_accel_register_types(void)
+{
+    type_register_static(&tcg_cpu_accel_type_info);
+}
+type_init(tcg_cpu_accel_register_types);
+
+static void tcg_cpu_accel_init(void)
+{
+    if (tcg_enabled()) {
+        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("tcg"));
+    }
+}
+
+accel_cpu_init(tcg_cpu_accel_init);
diff --git a/target/i386/tcg/meson.build b/target/i386/tcg/meson.build
index 02794226c2..9e439df9c7 100644
--- a/target/i386/tcg/meson.build
+++ b/target/i386/tcg/meson.build
@@ -10,4 +10,5 @@ i386_ss.add(when: 'CONFIG_TCG', if_true: files(
   'seg_helper.c',
   'smm_helper.c',
   'svm_helper.c',
-  'translate.c'), if_false: files('tcg-stub.c'))
+  'translate.c',
+  'cpu.c'), if_false: files('tcg-stub.c'))
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (9 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 10/12] i386: split cpu accelerators from cpu.c Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 16:59   ` Eduardo Habkost
  2020-11-24 20:13   ` Paolo Bonzini
  2020-11-24 16:22 ` [RFC v5 12/12] accel: centralize initialization of CpusAccelOps Claudio Fontana
  2020-11-24 20:14 ` [RFC v5 00/12] i386 cleanup Paolo Bonzini
  12 siblings, 2 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 target/i386/cpu-qom.h |  2 --
 target/i386/cpu.c     | 27 ++++++++++++++++++++-------
 target/i386/hvf/cpu.c |  9 ---------
 target/i386/kvm/cpu.c |  8 --------
 target/i386/tcg/cpu.c |  9 ---------
 5 files changed, 20 insertions(+), 35 deletions(-)

diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
index 9316e78e71..2cea5394c6 100644
--- a/target/i386/cpu-qom.h
+++ b/target/i386/cpu-qom.h
@@ -98,6 +98,4 @@ struct X86CPUAccelClass {
     void (*cpu_realizefn)(X86CPU *cpu, Error **errp);
 };
 
-void x86_cpu_accel_init(const char *accel_name);
-
 #endif
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b799723e53..f6fd055046 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7066,18 +7066,31 @@ type_init(x86_cpu_register_types)
 static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(klass);
-    const X86CPUAccelClass **accel = opaque;
+    X86CPUAccelClass *accel = opaque;
 
-    xcc->accel = *accel;
+    xcc->accel = accel;
     xcc->accel->cpu_common_class_init(xcc);
 }
 
-void x86_cpu_accel_init(const char *accel_name)
+static void x86_cpu_accel_init(void)
 {
-    X86CPUAccelClass *acc;
+    const char *ac_name;
+    ObjectClass *ac;
+    char *xac_name;
+    ObjectClass *xac;
 
-    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
-    g_assert(acc != NULL);
+    ac = object_get_class(OBJECT(current_accel()));
+    g_assert(ac != NULL);
+    ac_name = object_class_get_name(ac);
+    g_assert(ac_name != NULL);
 
-    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
+    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
+    xac = object_class_by_name(xac_name);
+    g_free(xac_name);
+
+    if (xac) {
+        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
+    }
 }
+
+accel_cpu_init(x86_cpu_accel_init);
diff --git a/target/i386/hvf/cpu.c b/target/i386/hvf/cpu.c
index 7e7dc044d3..70b6dbfc10 100644
--- a/target/i386/hvf/cpu.c
+++ b/target/i386/hvf/cpu.c
@@ -65,12 +65,3 @@ static void hvf_cpu_accel_register_types(void)
     type_register_static(&hvf_cpu_accel_type_info);
 }
 type_init(hvf_cpu_accel_register_types);
-
-static void hvf_cpu_accel_init(void)
-{
-    if (hvf_enabled()) {
-        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("hvf"));
-    }
-}
-
-accel_cpu_init(hvf_cpu_accel_init);
diff --git a/target/i386/kvm/cpu.c b/target/i386/kvm/cpu.c
index bc5f519479..c17ed5a3f2 100644
--- a/target/i386/kvm/cpu.c
+++ b/target/i386/kvm/cpu.c
@@ -147,11 +147,3 @@ static void kvm_cpu_accel_register_types(void)
     type_register_static(&kvm_cpu_accel_type_info);
 }
 type_init(kvm_cpu_accel_register_types);
-
-static void kvm_cpu_accel_init(void)
-{
-    if (kvm_enabled()) {
-        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("kvm"));
-    }
-}
-accel_cpu_init(kvm_cpu_accel_init);
diff --git a/target/i386/tcg/cpu.c b/target/i386/tcg/cpu.c
index e7d4effdd0..00166c36e9 100644
--- a/target/i386/tcg/cpu.c
+++ b/target/i386/tcg/cpu.c
@@ -170,12 +170,3 @@ static void tcg_cpu_accel_register_types(void)
     type_register_static(&tcg_cpu_accel_type_info);
 }
 type_init(tcg_cpu_accel_register_types);
-
-static void tcg_cpu_accel_init(void)
-{
-    if (tcg_enabled()) {
-        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("tcg"));
-    }
-}
-
-accel_cpu_init(tcg_cpu_accel_init);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (10 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces Claudio Fontana
@ 2020-11-24 16:22 ` Claudio Fontana
  2020-11-24 17:48   ` Eduardo Habkost
  2020-11-24 20:14 ` [RFC v5 00/12] i386 cleanup Paolo Bonzini
  12 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 16:22 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Claudio Fontana, Anthony Perard,
	Bruce Rogers, Olaf Hering, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 accel/kvm/kvm-all.c          |  9 -------
 accel/kvm/kvm-cpus.c         | 26 +++++++++++++-----
 accel/kvm/kvm-cpus.h         |  2 --
 accel/qtest/qtest.c          | 31 ++++++++++++----------
 accel/tcg/tcg-cpus-icount.c  | 11 +-------
 accel/tcg/tcg-cpus-icount.h  |  2 ++
 accel/tcg/tcg-cpus-mttcg.c   | 12 +++------
 accel/tcg/tcg-cpus-mttcg.h   | 19 ++++++++++++++
 accel/tcg/tcg-cpus-rr.c      |  7 -----
 accel/tcg/tcg-cpus.c         | 48 ++++++++++++++++++++++++++-------
 accel/tcg/tcg-cpus.h         |  4 ---
 accel/xen/xen-all.c          | 29 ++++++++++----------
 include/sysemu/cpus.h        | 39 ++++++++++++++++++++-------
 softmmu/cpus.c               | 51 +++++++++++++++++++++++++++++-------
 target/i386/hax/hax-all.c    |  9 -------
 target/i386/hax/hax-cpus.c   | 29 +++++++++++++++-----
 target/i386/hax/hax-cpus.h   |  2 --
 target/i386/hvf/hvf-cpus.c   | 27 ++++++++++++++-----
 target/i386/hvf/hvf-cpus.h   |  2 --
 target/i386/hvf/hvf.c        |  9 -------
 target/i386/whpx/whpx-all.c  |  9 -------
 target/i386/whpx/whpx-cpus.c | 29 +++++++++++++++-----
 target/i386/whpx/whpx-cpus.h |  2 --
 23 files changed, 251 insertions(+), 157 deletions(-)
 create mode 100644 accel/tcg/tcg-cpus-mttcg.h

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 509b249f52..33156cc4c7 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3234,12 +3234,3 @@ static void kvm_type_init(void)
 }
 
 type_init(kvm_type_init);
-
-static void kvm_accel_cpu_init(void)
-{
-    if (kvm_enabled()) {
-        cpus_register_accel(&kvm_cpus);
-    }
-}
-
-accel_cpu_init(kvm_accel_cpu_init);
diff --git a/accel/kvm/kvm-cpus.c b/accel/kvm/kvm-cpus.c
index d809b1e74c..33dc8e737a 100644
--- a/accel/kvm/kvm-cpus.c
+++ b/accel/kvm/kvm-cpus.c
@@ -74,11 +74,25 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
                        cpu, QEMU_THREAD_JOINABLE);
 }
 
-const CpusAccel kvm_cpus = {
-    .create_vcpu_thread = kvm_start_vcpu_thread,
+static void kvm_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
 
-    .synchronize_post_reset = kvm_cpu_synchronize_post_reset,
-    .synchronize_post_init = kvm_cpu_synchronize_post_init,
-    .synchronize_state = kvm_cpu_synchronize_state,
-    .synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm,
+    ops->create_vcpu_thread = kvm_start_vcpu_thread;
+    ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
+    ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
+    ops->synchronize_state = kvm_cpu_synchronize_state;
+    ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
 };
+static const TypeInfo kvm_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("kvm"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = kvm_cpus_class_init,
+    .abstract = true,
+};
+static void kvm_cpus_register_types(void)
+{
+    type_register_static(&kvm_cpus_type_info);
+}
+type_init(kvm_cpus_register_types);
diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h
index 3df732b816..bf0bd1bee4 100644
--- a/accel/kvm/kvm-cpus.h
+++ b/accel/kvm/kvm-cpus.h
@@ -12,8 +12,6 @@
 
 #include "sysemu/cpus.h"
 
-extern const CpusAccel kvm_cpus;
-
 int kvm_init_vcpu(CPUState *cpu, Error **errp);
 int kvm_cpu_exec(CPUState *cpu);
 void kvm_destroy_vcpu(CPUState *cpu);
diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
index 482f89729f..8bf51689bc 100644
--- a/accel/qtest/qtest.c
+++ b/accel/qtest/qtest.c
@@ -25,11 +25,6 @@
 #include "qemu/main-loop.h"
 #include "hw/core/cpu.h"
 
-const CpusAccel qtest_cpus = {
-    .create_vcpu_thread = dummy_start_vcpu_thread,
-    .get_virtual_clock = qtest_get_virtual_clock,
-};
-
 static int qtest_init_accel(MachineState *ms)
 {
     return 0;
@@ -51,18 +46,26 @@ static const TypeInfo qtest_accel_type = {
     .class_init = qtest_accel_class_init,
 };
 
+static void qtest_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
+
+    ops->create_vcpu_thread = dummy_start_vcpu_thread;
+    ops->get_virtual_clock = qtest_get_virtual_clock;
+};
+
+static const TypeInfo qtest_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("qtest"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = qtest_cpus_class_init,
+    .abstract = true,
+};
+
 static void qtest_type_init(void)
 {
     type_register_static(&qtest_accel_type);
+    type_register_static(&qtest_cpus_type_info);
 }
 
 type_init(qtest_type_init);
-
-static void qtest_accel_cpu_init(void)
-{
-    if (qtest_enabled()) {
-        cpus_register_accel(&qtest_cpus);
-    }
-}
-
-accel_cpu_init(qtest_accel_cpu_init);
diff --git a/accel/tcg/tcg-cpus-icount.c b/accel/tcg/tcg-cpus-icount.c
index 9f45432275..5445b4d545 100644
--- a/accel/tcg/tcg-cpus-icount.c
+++ b/accel/tcg/tcg-cpus-icount.c
@@ -125,7 +125,7 @@ void icount_process_data(CPUState *cpu)
     replay_mutex_unlock();
 }
 
-static void icount_handle_interrupt(CPUState *cpu, int mask)
+void icount_handle_interrupt(CPUState *cpu, int mask)
 {
     int old_mask = cpu->interrupt_request;
 
@@ -136,12 +136,3 @@ static void icount_handle_interrupt(CPUState *cpu, int mask)
         cpu_abort(cpu, "Raised interrupt while not in I/O function");
     }
 }
-
-const CpusAccel tcg_cpus_icount = {
-    .create_vcpu_thread = rr_start_vcpu_thread,
-    .kick_vcpu_thread = rr_kick_vcpu_thread,
-
-    .handle_interrupt = icount_handle_interrupt,
-    .get_virtual_clock = icount_get,
-    .get_elapsed_ticks = icount_get,
-};
diff --git a/accel/tcg/tcg-cpus-icount.h b/accel/tcg/tcg-cpus-icount.h
index b695939dfa..d884aa2aaa 100644
--- a/accel/tcg/tcg-cpus-icount.h
+++ b/accel/tcg/tcg-cpus-icount.h
@@ -14,4 +14,6 @@ void icount_handle_deadline(void);
 void icount_prepare_for_run(CPUState *cpu);
 void icount_process_data(CPUState *cpu);
 
+void icount_handle_interrupt(CPUState *cpu, int mask);
+
 #endif /* TCG_CPUS_ICOUNT_H */
diff --git a/accel/tcg/tcg-cpus-mttcg.c b/accel/tcg/tcg-cpus-mttcg.c
index 9c3767d260..dabf5ed42e 100644
--- a/accel/tcg/tcg-cpus-mttcg.c
+++ b/accel/tcg/tcg-cpus-mttcg.c
@@ -33,6 +33,7 @@
 #include "hw/boards.h"
 
 #include "tcg-cpus.h"
+#include "tcg-cpus-mttcg.h"
 
 /*
  * In the multi-threaded case each vCPU has its own thread. The TLS
@@ -103,12 +104,12 @@ static void *mttcg_cpu_thread_fn(void *arg)
     return NULL;
 }
 
-static void mttcg_kick_vcpu_thread(CPUState *cpu)
+void mttcg_kick_vcpu_thread(CPUState *cpu)
 {
     cpu_exit(cpu);
 }
 
-static void mttcg_start_vcpu_thread(CPUState *cpu)
+void mttcg_start_vcpu_thread(CPUState *cpu)
 {
     char thread_name[VCPU_THREAD_NAME_SIZE];
 
@@ -131,10 +132,3 @@ static void mttcg_start_vcpu_thread(CPUState *cpu)
     cpu->hThread = qemu_thread_get_handle(cpu->thread);
 #endif
 }
-
-const CpusAccel tcg_cpus_mttcg = {
-    .create_vcpu_thread = mttcg_start_vcpu_thread,
-    .kick_vcpu_thread = mttcg_kick_vcpu_thread,
-
-    .handle_interrupt = tcg_cpus_handle_interrupt,
-};
diff --git a/accel/tcg/tcg-cpus-mttcg.h b/accel/tcg/tcg-cpus-mttcg.h
new file mode 100644
index 0000000000..0af91dd3b3
--- /dev/null
+++ b/accel/tcg/tcg-cpus-mttcg.h
@@ -0,0 +1,19 @@
+/*
+ * QEMU TCG Multi Threaded vCPUs implementation
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TCG_CPUS_MTTCG_H
+#define TCG_CPUS_MTTCG_H
+
+/* kick MTTCG vCPU thread */
+void mttcg_kick_vcpu_thread(CPUState *cpu);
+
+/* start an mttcg vCPU thread */
+void mttcg_start_vcpu_thread(CPUState *cpu);
+
+#endif /* TCG_CPUS_MTTCG_H */
diff --git a/accel/tcg/tcg-cpus-rr.c b/accel/tcg/tcg-cpus-rr.c
index 0181d2e4eb..802c57bb60 100644
--- a/accel/tcg/tcg-cpus-rr.c
+++ b/accel/tcg/tcg-cpus-rr.c
@@ -296,10 +296,3 @@ void rr_start_vcpu_thread(CPUState *cpu)
         cpu->created = true;
     }
 }
-
-const CpusAccel tcg_cpus_rr = {
-    .create_vcpu_thread = rr_start_vcpu_thread,
-    .kick_vcpu_thread = rr_kick_vcpu_thread,
-
-    .handle_interrupt = tcg_cpus_handle_interrupt,
-};
diff --git a/accel/tcg/tcg-cpus.c b/accel/tcg/tcg-cpus.c
index c9e662f06e..4f3a50af2e 100644
--- a/accel/tcg/tcg-cpus.c
+++ b/accel/tcg/tcg-cpus.c
@@ -35,6 +35,9 @@
 #include "hw/boards.h"
 
 #include "tcg-cpus.h"
+#include "tcg-cpus-mttcg.h"
+#include "tcg-cpus-rr.h"
+#include "tcg-cpus-icount.h"
 
 /* common functionality among all TCG variants */
 
@@ -81,17 +84,42 @@ void tcg_cpus_handle_interrupt(CPUState *cpu, int mask)
     }
 }
 
-static void tcg_accel_cpu_init(void)
+static void tcg_cpus_accel_chosen_init(CpusAccelOps *ops)
 {
-    if (tcg_enabled()) {
-        if (qemu_tcg_mttcg_enabled()) {
-            cpus_register_accel(&tcg_cpus_mttcg);
-        } else if (icount_enabled()) {
-            cpus_register_accel(&tcg_cpus_icount);
-        } else {
-            cpus_register_accel(&tcg_cpus_rr);
-        }
+    if (qemu_tcg_mttcg_enabled()) {
+        ops->create_vcpu_thread = mttcg_start_vcpu_thread;
+        ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
+        ops->handle_interrupt = tcg_cpus_handle_interrupt;
+
+    } else if (icount_enabled()) {
+        ops->create_vcpu_thread = rr_start_vcpu_thread;
+        ops->kick_vcpu_thread = rr_kick_vcpu_thread;
+        ops->handle_interrupt = icount_handle_interrupt;
+        ops->get_virtual_clock = icount_get;
+        ops->get_elapsed_ticks = icount_get;
+
+    } else {
+        ops->create_vcpu_thread = rr_start_vcpu_thread;
+        ops->kick_vcpu_thread = rr_kick_vcpu_thread;
+        ops->handle_interrupt = tcg_cpus_handle_interrupt;
     }
 }
 
-accel_cpu_init(tcg_accel_cpu_init);
+static void tcg_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
+
+    ops->accel_chosen_init = tcg_cpus_accel_chosen_init;
+};
+static const TypeInfo tcg_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("tcg"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = tcg_cpus_class_init,
+    .abstract = true,
+};
+static void tcg_cpus_register_types(void)
+{
+    type_register_static(&tcg_cpus_type_info);
+}
+type_init(tcg_cpus_register_types);
diff --git a/accel/tcg/tcg-cpus.h b/accel/tcg/tcg-cpus.h
index d6893a32f8..923cbace12 100644
--- a/accel/tcg/tcg-cpus.h
+++ b/accel/tcg/tcg-cpus.h
@@ -14,10 +14,6 @@
 
 #include "sysemu/cpus.h"
 
-extern const CpusAccel tcg_cpus_mttcg;
-extern const CpusAccel tcg_cpus_icount;
-extern const CpusAccel tcg_cpus_rr;
-
 void tcg_cpus_destroy(CPUState *cpu);
 int tcg_cpus_exec(CPUState *cpu);
 void tcg_cpus_handle_interrupt(CPUState *cpu, int mask);
diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index be09b6ec22..976c7806d0 100644
--- a/accel/xen/xen-all.c
+++ b/accel/xen/xen-all.c
@@ -154,10 +154,6 @@ static void xen_setup_post(MachineState *ms, AccelState *accel)
     }
 }
 
-const CpusAccel xen_cpus = {
-    .create_vcpu_thread = dummy_start_vcpu_thread,
-};
-
 static int xen_init(MachineState *ms)
 {
     MachineClass *mc = MACHINE_GET_CLASS(ms);
@@ -219,18 +215,23 @@ static const TypeInfo xen_accel_type = {
     .class_init = xen_accel_class_init,
 };
 
+static void xen_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
+
+    ops->create_vcpu_thread = dummy_start_vcpu_thread;
+};
+static const TypeInfo xen_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("xen"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = xen_cpus_class_init,
+    .abstract = true,
+};
+
 static void xen_type_init(void)
 {
     type_register_static(&xen_accel_type);
+    type_register_static(&xen_cpus_type_info);
 }
-
 type_init(xen_type_init);
-
-static void xen_accel_cpu_init(void)
-{
-    if (xen_enabled()) {
-        cpus_register_accel(&xen_cpus);
-    }
-}
-
-accel_cpu_init(xen_accel_cpu_init);
diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
index e8156728c6..9b0c5eadf3 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -1,14 +1,39 @@
+/*
+ * CPUS module (softmmu/cpus.c) Accelerator Ops
+ *
+ * Copyright 2020 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
 #ifndef QEMU_CPUS_H
 #define QEMU_CPUS_H
 
 #include "qemu/timer.h"
+#include "qom/object.h"
+
+/* accel/dummy-cpus.c */
+
+/* Create a dummy vcpu for CpusAccelOps->create_vcpu_thread */
+void dummy_start_vcpu_thread(CPUState *);
 
 /* cpus.c */
 
-/* CPU execution threads */
+#define TYPE_CPUS_ACCEL_OPS "accel-ops"
+#define CPUS_ACCEL_TYPE_NAME(name) (name "-" TYPE_CPUS_ACCEL_OPS)
 
-typedef struct CpusAccel {
-    void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */
+typedef struct CpusAccelOps CpusAccelOps;
+DECLARE_CLASS_CHECKERS(CpusAccelOps, CPUS_ACCEL_OPS, TYPE_CPUS_ACCEL_OPS)
+
+struct CpusAccelOps {
+    ObjectClass parent_class;
+
+    /* initialization function called when accel is chosen */
+    void (*accel_chosen_init)(CpusAccelOps *ops);
+
+    void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */
     void (*kick_vcpu_thread)(CPUState *cpu);
 
     void (*synchronize_post_reset)(CPUState *cpu);
@@ -20,13 +45,7 @@ typedef struct CpusAccel {
 
     int64_t (*get_virtual_clock)(void);
     int64_t (*get_elapsed_ticks)(void);
-} CpusAccel;
-
-/* register accel-specific cpus interface implementation */
-void cpus_register_accel(const CpusAccel *i);
-
-/* Create a dummy vcpu for CpusAccel->create_vcpu_thread */
-void dummy_start_vcpu_thread(CPUState *);
+};
 
 /* interface available for cpus accelerator threads */
 
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index e46ac68ad0..2d2386900a 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -127,7 +127,7 @@ void hw_error(const char *fmt, ...)
 /*
  * The chosen accelerator is supposed to register this.
  */
-static const CpusAccel *cpus_accel;
+static CpusAccelOps *cpus_accel;
 
 void cpu_synchronize_all_states(void)
 {
@@ -593,13 +593,6 @@ void cpu_remove_sync(CPUState *cpu)
     qemu_mutex_lock_iothread();
 }
 
-void cpus_register_accel(const CpusAccel *ca)
-{
-    assert(ca != NULL);
-    assert(ca->create_vcpu_thread != NULL); /* mandatory */
-    cpus_accel = ca;
-}
-
 void qemu_init_vcpu(CPUState *cpu)
 {
     MachineState *ms = MACHINE(qdev_get_machine());
@@ -617,7 +610,7 @@ void qemu_init_vcpu(CPUState *cpu)
         cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory);
     }
 
-    /* accelerators all implement the CpusAccel interface */
+    /* accelerators all implement the CpusAccelOps */
     g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL);
     cpus_accel->create_vcpu_thread(cpu);
 
@@ -797,3 +790,43 @@ void qmp_inject_nmi(Error **errp)
     nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp);
 }
 
+static const TypeInfo cpus_accel_type_info = {
+    .name = TYPE_CPUS_ACCEL_OPS,
+    .parent = TYPE_OBJECT,
+    .abstract = true,
+    .class_size = sizeof(CpusAccelOps),
+};
+static void cpus_register_types(void)
+{
+    type_register_static(&cpus_accel_type_info);
+}
+type_init(cpus_register_types);
+
+static void cpus_accel_ops_init(void)
+{
+    const char *ac_name;
+    ObjectClass *ac;
+    char *ops_name;
+    ObjectClass *ops;
+
+    ac = object_get_class(OBJECT(current_accel()));
+    g_assert(ac != NULL);
+    ac_name = object_class_get_name(ac);
+    g_assert(ac_name != NULL);
+
+    ops_name = g_strdup_printf("%s-ops", ac_name);
+    ops = object_class_by_name(ops_name);
+    g_free(ops_name);
+
+    /*
+     * all accelerators need to define ops, providing at least a mandatory
+     * non-NULL create_vcpu_thread operation.
+     */
+    g_assert(ops != NULL);
+    cpus_accel = CPUS_ACCEL_OPS_CLASS(ops);
+    if (cpus_accel->accel_chosen_init) {
+        cpus_accel->accel_chosen_init(cpus_accel);
+    }
+}
+
+accel_cpu_init(cpus_accel_ops_init);
diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
index 77c365311c..ec3c426223 100644
--- a/target/i386/hax/hax-all.c
+++ b/target/i386/hax/hax-all.c
@@ -1138,12 +1138,3 @@ static void hax_type_init(void)
 }
 
 type_init(hax_type_init);
-
-static void hax_accel_cpu_init(void)
-{
-    if (hax_enabled()) {
-        cpus_register_accel(&hax_cpus);
-    }
-}
-
-accel_cpu_init(hax_accel_cpu_init);
diff --git a/target/i386/hax/hax-cpus.c b/target/i386/hax/hax-cpus.c
index f72c85bd49..171b5ac1e6 100644
--- a/target/i386/hax/hax-cpus.c
+++ b/target/i386/hax/hax-cpus.c
@@ -74,12 +74,27 @@ static void hax_start_vcpu_thread(CPUState *cpu)
 #endif
 }
 
-const CpusAccel hax_cpus = {
-    .create_vcpu_thread = hax_start_vcpu_thread,
-    .kick_vcpu_thread = hax_kick_vcpu_thread,
+static void hax_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
 
-    .synchronize_post_reset = hax_cpu_synchronize_post_reset,
-    .synchronize_post_init = hax_cpu_synchronize_post_init,
-    .synchronize_state = hax_cpu_synchronize_state,
-    .synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm,
+    ops->create_vcpu_thread = hax_start_vcpu_thread;
+    ops->kick_vcpu_thread = hax_kick_vcpu_thread;
+
+    ops->synchronize_post_reset = hax_cpu_synchronize_post_reset;
+    ops->synchronize_post_init = hax_cpu_synchronize_post_init;
+    ops->synchronize_state = hax_cpu_synchronize_state;
+    ops->synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm;
+};
+static const TypeInfo hax_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("hax"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = hax_cpus_class_init,
+    .abstract = true,
 };
+static void hax_cpus_register_types(void)
+{
+    type_register_static(&hax_cpus_type_info);
+}
+type_init(hax_cpus_register_types);
diff --git a/target/i386/hax/hax-cpus.h b/target/i386/hax/hax-cpus.h
index ee8ab7a631..c7698519cd 100644
--- a/target/i386/hax/hax-cpus.h
+++ b/target/i386/hax/hax-cpus.h
@@ -12,8 +12,6 @@
 
 #include "sysemu/cpus.h"
 
-extern const CpusAccel hax_cpus;
-
 #include "hax-interface.h"
 #include "hax-i386.h"
 
diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-cpus.c
index 817b3d7452..124662de58 100644
--- a/target/i386/hvf/hvf-cpus.c
+++ b/target/i386/hvf/hvf-cpus.c
@@ -121,11 +121,26 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
                        cpu, QEMU_THREAD_JOINABLE);
 }
 
-const CpusAccel hvf_cpus = {
-    .create_vcpu_thread = hvf_start_vcpu_thread,
+static void hvf_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
 
-    .synchronize_post_reset = hvf_cpu_synchronize_post_reset,
-    .synchronize_post_init = hvf_cpu_synchronize_post_init,
-    .synchronize_state = hvf_cpu_synchronize_state,
-    .synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm,
+    ops->create_vcpu_thread = hvf_start_vcpu_thread;
+
+    ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
+    ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
+    ops->synchronize_state = hvf_cpu_synchronize_state;
+    ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
+};
+static const TypeInfo hvf_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("hvf"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = hvf_cpus_class_init,
+    .abstract = true,
 };
+static void hvf_cpus_register_types(void)
+{
+    type_register_static(&hvf_cpus_type_info);
+}
+type_init(hvf_cpus_register_types);
diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.h
index ced31b82c0..8f992da168 100644
--- a/target/i386/hvf/hvf-cpus.h
+++ b/target/i386/hvf/hvf-cpus.h
@@ -12,8 +12,6 @@
 
 #include "sysemu/cpus.h"
 
-extern const CpusAccel hvf_cpus;
-
 int hvf_init_vcpu(CPUState *);
 int hvf_vcpu_exec(CPUState *);
 void hvf_cpu_synchronize_state(CPUState *);
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 58794c35ae..bd94bb5243 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -910,12 +910,3 @@ static void hvf_type_init(void)
 }
 
 type_init(hvf_type_init);
-
-static void hvf_accel_cpu_init(void)
-{
-    if (hvf_enabled()) {
-        cpus_register_accel(&hvf_cpus);
-    }
-}
-
-accel_cpu_init(hvf_accel_cpu_init);
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 097d6f5e60..90adae9af7 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1711,12 +1711,3 @@ error:
 }
 
 type_init(whpx_type_init);
-
-static void whpx_accel_cpu_init(void)
-{
-    if (whpx_enabled()) {
-        cpus_register_accel(&whpx_cpus);
-    }
-}
-
-accel_cpu_init(whpx_accel_cpu_init);
diff --git a/target/i386/whpx/whpx-cpus.c b/target/i386/whpx/whpx-cpus.c
index d9bd5a2d36..1e736a50b0 100644
--- a/target/i386/whpx/whpx-cpus.c
+++ b/target/i386/whpx/whpx-cpus.c
@@ -85,12 +85,27 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
     }
 }
 
-const CpusAccel whpx_cpus = {
-    .create_vcpu_thread = whpx_start_vcpu_thread,
-    .kick_vcpu_thread = whpx_kick_vcpu_thread,
+static void whpx_cpus_class_init(ObjectClass *oc, void *data)
+{
+    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
 
-    .synchronize_post_reset = whpx_cpu_synchronize_post_reset,
-    .synchronize_post_init = whpx_cpu_synchronize_post_init,
-    .synchronize_state = whpx_cpu_synchronize_state,
-    .synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm,
+    ops->create_vcpu_thread = whpx_start_vcpu_thread;
+    ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
+
+    ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
+    ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
+    ops->synchronize_state = whpx_cpu_synchronize_state;
+    ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm;
+};
+static const TypeInfo whpx_cpus_type_info = {
+    .name = CPUS_ACCEL_TYPE_NAME("whpx"),
+
+    .parent = TYPE_CPUS_ACCEL_OPS,
+    .class_init = whpx_cpus_class_init,
+    .abstract = true,
 };
+static void whpx_cpus_register_types(void)
+{
+    type_register_static(&whpx_cpus_type_info);
+}
+type_init(whpx_cpus_register_types);
diff --git a/target/i386/whpx/whpx-cpus.h b/target/i386/whpx/whpx-cpus.h
index bdb367d1d0..2dee6d61ea 100644
--- a/target/i386/whpx/whpx-cpus.h
+++ b/target/i386/whpx/whpx-cpus.h
@@ -12,8 +12,6 @@
 
 #include "sysemu/cpus.h"
 
-extern const CpusAccel whpx_cpus;
-
 int whpx_init_vcpu(CPUState *cpu);
 int whpx_vcpu_exec(CPUState *cpu);
 void whpx_destroy_vcpu(CPUState *cpu);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 16:22 ` [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces Claudio Fontana
@ 2020-11-24 16:59   ` Eduardo Habkost
  2020-11-24 18:38     ` Claudio Fontana
  2020-11-24 20:13   ` Paolo Bonzini
  1 sibling, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 16:59 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 05:22:09PM +0100, Claudio Fontana wrote:
> Signed-off-by: Claudio Fontana <cfontana@suse.de>

Probably this can be squashed into patch 10/12.

> ---
>  target/i386/cpu-qom.h |  2 --
>  target/i386/cpu.c     | 27 ++++++++++++++++++++-------
>  target/i386/hvf/cpu.c |  9 ---------
>  target/i386/kvm/cpu.c |  8 --------
>  target/i386/tcg/cpu.c |  9 ---------
>  5 files changed, 20 insertions(+), 35 deletions(-)
> 
> diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
> index 9316e78e71..2cea5394c6 100644
> --- a/target/i386/cpu-qom.h
> +++ b/target/i386/cpu-qom.h
> @@ -98,6 +98,4 @@ struct X86CPUAccelClass {
>      void (*cpu_realizefn)(X86CPU *cpu, Error **errp);
>  };
>  
> -void x86_cpu_accel_init(const char *accel_name);
> -
>  #endif
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index b799723e53..f6fd055046 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -7066,18 +7066,31 @@ type_init(x86_cpu_register_types)
>  static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
>  {
>      X86CPUClass *xcc = X86_CPU_CLASS(klass);
> -    const X86CPUAccelClass **accel = opaque;
> +    X86CPUAccelClass *accel = opaque;
>  
> -    xcc->accel = *accel;
> +    xcc->accel = accel;
>      xcc->accel->cpu_common_class_init(xcc);
>  }
>  
> -void x86_cpu_accel_init(const char *accel_name)
> +static void x86_cpu_accel_init(void)
>  {
> -    X86CPUAccelClass *acc;
> +    const char *ac_name;
> +    ObjectClass *ac;
> +    char *xac_name;
> +    ObjectClass *xac;
>  
> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> -    g_assert(acc != NULL);
> +    ac = object_get_class(OBJECT(current_accel()));
> +    g_assert(ac != NULL);
> +    ac_name = object_class_get_name(ac);
> +    g_assert(ac_name != NULL);
>  
> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> +    xac = object_class_by_name(xac_name);
> +    g_free(xac_name);
> +
> +    if (xac) {
> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> +    }
>  }
> +
> +accel_cpu_init(x86_cpu_accel_init);

This keeps the hidden initialization ordering dependency between
MODULE_INIT_ACCEL_CPU and current_accel().  I thought we were
going to get rid of module init functions that depend on runtime
state.

This is an improvement to the code in patch 10/12, though.  If
others believe it is an acceptable (temporary) solution, I won't
block it.

I would still prefer to have a
  void arch_accel_cpu_init(AccelState*)
function which would call a
  void x86_cpu_accel_init(AccelState*)
function.  That would make the dependency between
x86_cpu_accel_init() and accelerator creation explicit.


> diff --git a/target/i386/hvf/cpu.c b/target/i386/hvf/cpu.c
> index 7e7dc044d3..70b6dbfc10 100644
> --- a/target/i386/hvf/cpu.c
> +++ b/target/i386/hvf/cpu.c
> @@ -65,12 +65,3 @@ static void hvf_cpu_accel_register_types(void)
>      type_register_static(&hvf_cpu_accel_type_info);
>  }
>  type_init(hvf_cpu_accel_register_types);
> -
> -static void hvf_cpu_accel_init(void)
> -{
> -    if (hvf_enabled()) {
> -        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("hvf"));
> -    }
> -}
> -
> -accel_cpu_init(hvf_cpu_accel_init);
> diff --git a/target/i386/kvm/cpu.c b/target/i386/kvm/cpu.c
> index bc5f519479..c17ed5a3f2 100644
> --- a/target/i386/kvm/cpu.c
> +++ b/target/i386/kvm/cpu.c
> @@ -147,11 +147,3 @@ static void kvm_cpu_accel_register_types(void)
>      type_register_static(&kvm_cpu_accel_type_info);
>  }
>  type_init(kvm_cpu_accel_register_types);
> -
> -static void kvm_cpu_accel_init(void)
> -{
> -    if (kvm_enabled()) {
> -        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("kvm"));
> -    }
> -}
> -accel_cpu_init(kvm_cpu_accel_init);
> diff --git a/target/i386/tcg/cpu.c b/target/i386/tcg/cpu.c
> index e7d4effdd0..00166c36e9 100644
> --- a/target/i386/tcg/cpu.c
> +++ b/target/i386/tcg/cpu.c
> @@ -170,12 +170,3 @@ static void tcg_cpu_accel_register_types(void)
>      type_register_static(&tcg_cpu_accel_type_info);
>  }
>  type_init(tcg_cpu_accel_register_types);
> -
> -static void tcg_cpu_accel_init(void)
> -{
> -    if (tcg_enabled()) {
> -        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("tcg"));
> -    }
> -}
> -
> -accel_cpu_init(tcg_cpu_accel_init);
> -- 
> 2.26.2
> 

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 16:22 ` [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
@ 2020-11-24 17:08   ` Eduardo Habkost
  2020-11-24 18:29     ` Claudio Fontana
  2020-11-26 11:25   ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 17:08 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 05:22:07PM +0100, Claudio Fontana wrote:
> apply this to the registration of the cpus accel interfaces,
> 
> but this will be also in preparation for later use of this
> new module init step to also register per-accel x86 cpu type
> interfaces.
> 
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
[...]
> diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
> index b4e731cb2b..482f89729f 100644
> --- a/accel/qtest/qtest.c
> +++ b/accel/qtest/qtest.c
> @@ -32,7 +32,6 @@ const CpusAccel qtest_cpus = {
>  
>  static int qtest_init_accel(MachineState *ms)
>  {
> -    cpus_register_accel(&qtest_cpus);
>      return 0;
>  }
>  
> @@ -58,3 +57,12 @@ static void qtest_type_init(void)
>  }
>  
>  type_init(qtest_type_init);
> +
> +static void qtest_accel_cpu_init(void)
> +{
> +    if (qtest_enabled()) {
> +        cpus_register_accel(&qtest_cpus);
> +    }
> +}
> +
> +accel_cpu_init(qtest_accel_cpu_init);

I don't understand why this (and the similar changes on other
accelerators) is an improvement.

You are replacing a trivial AccelClass-specific init method with
a module_init() function that has a hidden dependency on runtime
state.

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 16:22 ` [RFC v5 12/12] accel: centralize initialization of CpusAccelOps Claudio Fontana
@ 2020-11-24 17:48   ` Eduardo Habkost
  2020-11-24 18:52     ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 17:48 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 05:22:10PM +0100, Claudio Fontana wrote:
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
>  accel/kvm/kvm-all.c          |  9 -------
>  accel/kvm/kvm-cpus.c         | 26 +++++++++++++-----
>  accel/kvm/kvm-cpus.h         |  2 --
>  accel/qtest/qtest.c          | 31 ++++++++++++----------
>  accel/tcg/tcg-cpus-icount.c  | 11 +-------
>  accel/tcg/tcg-cpus-icount.h  |  2 ++
>  accel/tcg/tcg-cpus-mttcg.c   | 12 +++------
>  accel/tcg/tcg-cpus-mttcg.h   | 19 ++++++++++++++
>  accel/tcg/tcg-cpus-rr.c      |  7 -----
>  accel/tcg/tcg-cpus.c         | 48 ++++++++++++++++++++++++++-------
>  accel/tcg/tcg-cpus.h         |  4 ---
>  accel/xen/xen-all.c          | 29 ++++++++++----------
>  include/sysemu/cpus.h        | 39 ++++++++++++++++++++-------
>  softmmu/cpus.c               | 51 +++++++++++++++++++++++++++++-------
>  target/i386/hax/hax-all.c    |  9 -------
>  target/i386/hax/hax-cpus.c   | 29 +++++++++++++++-----
>  target/i386/hax/hax-cpus.h   |  2 --
>  target/i386/hvf/hvf-cpus.c   | 27 ++++++++++++++-----
>  target/i386/hvf/hvf-cpus.h   |  2 --
>  target/i386/hvf/hvf.c        |  9 -------
>  target/i386/whpx/whpx-all.c  |  9 -------
>  target/i386/whpx/whpx-cpus.c | 29 +++++++++++++++-----
>  target/i386/whpx/whpx-cpus.h |  2 --
>  23 files changed, 251 insertions(+), 157 deletions(-)
>  create mode 100644 accel/tcg/tcg-cpus-mttcg.h
> 
> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
> index 509b249f52..33156cc4c7 100644
> --- a/accel/kvm/kvm-all.c
> +++ b/accel/kvm/kvm-all.c
> @@ -3234,12 +3234,3 @@ static void kvm_type_init(void)
>  }
>  
>  type_init(kvm_type_init);
> -
> -static void kvm_accel_cpu_init(void)
> -{
> -    if (kvm_enabled()) {
> -        cpus_register_accel(&kvm_cpus);
> -    }
> -}
> -
> -accel_cpu_init(kvm_accel_cpu_init);
> diff --git a/accel/kvm/kvm-cpus.c b/accel/kvm/kvm-cpus.c
> index d809b1e74c..33dc8e737a 100644
> --- a/accel/kvm/kvm-cpus.c
> +++ b/accel/kvm/kvm-cpus.c
> @@ -74,11 +74,25 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
>                         cpu, QEMU_THREAD_JOINABLE);
>  }
>  
> -const CpusAccel kvm_cpus = {
> -    .create_vcpu_thread = kvm_start_vcpu_thread,
> +static void kvm_cpus_class_init(ObjectClass *oc, void *data)
> +{
> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);

Why do you need a separate QOM type hierarchy instead of just
doing this inside AccelClass methods and/or existing accel
class_init functions?

>  
> -    .synchronize_post_reset = kvm_cpu_synchronize_post_reset,
> -    .synchronize_post_init = kvm_cpu_synchronize_post_init,
> -    .synchronize_state = kvm_cpu_synchronize_state,
> -    .synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm,
> +    ops->create_vcpu_thread = kvm_start_vcpu_thread;
> +    ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
> +    ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
> +    ops->synchronize_state = kvm_cpu_synchronize_state;
> +    ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;

All of these could be AccelClass fields.

TCG makes it a bit more complicated because there's a different
set of methods chosen for TYPE_TCG_ACCEL depending on the
configuration.  This could be solved by patching AccelClass at
init time, or by moving the method pointers to AccelState.

Alternatively, if you still want to keep the
CpusAccel/CpusAccelOps struct, that's OK.  You can just add a
`CpusAccel *cpu_accel_ops` field to AccelClass or AccelState.  No
need for a separate QOM hierarchy, either.

If you _really_ want a separate TYPE_CPU_ACCEL_OPS QOM type, you
can still have it.  But it can be just an interface implemented
by each accel subclass, instead of requiring a separate
CPUS_ACCEL_TYPE_NAME(...) type to be registered for each
accelerator.  (I don't see why you would want it, though.)


>  };
> +static const TypeInfo kvm_cpus_type_info = {
> +    .name = CPUS_ACCEL_TYPE_NAME("kvm"),
> +
> +    .parent = TYPE_CPUS_ACCEL_OPS,
> +    .class_init = kvm_cpus_class_init,
> +    .abstract = true,
> +};
> +static void kvm_cpus_register_types(void)
> +{
> +    type_register_static(&kvm_cpus_type_info);
> +}
> +type_init(kvm_cpus_register_types);
[...]
> -typedef struct CpusAccel {
> -    void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */
> +typedef struct CpusAccelOps CpusAccelOps;
> +DECLARE_CLASS_CHECKERS(CpusAccelOps, CPUS_ACCEL_OPS, TYPE_CPUS_ACCEL_OPS)
> +
> +struct CpusAccelOps {
> +    ObjectClass parent_class;
> +
> +    /* initialization function called when accel is chosen */
> +    void (*accel_chosen_init)(CpusAccelOps *ops);

This can be an AccelClass method too.  What about just naming it
AccelClass.init?

> +
> +    void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */
>      void (*kick_vcpu_thread)(CPUState *cpu);
>  
>      void (*synchronize_post_reset)(CPUState *cpu);
> @@ -20,13 +45,7 @@ typedef struct CpusAccel {
>  
>      int64_t (*get_virtual_clock)(void);
>      int64_t (*get_elapsed_ticks)(void);
> -} CpusAccel;
> -
[...]
> +
> +static void cpus_accel_ops_init(void)
> +{

If we move the fields above part of AccelClass, this could be
called accel_init().

> +    const char *ac_name;
> +    ObjectClass *ac;
> +    char *ops_name;
> +    ObjectClass *ops;
> +
> +    ac = object_get_class(OBJECT(current_accel()));
> +    g_assert(ac != NULL);

If you call this function directly from accel_init_machine(),
bsd-user:main(), and linux-user:main(), you can get AccelState*
as argument, and the dependency on current_accel() becomes
explicit instead of implicit.

> +    ac_name = object_class_get_name(ac);
> +    g_assert(ac_name != NULL);
> +
> +    ops_name = g_strdup_printf("%s-ops", ac_name);
> +    ops = object_class_by_name(ops_name);
> +    g_free(ops_name);

If we make the fields above part of AccelClass, you don't need
this lookup trick.

> +
> +    /*
> +     * all accelerators need to define ops, providing at least a mandatory
> +     * non-NULL create_vcpu_thread operation.
> +     */
> +    g_assert(ops != NULL);
> +    cpus_accel = CPUS_ACCEL_OPS_CLASS(ops);
> +    if (cpus_accel->accel_chosen_init) {
> +        cpus_accel->accel_chosen_init(cpus_accel);

If we move CpusAccelOps.accel_chosen_init to AccelClass.init,
this would be just:

  AccelClass *acc = ACCEL_GET_CLASS(accel);
  if (acc->init) {
      acc->init(acc);
  }

> +    }

Additionally, if you call arch_cpu_accel_init() here, you won't
need MODULE_INIT_ACCEL_CPU anymore.  The

  module_call_init(MODULE_INIT_ACCEL_CPU)

call with implicit dependencies on runtime state inside vl.c and
*-user/main.c becomes a trivial:

  accel_init(accel)

call in accel_init_machine() and *-user:main().

> +}
> +
> +accel_cpu_init(cpus_accel_ops_init);
> diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
> index 77c365311c..ec3c426223 100644
> --- a/target/i386/hax/hax-all.c
> +++ b/target/i386/hax/hax-all.c
> @@ -1138,12 +1138,3 @@ static void hax_type_init(void)
>  }
>  
>  type_init(hax_type_init);
> -
> -static void hax_accel_cpu_init(void)
> -{
> -    if (hax_enabled()) {
> -        cpus_register_accel(&hax_cpus);
> -    }
> -}
> -
> -accel_cpu_init(hax_accel_cpu_init);
> diff --git a/target/i386/hax/hax-cpus.c b/target/i386/hax/hax-cpus.c
> index f72c85bd49..171b5ac1e6 100644
> --- a/target/i386/hax/hax-cpus.c
> +++ b/target/i386/hax/hax-cpus.c
> @@ -74,12 +74,27 @@ static void hax_start_vcpu_thread(CPUState *cpu)
>  #endif
>  }
>  
> -const CpusAccel hax_cpus = {
> -    .create_vcpu_thread = hax_start_vcpu_thread,
> -    .kick_vcpu_thread = hax_kick_vcpu_thread,
> +static void hax_cpus_class_init(ObjectClass *oc, void *data)
> +{
> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
>  
> -    .synchronize_post_reset = hax_cpu_synchronize_post_reset,
> -    .synchronize_post_init = hax_cpu_synchronize_post_init,
> -    .synchronize_state = hax_cpu_synchronize_state,
> -    .synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm,
> +    ops->create_vcpu_thread = hax_start_vcpu_thread;
> +    ops->kick_vcpu_thread = hax_kick_vcpu_thread;
> +
> +    ops->synchronize_post_reset = hax_cpu_synchronize_post_reset;
> +    ops->synchronize_post_init = hax_cpu_synchronize_post_init;
> +    ops->synchronize_state = hax_cpu_synchronize_state;
> +    ops->synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm;
> +};
> +static const TypeInfo hax_cpus_type_info = {
> +    .name = CPUS_ACCEL_TYPE_NAME("hax"),
> +
> +    .parent = TYPE_CPUS_ACCEL_OPS,
> +    .class_init = hax_cpus_class_init,
> +    .abstract = true,
>  };
> +static void hax_cpus_register_types(void)
> +{
> +    type_register_static(&hax_cpus_type_info);
> +}
> +type_init(hax_cpus_register_types);
> diff --git a/target/i386/hax/hax-cpus.h b/target/i386/hax/hax-cpus.h
> index ee8ab7a631..c7698519cd 100644
> --- a/target/i386/hax/hax-cpus.h
> +++ b/target/i386/hax/hax-cpus.h
> @@ -12,8 +12,6 @@
>  
>  #include "sysemu/cpus.h"
>  
> -extern const CpusAccel hax_cpus;
> -
>  #include "hax-interface.h"
>  #include "hax-i386.h"
>  
> diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-cpus.c
> index 817b3d7452..124662de58 100644
> --- a/target/i386/hvf/hvf-cpus.c
> +++ b/target/i386/hvf/hvf-cpus.c
> @@ -121,11 +121,26 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
>                         cpu, QEMU_THREAD_JOINABLE);
>  }
>  
> -const CpusAccel hvf_cpus = {
> -    .create_vcpu_thread = hvf_start_vcpu_thread,
> +static void hvf_cpus_class_init(ObjectClass *oc, void *data)
> +{
> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
>  
> -    .synchronize_post_reset = hvf_cpu_synchronize_post_reset,
> -    .synchronize_post_init = hvf_cpu_synchronize_post_init,
> -    .synchronize_state = hvf_cpu_synchronize_state,
> -    .synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm,
> +    ops->create_vcpu_thread = hvf_start_vcpu_thread;
> +
> +    ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
> +    ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
> +    ops->synchronize_state = hvf_cpu_synchronize_state;
> +    ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
> +};
> +static const TypeInfo hvf_cpus_type_info = {
> +    .name = CPUS_ACCEL_TYPE_NAME("hvf"),
> +
> +    .parent = TYPE_CPUS_ACCEL_OPS,
> +    .class_init = hvf_cpus_class_init,
> +    .abstract = true,
>  };
> +static void hvf_cpus_register_types(void)
> +{
> +    type_register_static(&hvf_cpus_type_info);
> +}
> +type_init(hvf_cpus_register_types);
> diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.h
> index ced31b82c0..8f992da168 100644
> --- a/target/i386/hvf/hvf-cpus.h
> +++ b/target/i386/hvf/hvf-cpus.h
> @@ -12,8 +12,6 @@
>  
>  #include "sysemu/cpus.h"
>  
> -extern const CpusAccel hvf_cpus;
> -
>  int hvf_init_vcpu(CPUState *);
>  int hvf_vcpu_exec(CPUState *);
>  void hvf_cpu_synchronize_state(CPUState *);
> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> index 58794c35ae..bd94bb5243 100644
> --- a/target/i386/hvf/hvf.c
> +++ b/target/i386/hvf/hvf.c
> @@ -910,12 +910,3 @@ static void hvf_type_init(void)
>  }
>  
>  type_init(hvf_type_init);
> -
> -static void hvf_accel_cpu_init(void)
> -{
> -    if (hvf_enabled()) {
> -        cpus_register_accel(&hvf_cpus);
> -    }
> -}
> -
> -accel_cpu_init(hvf_accel_cpu_init);
> diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
> index 097d6f5e60..90adae9af7 100644
> --- a/target/i386/whpx/whpx-all.c
> +++ b/target/i386/whpx/whpx-all.c
> @@ -1711,12 +1711,3 @@ error:
>  }
>  
>  type_init(whpx_type_init);
> -
> -static void whpx_accel_cpu_init(void)
> -{
> -    if (whpx_enabled()) {
> -        cpus_register_accel(&whpx_cpus);
> -    }
> -}
> -
> -accel_cpu_init(whpx_accel_cpu_init);
> diff --git a/target/i386/whpx/whpx-cpus.c b/target/i386/whpx/whpx-cpus.c
> index d9bd5a2d36..1e736a50b0 100644
> --- a/target/i386/whpx/whpx-cpus.c
> +++ b/target/i386/whpx/whpx-cpus.c
> @@ -85,12 +85,27 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
>      }
>  }
>  
> -const CpusAccel whpx_cpus = {
> -    .create_vcpu_thread = whpx_start_vcpu_thread,
> -    .kick_vcpu_thread = whpx_kick_vcpu_thread,
> +static void whpx_cpus_class_init(ObjectClass *oc, void *data)
> +{
> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
>  
> -    .synchronize_post_reset = whpx_cpu_synchronize_post_reset,
> -    .synchronize_post_init = whpx_cpu_synchronize_post_init,
> -    .synchronize_state = whpx_cpu_synchronize_state,
> -    .synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm,
> +    ops->create_vcpu_thread = whpx_start_vcpu_thread;
> +    ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
> +
> +    ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
> +    ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
> +    ops->synchronize_state = whpx_cpu_synchronize_state;
> +    ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm;
> +};
> +static const TypeInfo whpx_cpus_type_info = {
> +    .name = CPUS_ACCEL_TYPE_NAME("whpx"),
> +
> +    .parent = TYPE_CPUS_ACCEL_OPS,
> +    .class_init = whpx_cpus_class_init,
> +    .abstract = true,
>  };
> +static void whpx_cpus_register_types(void)
> +{
> +    type_register_static(&whpx_cpus_type_info);
> +}
> +type_init(whpx_cpus_register_types);
> diff --git a/target/i386/whpx/whpx-cpus.h b/target/i386/whpx/whpx-cpus.h
> index bdb367d1d0..2dee6d61ea 100644
> --- a/target/i386/whpx/whpx-cpus.h
> +++ b/target/i386/whpx/whpx-cpus.h
> @@ -12,8 +12,6 @@
>  
>  #include "sysemu/cpus.h"
>  
> -extern const CpusAccel whpx_cpus;
> -
>  int whpx_init_vcpu(CPUState *cpu);
>  int whpx_vcpu_exec(CPUState *cpu);
>  void whpx_destroy_vcpu(CPUState *cpu);
> -- 
> 2.26.2
> 

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode
  2020-11-24 16:22 ` [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode Claudio Fontana
@ 2020-11-24 17:56   ` Eduardo Habkost
  2020-11-24 18:16     ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 17:56 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 05:22:06PM +0100, Claudio Fontana wrote:
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
[...]
> @@ -908,8 +909,12 @@ int main(int argc, char **argv)
>      }
>  
>      /* init tcg before creating CPUs and to get qemu_host_page_size */
> -    tcg_exec_init(0);
> +    {
> +        AccelClass *ac = accel_find("tcg");
>  
> +        g_assert(ac != NULL);
> +        ac->init_machine(NULL);

Most init_machine() methods will crash if you call them with a
NULL argument.

This looks like another reason for having a
  void accel_init(AccelState*)
function and a
  void (*init)(AccelState*)
method in AccelClass.

Then the whole code block above would be as trivial as:

  accel_init(current_accel());


> +    }
[...]
> 

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode
  2020-11-24 17:56   ` Eduardo Habkost
@ 2020-11-24 18:16     ` Claudio Fontana
  0 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 18:16 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

Hi Eduardo,

thanks for looking at this,

On 11/24/20 6:56 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 05:22:06PM +0100, Claudio Fontana wrote:
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
> [...]
>> @@ -908,8 +909,12 @@ int main(int argc, char **argv)
>>      }
>>  
>>      /* init tcg before creating CPUs and to get qemu_host_page_size */
>> -    tcg_exec_init(0);
>> +    {
>> +        AccelClass *ac = accel_find("tcg");
>>  
>> +        g_assert(ac != NULL);
>> +        ac->init_machine(NULL);
> 
> Most init_machine() methods will crash if you call them with a
> NULL argument.

not tcg though,


> 
> This looks like another reason for having a
>   void accel_init(AccelState*)
> function and a
>   void (*init)(AccelState*)
> method in AccelClass.
> 
> Then the whole code block above would be as trivial as:
> 
>   accel_init(current_accel());


but this does look like an attractive result,

thanks!

CLaudio
> 
> 
>> +    }
> [...]
>>
> 



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 17:08   ` Eduardo Habkost
@ 2020-11-24 18:29     ` Claudio Fontana
  2020-11-24 19:08       ` Eduardo Habkost
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 18:29 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/24/20 6:08 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 05:22:07PM +0100, Claudio Fontana wrote:
>> apply this to the registration of the cpus accel interfaces,
>>
>> but this will be also in preparation for later use of this
>> new module init step to also register per-accel x86 cpu type
>> interfaces.
>>
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
> [...]
>> diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
>> index b4e731cb2b..482f89729f 100644
>> --- a/accel/qtest/qtest.c
>> +++ b/accel/qtest/qtest.c
>> @@ -32,7 +32,6 @@ const CpusAccel qtest_cpus = {
>>  
>>  static int qtest_init_accel(MachineState *ms)
>>  {
>> -    cpus_register_accel(&qtest_cpus);
>>      return 0;
>>  }
>>  
>> @@ -58,3 +57,12 @@ static void qtest_type_init(void)
>>  }
>>  
>>  type_init(qtest_type_init);
>> +
>> +static void qtest_accel_cpu_init(void)
>> +{
>> +    if (qtest_enabled()) {
>> +        cpus_register_accel(&qtest_cpus);
>> +    }
>> +}
>> +
>> +accel_cpu_init(qtest_accel_cpu_init);
> 
> I don't understand why this (and the similar changes on other
> accelerators) is an improvement.
> 
> You are replacing a trivial AccelClass-specific init method with
> a module_init() function that has a hidden dependency on runtime
> state.
> 

Not a big advantage I agree,
I think however there is one, in using the existing framework that exists, for the purposes that it was built for.

As I understand it, the global module init framework is supposed to mark the major initialization steps,
and this seems to fit the bill.

The "hidden" dependency on the fact that accels need to be initialized at that time, is not hidden at all I think,
it is what this module init step is all about.

It is explicitly meaning, "_now that the current accelerator is chosen_, perform these initializations".

But, as you mentioned elsewhere, I will in the meantime anyway squash these things so they do not start fragmented at all, and centralize immediately.


Thanks,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 16:59   ` Eduardo Habkost
@ 2020-11-24 18:38     ` Claudio Fontana
  0 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 18:38 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/24/20 5:59 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 05:22:09PM +0100, Claudio Fontana wrote:
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> 
> Probably this can be squashed into patch 10/12.


Yes, you are right, no point building things fragmented and then merging together later.


> 
>> ---
>>  target/i386/cpu-qom.h |  2 --
>>  target/i386/cpu.c     | 27 ++++++++++++++++++++-------
>>  target/i386/hvf/cpu.c |  9 ---------
>>  target/i386/kvm/cpu.c |  8 --------
>>  target/i386/tcg/cpu.c |  9 ---------
>>  5 files changed, 20 insertions(+), 35 deletions(-)
>>
>> diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
>> index 9316e78e71..2cea5394c6 100644
>> --- a/target/i386/cpu-qom.h
>> +++ b/target/i386/cpu-qom.h
>> @@ -98,6 +98,4 @@ struct X86CPUAccelClass {
>>      void (*cpu_realizefn)(X86CPU *cpu, Error **errp);
>>  };
>>  
>> -void x86_cpu_accel_init(const char *accel_name);
>> -
>>  #endif
>> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
>> index b799723e53..f6fd055046 100644
>> --- a/target/i386/cpu.c
>> +++ b/target/i386/cpu.c
>> @@ -7066,18 +7066,31 @@ type_init(x86_cpu_register_types)
>>  static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
>>  {
>>      X86CPUClass *xcc = X86_CPU_CLASS(klass);
>> -    const X86CPUAccelClass **accel = opaque;
>> +    X86CPUAccelClass *accel = opaque;
>>  
>> -    xcc->accel = *accel;
>> +    xcc->accel = accel;
>>      xcc->accel->cpu_common_class_init(xcc);
>>  }
>>  
>> -void x86_cpu_accel_init(const char *accel_name)
>> +static void x86_cpu_accel_init(void)
>>  {
>> -    X86CPUAccelClass *acc;
>> +    const char *ac_name;
>> +    ObjectClass *ac;
>> +    char *xac_name;
>> +    ObjectClass *xac;
>>  
>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>> -    g_assert(acc != NULL);
>> +    ac = object_get_class(OBJECT(current_accel()));
>> +    g_assert(ac != NULL);
>> +    ac_name = object_class_get_name(ac);
>> +    g_assert(ac_name != NULL);
>>  
>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>> +    xac = object_class_by_name(xac_name);
>> +    g_free(xac_name);
>> +
>> +    if (xac) {
>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>> +    }
>>  }
>> +
>> +accel_cpu_init(x86_cpu_accel_init);
> 
> This keeps the hidden initialization ordering dependency between
> MODULE_INIT_ACCEL_CPU and current_accel().  I thought we were
> going to get rid of module init functions that depend on runtime
> state.
> 
> This is an improvement to the code in patch 10/12, though.  If
> others believe it is an acceptable (temporary) solution, I won't
> block it.


In the way I thought about it, MODULE_INIT_ACCEL_CPU meant exactly that: initializations to be done after accel is chosen.
So in my view the relationship with current_accel() was then following naturally.



> 
> I would still prefer to have a
>   void arch_accel_cpu_init(AccelState*)
> function which would call a
>   void x86_cpu_accel_init(AccelState*)
> function.  That would make the dependency between
> x86_cpu_accel_init() and accelerator creation explicit.
> 


not a bad idea either,
what I would lose here is a single point to discover the codebase, ie

MODULE_INIT_ACCEL_CPU via a simple grep or gid MODULE_INIT_ACCEL_CPU gives me all initializations done
for this phase, not only the arch_ stuff, but also currently the Ops stuff.


> 
>> diff --git a/target/i386/hvf/cpu.c b/target/i386/hvf/cpu.c
>> index 7e7dc044d3..70b6dbfc10 100644
>> --- a/target/i386/hvf/cpu.c
>> +++ b/target/i386/hvf/cpu.c
>> @@ -65,12 +65,3 @@ static void hvf_cpu_accel_register_types(void)
>>      type_register_static(&hvf_cpu_accel_type_info);
>>  }
>>  type_init(hvf_cpu_accel_register_types);
>> -
>> -static void hvf_cpu_accel_init(void)
>> -{
>> -    if (hvf_enabled()) {
>> -        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("hvf"));
>> -    }
>> -}
>> -
>> -accel_cpu_init(hvf_cpu_accel_init);
>> diff --git a/target/i386/kvm/cpu.c b/target/i386/kvm/cpu.c
>> index bc5f519479..c17ed5a3f2 100644
>> --- a/target/i386/kvm/cpu.c
>> +++ b/target/i386/kvm/cpu.c
>> @@ -147,11 +147,3 @@ static void kvm_cpu_accel_register_types(void)
>>      type_register_static(&kvm_cpu_accel_type_info);
>>  }
>>  type_init(kvm_cpu_accel_register_types);
>> -
>> -static void kvm_cpu_accel_init(void)
>> -{
>> -    if (kvm_enabled()) {
>> -        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("kvm"));
>> -    }
>> -}
>> -accel_cpu_init(kvm_cpu_accel_init);
>> diff --git a/target/i386/tcg/cpu.c b/target/i386/tcg/cpu.c
>> index e7d4effdd0..00166c36e9 100644
>> --- a/target/i386/tcg/cpu.c
>> +++ b/target/i386/tcg/cpu.c
>> @@ -170,12 +170,3 @@ static void tcg_cpu_accel_register_types(void)
>>      type_register_static(&tcg_cpu_accel_type_info);
>>  }
>>  type_init(tcg_cpu_accel_register_types);
>> -
>> -static void tcg_cpu_accel_init(void)
>> -{
>> -    if (tcg_enabled()) {
>> -        x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("tcg"));
>> -    }
>> -}
>> -
>> -accel_cpu_init(tcg_cpu_accel_init);
>> -- 
>> 2.26.2
>>
> 



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 17:48   ` Eduardo Habkost
@ 2020-11-24 18:52     ` Claudio Fontana
  2020-11-24 19:27       ` Eduardo Habkost
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 18:52 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/24/20 6:48 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 05:22:10PM +0100, Claudio Fontana wrote:
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
>>  accel/kvm/kvm-all.c          |  9 -------
>>  accel/kvm/kvm-cpus.c         | 26 +++++++++++++-----
>>  accel/kvm/kvm-cpus.h         |  2 --
>>  accel/qtest/qtest.c          | 31 ++++++++++++----------
>>  accel/tcg/tcg-cpus-icount.c  | 11 +-------
>>  accel/tcg/tcg-cpus-icount.h  |  2 ++
>>  accel/tcg/tcg-cpus-mttcg.c   | 12 +++------
>>  accel/tcg/tcg-cpus-mttcg.h   | 19 ++++++++++++++
>>  accel/tcg/tcg-cpus-rr.c      |  7 -----
>>  accel/tcg/tcg-cpus.c         | 48 ++++++++++++++++++++++++++-------
>>  accel/tcg/tcg-cpus.h         |  4 ---
>>  accel/xen/xen-all.c          | 29 ++++++++++----------
>>  include/sysemu/cpus.h        | 39 ++++++++++++++++++++-------
>>  softmmu/cpus.c               | 51 +++++++++++++++++++++++++++++-------
>>  target/i386/hax/hax-all.c    |  9 -------
>>  target/i386/hax/hax-cpus.c   | 29 +++++++++++++++-----
>>  target/i386/hax/hax-cpus.h   |  2 --
>>  target/i386/hvf/hvf-cpus.c   | 27 ++++++++++++++-----
>>  target/i386/hvf/hvf-cpus.h   |  2 --
>>  target/i386/hvf/hvf.c        |  9 -------
>>  target/i386/whpx/whpx-all.c  |  9 -------
>>  target/i386/whpx/whpx-cpus.c | 29 +++++++++++++++-----
>>  target/i386/whpx/whpx-cpus.h |  2 --
>>  23 files changed, 251 insertions(+), 157 deletions(-)
>>  create mode 100644 accel/tcg/tcg-cpus-mttcg.h
>>
>> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
>> index 509b249f52..33156cc4c7 100644
>> --- a/accel/kvm/kvm-all.c
>> +++ b/accel/kvm/kvm-all.c
>> @@ -3234,12 +3234,3 @@ static void kvm_type_init(void)
>>  }
>>  
>>  type_init(kvm_type_init);
>> -
>> -static void kvm_accel_cpu_init(void)
>> -{
>> -    if (kvm_enabled()) {
>> -        cpus_register_accel(&kvm_cpus);
>> -    }
>> -}
>> -
>> -accel_cpu_init(kvm_accel_cpu_init);
>> diff --git a/accel/kvm/kvm-cpus.c b/accel/kvm/kvm-cpus.c
>> index d809b1e74c..33dc8e737a 100644
>> --- a/accel/kvm/kvm-cpus.c
>> +++ b/accel/kvm/kvm-cpus.c
>> @@ -74,11 +74,25 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
>>                         cpu, QEMU_THREAD_JOINABLE);
>>  }
>>  
>> -const CpusAccel kvm_cpus = {
>> -    .create_vcpu_thread = kvm_start_vcpu_thread,
>> +static void kvm_cpus_class_init(ObjectClass *oc, void *data)
>> +{
>> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
> 
> Why do you need a separate QOM type hierarchy instead of just
> doing this inside AccelClass methods and/or existing accel
> class_init functions?
> 
>>  
>> -    .synchronize_post_reset = kvm_cpu_synchronize_post_reset,
>> -    .synchronize_post_init = kvm_cpu_synchronize_post_init,
>> -    .synchronize_state = kvm_cpu_synchronize_state,
>> -    .synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm,
>> +    ops->create_vcpu_thread = kvm_start_vcpu_thread;
>> +    ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
>> +    ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
>> +    ops->synchronize_state = kvm_cpu_synchronize_state;
>> +    ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
> 
> All of these could be AccelClass fields.


Makes sense, and I like also the idea below (to have a pointer from the AccelClass to the Ops).
I'll give both a try.


> 
> TCG makes it a bit more complicated because there's a different
> set of methods chosen for TYPE_TCG_ACCEL depending on the
> configuration.

Right, that was a bit painful,

> This could be solved by patching AccelClass at
> init time, or by moving the method pointers to AccelState.


Ok I'll experiment here.

> 
> Alternatively, if you still want to keep the
> CpusAccel/CpusAccelOps struct, that's OK.  You can just add a
> `CpusAccel *cpu_accel_ops` field to AccelClass or AccelState.  No
> need for a separate QOM hierarchy, either.
> 
> If you _really_ want a separate TYPE_CPU_ACCEL_OPS QOM type, you



No, I do not think I really need a separate QOM type.



> can still have it.  But it can be just an interface implemented
> by each accel subclass, instead of requiring a separate
> CPUS_ACCEL_TYPE_NAME(...) type to be registered for each
> accelerator.  (I don't see why you would want it, though.)
> 
> 
>>  };
>> +static const TypeInfo kvm_cpus_type_info = {
>> +    .name = CPUS_ACCEL_TYPE_NAME("kvm"),
>> +
>> +    .parent = TYPE_CPUS_ACCEL_OPS,
>> +    .class_init = kvm_cpus_class_init,
>> +    .abstract = true,
>> +};
>> +static void kvm_cpus_register_types(void)
>> +{
>> +    type_register_static(&kvm_cpus_type_info);
>> +}
>> +type_init(kvm_cpus_register_types);
> [...]
>> -typedef struct CpusAccel {
>> -    void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */
>> +typedef struct CpusAccelOps CpusAccelOps;
>> +DECLARE_CLASS_CHECKERS(CpusAccelOps, CPUS_ACCEL_OPS, TYPE_CPUS_ACCEL_OPS)
>> +
>> +struct CpusAccelOps {
>> +    ObjectClass parent_class;
>> +
>> +    /* initialization function called when accel is chosen */
>> +    void (*accel_chosen_init)(CpusAccelOps *ops);
> 
> This can be an AccelClass method too.  What about just naming it
> AccelClass.init?


yes, .init is fine for me

> 
>> +
>> +    void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */
>>      void (*kick_vcpu_thread)(CPUState *cpu);
>>  
>>      void (*synchronize_post_reset)(CPUState *cpu);
>> @@ -20,13 +45,7 @@ typedef struct CpusAccel {
>>  
>>      int64_t (*get_virtual_clock)(void);
>>      int64_t (*get_elapsed_ticks)(void);
>> -} CpusAccel;
>> -
> [...]
>> +
>> +static void cpus_accel_ops_init(void)
>> +{
> 
> If we move the fields above part of AccelClass, this could be
> called accel_init().


*nod*


> 
>> +    const char *ac_name;
>> +    ObjectClass *ac;
>> +    char *ops_name;
>> +    ObjectClass *ops;
>> +
>> +    ac = object_get_class(OBJECT(current_accel()));
>> +    g_assert(ac != NULL);
> 
> If you call this function directly from accel_init_machine(),
> bsd-user:main(), and linux-user:main(), you can get AccelState*
> as argument, and the dependency on current_accel() becomes
> explicit instead of implicit.


That I must say is a good point.


> 
>> +    ac_name = object_class_get_name(ac);
>> +    g_assert(ac_name != NULL);
>> +
>> +    ops_name = g_strdup_printf("%s-ops", ac_name);
>> +    ops = object_class_by_name(ops_name);
>> +    g_free(ops_name);
> 
> If we make the fields above part of AccelClass, you don't need
> this lookup trick.



Yes, I will remove this QOM hierarchy completely.
 

> 
>> +
>> +    /*
>> +     * all accelerators need to define ops, providing at least a mandatory
>> +     * non-NULL create_vcpu_thread operation.
>> +     */
>> +    g_assert(ops != NULL);
>> +    cpus_accel = CPUS_ACCEL_OPS_CLASS(ops);
>> +    if (cpus_accel->accel_chosen_init) {
>> +        cpus_accel->accel_chosen_init(cpus_accel);
> 
> If we move CpusAccelOps.accel_chosen_init to AccelClass.init,
> this would be just:
> 
>   AccelClass *acc = ACCEL_GET_CLASS(accel);
>   if (acc->init) {
>       acc->init(acc);
>   }
> 


nice...


>> +    }
> 
> Additionally, if you call arch_cpu_accel_init() here, you won't
> need MODULE_INIT_ACCEL_CPU anymore.  The
> 
>   module_call_init(MODULE_INIT_ACCEL_CPU)
> 
> call with implicit dependencies on runtime state inside vl.c and
> *-user/main.c becomes a trivial:
> 
>   accel_init(accel)
> 
> call in accel_init_machine() and *-user:main().



I do need a separate thing for the arch cpu accel specialization though,
without MODULE_INIT_ACCEL_CPU that link between all operations done at accel-chosen time is missing..



> 
>> +}
>> +
>> +accel_cpu_init(cpus_accel_ops_init);
>> diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
>> index 77c365311c..ec3c426223 100644
>> --- a/target/i386/hax/hax-all.c
>> +++ b/target/i386/hax/hax-all.c
>> @@ -1138,12 +1138,3 @@ static void hax_type_init(void)
>>  }
>>  
>>  type_init(hax_type_init);
>> -
>> -static void hax_accel_cpu_init(void)
>> -{
>> -    if (hax_enabled()) {
>> -        cpus_register_accel(&hax_cpus);
>> -    }
>> -}
>> -
>> -accel_cpu_init(hax_accel_cpu_init);
>> diff --git a/target/i386/hax/hax-cpus.c b/target/i386/hax/hax-cpus.c
>> index f72c85bd49..171b5ac1e6 100644
>> --- a/target/i386/hax/hax-cpus.c
>> +++ b/target/i386/hax/hax-cpus.c
>> @@ -74,12 +74,27 @@ static void hax_start_vcpu_thread(CPUState *cpu)
>>  #endif
>>  }
>>  
>> -const CpusAccel hax_cpus = {
>> -    .create_vcpu_thread = hax_start_vcpu_thread,
>> -    .kick_vcpu_thread = hax_kick_vcpu_thread,
>> +static void hax_cpus_class_init(ObjectClass *oc, void *data)
>> +{
>> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
>>  
>> -    .synchronize_post_reset = hax_cpu_synchronize_post_reset,
>> -    .synchronize_post_init = hax_cpu_synchronize_post_init,
>> -    .synchronize_state = hax_cpu_synchronize_state,
>> -    .synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm,
>> +    ops->create_vcpu_thread = hax_start_vcpu_thread;
>> +    ops->kick_vcpu_thread = hax_kick_vcpu_thread;
>> +
>> +    ops->synchronize_post_reset = hax_cpu_synchronize_post_reset;
>> +    ops->synchronize_post_init = hax_cpu_synchronize_post_init;
>> +    ops->synchronize_state = hax_cpu_synchronize_state;
>> +    ops->synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm;
>> +};
>> +static const TypeInfo hax_cpus_type_info = {
>> +    .name = CPUS_ACCEL_TYPE_NAME("hax"),
>> +
>> +    .parent = TYPE_CPUS_ACCEL_OPS,
>> +    .class_init = hax_cpus_class_init,
>> +    .abstract = true,
>>  };
>> +static void hax_cpus_register_types(void)
>> +{
>> +    type_register_static(&hax_cpus_type_info);
>> +}
>> +type_init(hax_cpus_register_types);
>> diff --git a/target/i386/hax/hax-cpus.h b/target/i386/hax/hax-cpus.h
>> index ee8ab7a631..c7698519cd 100644
>> --- a/target/i386/hax/hax-cpus.h
>> +++ b/target/i386/hax/hax-cpus.h
>> @@ -12,8 +12,6 @@
>>  
>>  #include "sysemu/cpus.h"
>>  
>> -extern const CpusAccel hax_cpus;
>> -
>>  #include "hax-interface.h"
>>  #include "hax-i386.h"
>>  
>> diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/hvf/hvf-cpus.c
>> index 817b3d7452..124662de58 100644
>> --- a/target/i386/hvf/hvf-cpus.c
>> +++ b/target/i386/hvf/hvf-cpus.c
>> @@ -121,11 +121,26 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
>>                         cpu, QEMU_THREAD_JOINABLE);
>>  }
>>  
>> -const CpusAccel hvf_cpus = {
>> -    .create_vcpu_thread = hvf_start_vcpu_thread,
>> +static void hvf_cpus_class_init(ObjectClass *oc, void *data)
>> +{
>> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
>>  
>> -    .synchronize_post_reset = hvf_cpu_synchronize_post_reset,
>> -    .synchronize_post_init = hvf_cpu_synchronize_post_init,
>> -    .synchronize_state = hvf_cpu_synchronize_state,
>> -    .synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm,
>> +    ops->create_vcpu_thread = hvf_start_vcpu_thread;
>> +
>> +    ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
>> +    ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
>> +    ops->synchronize_state = hvf_cpu_synchronize_state;
>> +    ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
>> +};
>> +static const TypeInfo hvf_cpus_type_info = {
>> +    .name = CPUS_ACCEL_TYPE_NAME("hvf"),
>> +
>> +    .parent = TYPE_CPUS_ACCEL_OPS,
>> +    .class_init = hvf_cpus_class_init,
>> +    .abstract = true,
>>  };
>> +static void hvf_cpus_register_types(void)
>> +{
>> +    type_register_static(&hvf_cpus_type_info);
>> +}
>> +type_init(hvf_cpus_register_types);
>> diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/hvf/hvf-cpus.h
>> index ced31b82c0..8f992da168 100644
>> --- a/target/i386/hvf/hvf-cpus.h
>> +++ b/target/i386/hvf/hvf-cpus.h
>> @@ -12,8 +12,6 @@
>>  
>>  #include "sysemu/cpus.h"
>>  
>> -extern const CpusAccel hvf_cpus;
>> -
>>  int hvf_init_vcpu(CPUState *);
>>  int hvf_vcpu_exec(CPUState *);
>>  void hvf_cpu_synchronize_state(CPUState *);
>> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
>> index 58794c35ae..bd94bb5243 100644
>> --- a/target/i386/hvf/hvf.c
>> +++ b/target/i386/hvf/hvf.c
>> @@ -910,12 +910,3 @@ static void hvf_type_init(void)
>>  }
>>  
>>  type_init(hvf_type_init);
>> -
>> -static void hvf_accel_cpu_init(void)
>> -{
>> -    if (hvf_enabled()) {
>> -        cpus_register_accel(&hvf_cpus);
>> -    }
>> -}
>> -
>> -accel_cpu_init(hvf_accel_cpu_init);
>> diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
>> index 097d6f5e60..90adae9af7 100644
>> --- a/target/i386/whpx/whpx-all.c
>> +++ b/target/i386/whpx/whpx-all.c
>> @@ -1711,12 +1711,3 @@ error:
>>  }
>>  
>>  type_init(whpx_type_init);
>> -
>> -static void whpx_accel_cpu_init(void)
>> -{
>> -    if (whpx_enabled()) {
>> -        cpus_register_accel(&whpx_cpus);
>> -    }
>> -}
>> -
>> -accel_cpu_init(whpx_accel_cpu_init);
>> diff --git a/target/i386/whpx/whpx-cpus.c b/target/i386/whpx/whpx-cpus.c
>> index d9bd5a2d36..1e736a50b0 100644
>> --- a/target/i386/whpx/whpx-cpus.c
>> +++ b/target/i386/whpx/whpx-cpus.c
>> @@ -85,12 +85,27 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
>>      }
>>  }
>>  
>> -const CpusAccel whpx_cpus = {
>> -    .create_vcpu_thread = whpx_start_vcpu_thread,
>> -    .kick_vcpu_thread = whpx_kick_vcpu_thread,
>> +static void whpx_cpus_class_init(ObjectClass *oc, void *data)
>> +{
>> +    CpusAccelOps *ops = CPUS_ACCEL_OPS_CLASS(oc);
>>  
>> -    .synchronize_post_reset = whpx_cpu_synchronize_post_reset,
>> -    .synchronize_post_init = whpx_cpu_synchronize_post_init,
>> -    .synchronize_state = whpx_cpu_synchronize_state,
>> -    .synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm,
>> +    ops->create_vcpu_thread = whpx_start_vcpu_thread;
>> +    ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
>> +
>> +    ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
>> +    ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
>> +    ops->synchronize_state = whpx_cpu_synchronize_state;
>> +    ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm;
>> +};
>> +static const TypeInfo whpx_cpus_type_info = {
>> +    .name = CPUS_ACCEL_TYPE_NAME("whpx"),
>> +
>> +    .parent = TYPE_CPUS_ACCEL_OPS,
>> +    .class_init = whpx_cpus_class_init,
>> +    .abstract = true,
>>  };
>> +static void whpx_cpus_register_types(void)
>> +{
>> +    type_register_static(&whpx_cpus_type_info);
>> +}
>> +type_init(whpx_cpus_register_types);
>> diff --git a/target/i386/whpx/whpx-cpus.h b/target/i386/whpx/whpx-cpus.h
>> index bdb367d1d0..2dee6d61ea 100644
>> --- a/target/i386/whpx/whpx-cpus.h
>> +++ b/target/i386/whpx/whpx-cpus.h
>> @@ -12,8 +12,6 @@
>>  
>>  #include "sysemu/cpus.h"
>>  
>> -extern const CpusAccel whpx_cpus;
>> -
>>  int whpx_init_vcpu(CPUState *cpu);
>>  int whpx_vcpu_exec(CPUState *cpu);
>>  void whpx_destroy_vcpu(CPUState *cpu);
>> -- 
>> 2.26.2
>>
> 


Thanks a lot for reading all this!

Back to the drawing board..

Ciao,

Claudio





^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 18:29     ` Claudio Fontana
@ 2020-11-24 19:08       ` Eduardo Habkost
  2020-11-24 20:01         ` Paolo Bonzini
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 19:08 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 07:29:50PM +0100, Claudio Fontana wrote:
> On 11/24/20 6:08 PM, Eduardo Habkost wrote:
> > On Tue, Nov 24, 2020 at 05:22:07PM +0100, Claudio Fontana wrote:
> >> apply this to the registration of the cpus accel interfaces,
> >>
> >> but this will be also in preparation for later use of this
> >> new module init step to also register per-accel x86 cpu type
> >> interfaces.
> >>
> >> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> >> ---
> > [...]
> >> diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
> >> index b4e731cb2b..482f89729f 100644
> >> --- a/accel/qtest/qtest.c
> >> +++ b/accel/qtest/qtest.c
> >> @@ -32,7 +32,6 @@ const CpusAccel qtest_cpus = {
> >>  
> >>  static int qtest_init_accel(MachineState *ms)
> >>  {
> >> -    cpus_register_accel(&qtest_cpus);
> >>      return 0;
> >>  }
> >>  
> >> @@ -58,3 +57,12 @@ static void qtest_type_init(void)
> >>  }
> >>  
> >>  type_init(qtest_type_init);
> >> +
> >> +static void qtest_accel_cpu_init(void)
> >> +{
> >> +    if (qtest_enabled()) {
> >> +        cpus_register_accel(&qtest_cpus);
> >> +    }
> >> +}
> >> +
> >> +accel_cpu_init(qtest_accel_cpu_init);
> > 
> > I don't understand why this (and the similar changes on other
> > accelerators) is an improvement.
> > 
> > You are replacing a trivial AccelClass-specific init method with
> > a module_init() function that has a hidden dependency on runtime
> > state.
> > 
> 
> Not a big advantage I agree,
> I think however there is one, in using the existing framework that exists, for the purposes that it was built for.
> 
> As I understand it, the global module init framework is supposed to mark the major initialization steps,
> and this seems to fit the bill.

That seems to be the main source of disagreement.  I don't agree
that's the purpose of module_init().

The module init framework is used to unconditionally register
module-provided entities like option names, QOM types, block
drivers, trace events, etc.  The entities registered by module
init functions represent a passive dynamically loadable piece of
code.

module_init() was never used for initialization of machines,
devices, CPUs, or other runtime state.  We don't have
MODULE_INIT_MONITOR, MODULE_INIT_OBJECTS, MODULE_INIT_MACHINE,
MODULE_INIT_CPUS, MODULE_INIT_DEVICES, etc.

And I'm not convinced we should, because it would hide
dependencies between initialization steps.  It would force us to
make initialization functions affect and depend on global state.

I believe this:

  int main()
  {
    result_of_A = init_A(input_for_A);
    result_of_B = init_B(input_for_B);
    result_of_C = init_C(input_for_C);
  }

is clearer and more maintainable than:

  int main()
  {
    module_init_call(MODULE_INIT_A);  /* result_of_A hidden in global state */
    module_init_call(MODULE_INIT_B);  /* result_of_B hidden in global state */
    module_init_call(MODULE_INIT_C);  /* result_of_C hidden in global state */
  }

> 
> The "hidden" dependency on the fact that accels need to be initialized at that time, is not hidden at all I think,
> it is what this module init step is all about.
> 
> It is explicitly meaning, "_now that the current accelerator is chosen_, perform these initializations".
> 
> But, as you mentioned elsewhere, I will in the meantime anyway squash these things so they do not start fragmented at all, and centralize immediately.

Agreed.  We still need to sort out the disagreement above, or
we'll spend a lot of energy arguing about code.

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 18:52     ` Claudio Fontana
@ 2020-11-24 19:27       ` Eduardo Habkost
  2020-11-24 19:39         ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 19:27 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 07:52:15PM +0100, Claudio Fontana wrote:
[...]
> >> +    }
> > 
> > Additionally, if you call arch_cpu_accel_init() here, you won't
> > need MODULE_INIT_ACCEL_CPU anymore.  The
> > 
> >   module_call_init(MODULE_INIT_ACCEL_CPU)
> > 
> > call with implicit dependencies on runtime state inside vl.c and
> > *-user/main.c becomes a trivial:
> > 
> >   accel_init(accel)
> > 
> > call in accel_init_machine() and *-user:main().
> 
> 
> 
> I do need a separate thing for the arch cpu accel specialization though,
> without MODULE_INIT_ACCEL_CPU that link between all operations done at accel-chosen time is missing..
> 

I think this is a key point we need to sort out.

What do you mean by "link between all operations done at
accel-chosen time" and why that's important?

accel_init_machine() has 2-3 lines of code with side effects.  It
calls AccelClass.init_machine(), which may may have hundreds of
lines of code.  accel_setup_post() has one additional method
call, which is triggered at a slightly different moment.

You are using MODULE_INIT_ACCEL for 2 additional lines of code:
- the cpus_register_accel() call
- the x86_cpu_accel_init() call

What makes those 2 lines of code so special, to make them deserve
a completely new mechanism to trigger them, instead of using
trivial function calls inside a accel_init() function?

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 19:27       ` Eduardo Habkost
@ 2020-11-24 19:39         ` Claudio Fontana
  2020-11-24 20:34           ` Eduardo Habkost
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-24 19:39 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/24/20 8:27 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 07:52:15PM +0100, Claudio Fontana wrote:
> [...]
>>>> +    }
>>>
>>> Additionally, if you call arch_cpu_accel_init() here, you won't
>>> need MODULE_INIT_ACCEL_CPU anymore.  The
>>>
>>>   module_call_init(MODULE_INIT_ACCEL_CPU)
>>>
>>> call with implicit dependencies on runtime state inside vl.c and
>>> *-user/main.c becomes a trivial:
>>>
>>>   accel_init(accel)
>>>
>>> call in accel_init_machine() and *-user:main().
>>
>>
>>
>> I do need a separate thing for the arch cpu accel specialization though,
>> without MODULE_INIT_ACCEL_CPU that link between all operations done at accel-chosen time is missing..
>>
> 
> I think this is a key point we need to sort out.
> 
> What do you mean by "link between all operations done at
> accel-chosen time" and why that's important?


For understanding by a reader that tries to figure this out,
(see the gid MODULE_INIT_ACCEL_CPU comment elsewhere in the thread).

And it could be that the high level plan to make accelerators fully dynamically loadable plugins in the future
also conditioned me to want to have a very clear demarcation line around the choice of the accelerator.


> 
> accel_init_machine() has 2-3 lines of code with side effects.  It
> calls AccelClass.init_machine(), which may may have hundreds of


could we initialize also all arch-dependent stuff in here?


> lines of code.  accel_setup_post() has one additional method
> call, which is triggered at a slightly different moment.
> 
> You are using MODULE_INIT_ACCEL for 2 additional lines of code:
> - the cpus_register_accel() call
> - the x86_cpu_accel_init() call
> 
> What makes those 2 lines of code so special, to make them deserve
> a completely new mechanism to trigger them, instead of using
> trivial function calls inside a accel_init() function?
> 

...can we do also the x86_cpu_accel_init inside accel_init()?


In any case I'll try also the alternative, it would be nice if I could bring everything together under the same roof,
and easily discoverable, both the arch-specific steps that we need to do at accel-chosen time and the non-arch-specific steps.

Hope this helps clarifying where I am coming from,
but I am open to have my mind changed, also trying the alternatives you propose here could help me see first hand how things play out.

Thanks!

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 19:08       ` Eduardo Habkost
@ 2020-11-24 20:01         ` Paolo Bonzini
  2020-11-25  9:21           ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Paolo Bonzini @ 2020-11-24 20:01 UTC (permalink / raw)
  To: Eduardo Habkost, Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Cameron Esfahani, Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Emilio G . Cota,
	haxm-team, Colin Xu, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Wenchao Wang

On 24/11/20 20:08, Eduardo Habkost wrote:
>> Not a big advantage I agree,
>> I think however there is one, in using the existing framework that exists, for the purposes that it was built for.
>>
>> As I understand it, the global module init framework is supposed to mark the major initialization steps,
>> and this seems to fit the bill.
> That seems to be the main source of disagreement.  I don't agree
> that's the purpose of module_init().
> 
> The module init framework is used to unconditionally register
> module-provided entities like option names, QOM types, block
> drivers, trace events, etc.  The entities registered by module
> init functions represent a passive dynamically loadable piece of
> code.

Indeed.  Think of module_init() as C++ global constructors.

Anything that has an "if" does not belong in module_init.

If you look at my review of the previous versions, I was not necessarily 
against MODULE_INIT_ACCEL_CPU, but I was (and am) strongly against 
calling it in the middle of the machine creation sequence.

Paolo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 16:22 ` [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces Claudio Fontana
  2020-11-24 16:59   ` Eduardo Habkost
@ 2020-11-24 20:13   ` Paolo Bonzini
  2020-11-24 21:31     ` Eduardo Habkost
                       ` (2 more replies)
  1 sibling, 3 replies; 51+ messages in thread
From: Paolo Bonzini @ 2020-11-24 20:13 UTC (permalink / raw)
  To: Claudio Fontana, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Colin Xu, Anthony Perard,
	Bruce Rogers, Olaf Hering

On 24/11/20 17:22, Claudio Fontana wrote:
> +static void x86_cpu_accel_init(void)
>  {
> -    X86CPUAccelClass *acc;
> +    const char *ac_name;
> +    ObjectClass *ac;
> +    char *xac_name;
> +    ObjectClass *xac;
>  
> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> -    g_assert(acc != NULL);
> +    ac = object_get_class(OBJECT(current_accel()));
> +    g_assert(ac != NULL);
> +    ac_name = object_class_get_name(ac);
> +    g_assert(ac_name != NULL);
>  
> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> +    xac = object_class_by_name(xac_name);
> +    g_free(xac_name);
> +
> +    if (xac) {
> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> +    }
>  }
> +
> +accel_cpu_init(x86_cpu_accel_init);

If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd 
rather make them functions in CPUClass (which you find and call via 
CPU_RESOLVING_TYPE) and AccelClass respectively.

Paolo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 00/12] i386 cleanup
  2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
                   ` (11 preceding siblings ...)
  2020-11-24 16:22 ` [RFC v5 12/12] accel: centralize initialization of CpusAccelOps Claudio Fontana
@ 2020-11-24 20:14 ` Paolo Bonzini
  12 siblings, 0 replies; 51+ messages in thread
From: Paolo Bonzini @ 2020-11-24 20:14 UTC (permalink / raw)
  To: Claudio Fontana, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Colin Xu, Anthony Perard,
	Bruce Rogers, Olaf Hering

On 24/11/20 17:21, Claudio Fontana wrote:
> In this version I basically QOMified X86CPUAccel, taking the
> suggestions from Eduardo as the starting point,
> but stopping just short of making it an actual QOM interface,
> using a plain abstract class, and then subclasses for the
> actual objects.
> 
> Initialization is still using the existing qemu initialization
> framework (module_call_init), which is I still think is better
> than the alternatives proposed, in the current state.
> 
> Possibly some improvements could be developed in the future here.
> In this case, effort should be put in keeping things extendible,
> in order not to be blocked once accelerators also become modules.

It's certainly getting there.  Thanks for persisting!

Paolo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 19:39         ` Claudio Fontana
@ 2020-11-24 20:34           ` Eduardo Habkost
  2020-11-25  9:32             ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 20:34 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Tue, Nov 24, 2020 at 08:39:33PM +0100, Claudio Fontana wrote:
> On 11/24/20 8:27 PM, Eduardo Habkost wrote:
> > On Tue, Nov 24, 2020 at 07:52:15PM +0100, Claudio Fontana wrote:
> > [...]
> >>>> +    }
> >>>
> >>> Additionally, if you call arch_cpu_accel_init() here, you won't
> >>> need MODULE_INIT_ACCEL_CPU anymore.  The
> >>>
> >>>   module_call_init(MODULE_INIT_ACCEL_CPU)
> >>>
> >>> call with implicit dependencies on runtime state inside vl.c and
> >>> *-user/main.c becomes a trivial:
> >>>
> >>>   accel_init(accel)
> >>>
> >>> call in accel_init_machine() and *-user:main().
> >>
> >>
> >>
> >> I do need a separate thing for the arch cpu accel specialization though,
> >> without MODULE_INIT_ACCEL_CPU that link between all operations done at accel-chosen time is missing..
> >>
> > 
> > I think this is a key point we need to sort out.
> > 
> > What do you mean by "link between all operations done at
> > accel-chosen time" and why that's important?
> 
> 
> For understanding by a reader that tries to figure this out,
> (see the gid MODULE_INIT_ACCEL_CPU comment elsewhere in the thread).

Right, but how does the module_call_init(MODULE_INIT_ACCEL_CPU)
indirection makes this easier to figure out than just looking at
a accel_init() function that makes regular function calls?


> 
> And it could be that the high level plan to make accelerators fully dynamically loadable plugins in the future
> also conditioned me to want to have a very clear demarcation line around the choice of the accelerator.

We have dynamically loadable modules for other QOM types,
already, and they just use type_init().  I don't see why an extra
module_init() type makes this easier.

> 
> 
> > 
> > accel_init_machine() has 2-3 lines of code with side effects.  It
> > calls AccelClass.init_machine(), which may may have hundreds of
> 
> 
> could we initialize also all arch-dependent stuff in here?

You can, if you use a wrapper + stub, like arch_cpu_accel_init().


> 
> 
> > lines of code.  accel_setup_post() has one additional method
> > call, which is triggered at a slightly different moment.
> > 
> > You are using MODULE_INIT_ACCEL for 2 additional lines of code:
> > - the cpus_register_accel() call
> > - the x86_cpu_accel_init() call
> > 
> > What makes those 2 lines of code so special, to make them deserve
> > a completely new mechanism to trigger them, instead of using
> > trivial function calls inside a accel_init() function?
> > 
> 
> ...can we do also the x86_cpu_accel_init inside accel_init()?
> 
> 
> In any case I'll try also the alternative, it would be nice if I could bring everything together under the same roof,
> and easily discoverable, both the arch-specific steps that we need to do at accel-chosen time and the non-arch-specific steps.

One way to bring everything together under the same roof is to
call everything inside a accel_init() function.


> 
> Hope this helps clarifying where I am coming from,
> but I am open to have my mind changed, also trying the alternatives you propose here could help me see first hand how things play out.

Thanks!

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 20:13   ` Paolo Bonzini
@ 2020-11-24 21:31     ` Eduardo Habkost
  2020-11-25  9:26       ` Claudio Fontana
  2020-11-26 10:57       ` Claudio Fontana
  2020-11-25  9:24     ` Claudio Fontana
  2020-11-26 14:42     ` Claudio Fontana
  2 siblings, 2 replies; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-24 21:31 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Claudio Fontana, Anthony Perard,
	Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang

On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
> On 24/11/20 17:22, Claudio Fontana wrote:
> > +static void x86_cpu_accel_init(void)
> >  {
> > -    X86CPUAccelClass *acc;
> > +    const char *ac_name;
> > +    ObjectClass *ac;
> > +    char *xac_name;
> > +    ObjectClass *xac;
> > -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> > -    g_assert(acc != NULL);
> > +    ac = object_get_class(OBJECT(current_accel()));
> > +    g_assert(ac != NULL);
> > +    ac_name = object_class_get_name(ac);
> > +    g_assert(ac_name != NULL);
> > -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> > +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> > +    xac = object_class_by_name(xac_name);
> > +    g_free(xac_name);
> > +
> > +    if (xac) {
> > +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> > +    }
> >  }
> > +
> > +accel_cpu_init(x86_cpu_accel_init);
> 
> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
> rather make them functions in CPUClass (which you find and call via
> CPU_RESOLVING_TYPE) and AccelClass respectively.

Making x86_cpu_accel_init() be a CPUClass method sounds like a
good idea.  This way we won't need a arch_cpu_accel_init() stub
for non-x86.

accel.c can't use cpu.h, correct?  We can add a:

  CPUClass *arch_base_cpu_type(void)
  {
      return object_class_by_name(CPU_RESOLVING_TYPE);
  }

function to arch_init.c, to allow target-independent code call
target-specific code.

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 20:01         ` Paolo Bonzini
@ 2020-11-25  9:21           ` Claudio Fontana
  2020-11-25  9:30             ` Paolo Bonzini
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-25  9:21 UTC (permalink / raw)
  To: Paolo Bonzini, Eduardo Habkost
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Paul Durrant, Olaf Hering, Jason Wang, Marcelo Tosatti,
	Richard Henderson, qemu-devel, Cameron Esfahani, Bruce Rogers,
	Roman Bolshakov, Emilio G . Cota, haxm-team, Peter Xu,
	Anthony Perard, Sunil Muthuswamy, Dario Faggioli,
	Philippe Mathieu-Daudé,
	Colin Xu

On 11/24/20 9:01 PM, Paolo Bonzini wrote:
> On 24/11/20 20:08, Eduardo Habkost wrote:
>>> Not a big advantage I agree,
>>> I think however there is one, in using the existing framework that exists, for the purposes that it was built for.
>>>
>>> As I understand it, the global module init framework is supposed to mark the major initialization steps,
>>> and this seems to fit the bill.
>> That seems to be the main source of disagreement.  I don't agree
>> that's the purpose of module_init().
>>
>> The module init framework is used to unconditionally register
>> module-provided entities like option names, QOM types, block
>> drivers, trace events, etc.  The entities registered by module
>> init functions represent a passive dynamically loadable piece of
>> code.
> 
> Indeed.  Think of module_init() as C++ global constructors.
> 
> Anything that has an "if" does not belong in module_init.
> 
> If you look at my review of the previous versions, I was not necessarily 
> against MODULE_INIT_ACCEL_CPU, but I was (and am) strongly against 
> calling it in the middle of the machine creation sequence.
> 
> Paolo
> 
> 

Hi Paolo,

in RFC v5 , module init for ACCEL_CPU is not conditional anymore, right?
But the fact that its behavior depends on current_accel() still disqualifies it?

It is called right after the accelerator is chosen and initialized in RFC v5, this still is "in the middle of the machine creation sequence"?

I am trying to find the actual things to fix, since when doing RFC v5 I tried to specifically address two points:

1) no if () inside module init functions

2) no proliferation of module init functions

which I accomplished via AccelClass extension to user mode, current_accel(), and class lookup.

If MODULE_INIT_ACCEL_CPU remains an option, where would you like to see the call so that it is not "in the middle"?

It is interesting for me to try to discern which meaning you folks give to MODULE_INIT.

Keep in mind, I will experiment with Eduardo's option of "one accel_init() to rule them all", without MODULE_INIT_ACCEL_CPU,
so I am not focused on using this no matter what.

Ciao,

Claudio




^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 20:13   ` Paolo Bonzini
  2020-11-24 21:31     ` Eduardo Habkost
@ 2020-11-25  9:24     ` Claudio Fontana
  2020-11-26 14:42     ` Claudio Fontana
  2 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-25  9:24 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli, haxm-team,
	Cameron Esfahani, Anthony Perard, Bruce Rogers, Olaf Hering,
	Colin Xu

On 11/24/20 9:13 PM, Paolo Bonzini wrote:
> On 24/11/20 17:22, Claudio Fontana wrote:
>> +static void x86_cpu_accel_init(void)
>>  {
>> -    X86CPUAccelClass *acc;
>> +    const char *ac_name;
>> +    ObjectClass *ac;
>> +    char *xac_name;
>> +    ObjectClass *xac;
>>  
>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>> -    g_assert(acc != NULL);
>> +    ac = object_get_class(OBJECT(current_accel()));
>> +    g_assert(ac != NULL);
>> +    ac_name = object_class_get_name(ac);
>> +    g_assert(ac_name != NULL);
>>  
>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>> +    xac = object_class_by_name(xac_name);
>> +    g_free(xac_name);
>> +
>> +    if (xac) {
>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>> +    }
>>  }
>> +
>> +accel_cpu_init(x86_cpu_accel_init);
> 
> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd 
> rather make them functions in CPUClass (which you find and call via 
> CPU_RESOLVING_TYPE) and AccelClass respectively.
> 
> Paolo
> 
> 

I don't expect others (actually I do, but it's going to be one additional call per target).
So based on RFCv5, I would see additional calls to accel_cpu_init for target/arm/cpu.c, target/s390x/cpu.c in patches to come.

I'll look into this.

Thanks,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 21:31     ` Eduardo Habkost
@ 2020-11-25  9:26       ` Claudio Fontana
  2020-11-26 10:57       ` Claudio Fontana
  1 sibling, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-25  9:26 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Cameron Esfahani, Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Emilio G . Cota,
	haxm-team, Colin Xu, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Wenchao Wang

On 11/24/20 10:31 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
>> On 24/11/20 17:22, Claudio Fontana wrote:
>>> +static void x86_cpu_accel_init(void)
>>>  {
>>> -    X86CPUAccelClass *acc;
>>> +    const char *ac_name;
>>> +    ObjectClass *ac;
>>> +    char *xac_name;
>>> +    ObjectClass *xac;
>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>>> -    g_assert(acc != NULL);
>>> +    ac = object_get_class(OBJECT(current_accel()));
>>> +    g_assert(ac != NULL);
>>> +    ac_name = object_class_get_name(ac);
>>> +    g_assert(ac_name != NULL);
>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>>> +    xac = object_class_by_name(xac_name);
>>> +    g_free(xac_name);
>>> +
>>> +    if (xac) {
>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>>> +    }
>>>  }
>>> +
>>> +accel_cpu_init(x86_cpu_accel_init);
>>
>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
>> rather make them functions in CPUClass (which you find and call via
>> CPU_RESOLVING_TYPE) and AccelClass respectively.
> 
> Making x86_cpu_accel_init() be a CPUClass method sounds like a
> good idea.  This way we won't need a arch_cpu_accel_init() stub
> for non-x86.


I really don't like stubs, and trying to link the proper ones for each of the targets we need to build.

It screams "this hasn't been refactored properly yet - sorry!"

If we could avoid them it would be a clear benefit from my perspective.


> 
> accel.c can't use cpu.h, correct?  We can add a:
> 
>   CPUClass *arch_base_cpu_type(void)
>   {
>       return object_class_by_name(CPU_RESOLVING_TYPE);
>   }
> 
> function to arch_init.c, to allow target-independent code call
> target-specific code.
> 

Ciao,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-25  9:21           ` Claudio Fontana
@ 2020-11-25  9:30             ` Paolo Bonzini
  2020-11-25 10:42               ` Claudio Fontana
  2020-11-26 12:45               ` Claudio Fontana
  0 siblings, 2 replies; 51+ messages in thread
From: Paolo Bonzini @ 2020-11-25  9:30 UTC (permalink / raw)
  To: Claudio Fontana, Eduardo Habkost
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Paul Durrant, Olaf Hering, Jason Wang, Marcelo Tosatti,
	Richard Henderson, qemu-devel, Cameron Esfahani, Bruce Rogers,
	Roman Bolshakov, Emilio G . Cota, haxm-team, Peter Xu,
	Anthony Perard, Sunil Muthuswamy, Dario Faggioli,
	Philippe Mathieu-Daudé,
	Colin Xu

On 25/11/20 10:21, Claudio Fontana wrote:
> Hi Paolo,
> 
> in RFC v5 , module init for ACCEL_CPU is not conditional anymore, right?
> But the fact that its behavior depends on current_accel() still disqualifies it?
> It is called right after the accelerator is chosen and initialized
> in RFC v5, this still is "in the middle of the machine creation sequence"?
Yes, machine creation basically starts after command line parsing, or 
perhaps even _with_ command line parsing.  Basically once the user can 
control the flow it is already too late.

> I am trying to find the actual things to fix, since when doing RFC
> v5  I tried to specifically address two points:
> 
> 1) no if () inside module init functions
> 
> 2) no proliferation of module init functions
> 
> which I accomplished via AccelClass extension to user mode, current_accel(), and class lookup.

Yes, the rest is great, I'm just not sure that MODULE_INIT_ACCEL_CPU is 
useful and if virtual functions on accel and CPU_RESOLVING_TYPE can 
achieve the same.

> If MODULE_INIT_ACCEL_CPU remains an option, where would you like to see the call so that it is not "in the middle"?

No later than the runstate_init() call, roughly.

Paolo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-24 20:34           ` Eduardo Habkost
@ 2020-11-25  9:32             ` Claudio Fontana
  2020-11-25 11:48               ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-25  9:32 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/24/20 9:34 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 08:39:33PM +0100, Claudio Fontana wrote:
>> On 11/24/20 8:27 PM, Eduardo Habkost wrote:
>>> On Tue, Nov 24, 2020 at 07:52:15PM +0100, Claudio Fontana wrote:
>>> [...]
>>>>>> +    }
>>>>>
>>>>> Additionally, if you call arch_cpu_accel_init() here, you won't
>>>>> need MODULE_INIT_ACCEL_CPU anymore.  The
>>>>>
>>>>>   module_call_init(MODULE_INIT_ACCEL_CPU)
>>>>>
>>>>> call with implicit dependencies on runtime state inside vl.c and
>>>>> *-user/main.c becomes a trivial:
>>>>>
>>>>>   accel_init(accel)
>>>>>
>>>>> call in accel_init_machine() and *-user:main().
>>>>
>>>>
>>>>
>>>> I do need a separate thing for the arch cpu accel specialization though,
>>>> without MODULE_INIT_ACCEL_CPU that link between all operations done at accel-chosen time is missing..
>>>>
>>>
>>> I think this is a key point we need to sort out.
>>>
>>> What do you mean by "link between all operations done at
>>> accel-chosen time" and why that's important?
>>
>>
>> For understanding by a reader that tries to figure this out,
>> (see the gid MODULE_INIT_ACCEL_CPU comment elsewhere in the thread).
> 
> Right, but how does the module_call_init(MODULE_INIT_ACCEL_CPU)
> indirection makes this easier to figure out than just looking at
> a accel_init() function that makes regular function calls?


I agree, if we accomplish a single accel_init() call that does everything (accelerator initialization and arch independent ops initialization and arch dependent specialization of the x86 cpu),
that would be the best outcome in my view also.


> 
> 
>>
>> And it could be that the high level plan to make accelerators fully dynamically loadable plugins in the future
>> also conditioned me to want to have a very clear demarcation line around the choice of the accelerator.
> 
> We have dynamically loadable modules for other QOM types,
> already, and they just use type_init().  I don't see why an extra
> module_init() type makes this easier.
> 
>>
>>
>>>
>>> accel_init_machine() has 2-3 lines of code with side effects.  It
>>> calls AccelClass.init_machine(), which may may have hundreds of
>>
>>
>> could we initialize also all arch-dependent stuff in here?
> 
> You can, if you use a wrapper + stub, like arch_cpu_accel_init().
> 

As mentioned elsewhere, I'll try to avoid stubs. One is too many I think in the codebase (well one is probably ok, but you get what I mean, I don't like their proliferation).

> 
>>
>>
>>> lines of code.  accel_setup_post() has one additional method
>>> call, which is triggered at a slightly different moment.
>>>
>>> You are using MODULE_INIT_ACCEL for 2 additional lines of code:
>>> - the cpus_register_accel() call
>>> - the x86_cpu_accel_init() call
>>>
>>> What makes those 2 lines of code so special, to make them deserve
>>> a completely new mechanism to trigger them, instead of using
>>> trivial function calls inside a accel_init() function?
>>>
>>
>> ...can we do also the x86_cpu_accel_init inside accel_init()?
>>
>>
>> In any case I'll try also the alternative, it would be nice if I could bring everything together under the same roof,
>> and easily discoverable, both the arch-specific steps that we need to do at accel-chosen time and the non-arch-specific steps.
> 
> One way to bring everything together under the same roof is to
> call everything inside a accel_init() function.

Will try!


> 
> 
>>
>> Hope this helps clarifying where I am coming from,
>> but I am open to have my mind changed, also trying the alternatives you propose here could help me see first hand how things play out.
> 
> Thanks!
> 

Thanks,

Ciao,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-25  9:30             ` Paolo Bonzini
@ 2020-11-25 10:42               ` Claudio Fontana
  2020-11-26 12:45               ` Claudio Fontana
  1 sibling, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-25 10:42 UTC (permalink / raw)
  To: Paolo Bonzini, Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Cameron Esfahani, Bruce Rogers, Roman Bolshakov, Emilio G . Cota,
	haxm-team, Wenchao Wang, Anthony Perard, Peter Xu,
	Dario Faggioli, Olaf Hering, Sunil Muthuswamy, Colin Xu

On 11/25/20 10:30 AM, Paolo Bonzini wrote:
> On 25/11/20 10:21, Claudio Fontana wrote:
>> Hi Paolo,
>>
>> in RFC v5 , module init for ACCEL_CPU is not conditional anymore, right?
>> But the fact that its behavior depends on current_accel() still disqualifies it?
>> It is called right after the accelerator is chosen and initialized
>> in RFC v5, this still is "in the middle of the machine creation sequence"?
> Yes, machine creation basically starts after command line parsing, or 
> perhaps even _with_ command line parsing.  Basically once the user can 
> control the flow it is already too late.
> 
>> I am trying to find the actual things to fix, since when doing RFC
>> v5  I tried to specifically address two points:
>>
>> 1) no if () inside module init functions
>>
>> 2) no proliferation of module init functions
>>
>> which I accomplished via AccelClass extension to user mode, current_accel(), and class lookup.
> 
> Yes, the rest is great, I'm just not sure that MODULE_INIT_ACCEL_CPU is 
> useful and if virtual functions on accel and CPU_RESOLVING_TYPE can 
> achieve the same.
> 
>> If MODULE_INIT_ACCEL_CPU remains an option, where would you like to see the call so that it is not "in the middle"?
> 
> No later than the runstate_init() call, roughly.
> 
> Paolo
> 
> 

Aha! Then that solves it, I don't think it is feasible to put it that early with the meaning I intended for it.

Thanks for clarifying this,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-25  9:32             ` Claudio Fontana
@ 2020-11-25 11:48               ` Claudio Fontana
  2020-11-25 14:51                 ` Eduardo Habkost
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-25 11:48 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/25/20 10:32 AM, Claudio Fontana wrote:
> On 11/24/20 9:34 PM, Eduardo Habkost wrote:
>> On Tue, Nov 24, 2020 at 08:39:33PM +0100, Claudio Fontana wrote:
>>> On 11/24/20 8:27 PM, Eduardo Habkost wrote:
>>>> On Tue, Nov 24, 2020 at 07:52:15PM +0100, Claudio Fontana wrote:
>>>> [...]
>>>>>>> +    }
>>>>>>
>>>>>> Additionally, if you call arch_cpu_accel_init() here, you won't
>>>>>> need MODULE_INIT_ACCEL_CPU anymore.  The
>>>>>>
>>>>>>   module_call_init(MODULE_INIT_ACCEL_CPU)
>>>>>>
>>>>>> call with implicit dependencies on runtime state inside vl.c and
>>>>>> *-user/main.c becomes a trivial:
>>>>>>
>>>>>>   accel_init(accel)
>>>>>>
>>>>>> call in accel_init_machine() and *-user:main().


On this one I see an issue:

the *-user_main() would still need an ac->machine_init() call to initialize tcg itself,
currently the accelerator initialization is put into ac->machine_init

(tcg_init, kvm_init, xen_init, etc).

Or are you proposing to move tcg initialization away from the current ->machine_init(),
into the new ac->init called by accel_init()?

This would make tcg even more different from the other accelerators.

Or are you proposing for all accelerators to separate the initialization of the accelerator itself
from the machine state input, leading to, for example, separating kvm-all.c kvm_init() into two
functions, one which takes the input from MachineState and puts it into the AccelState, and
another one which actually then initializes kvm proper? And same for all accels?

In my view we could still do in *-user main.c,

ac = ACCEL_GET_CLASS(current_accel())
ac->machine_init(NULL);
ac->init_cpu_interfaces(ac);

to solve this, or something like that, but also the option of fixing all accelerators to separate
the gathering of the input from the MachineState to the actual accelerator initialization is
a possibility to me.

Ciao,

Claudio


>>>>>
>>>>>
>>>>>
>>>>> I do need a separate thing for the arch cpu accel specialization though,
>>>>> without MODULE_INIT_ACCEL_CPU that link between all operations done at accel-chosen time is missing..
>>>>>
>>>>
>>>> I think this is a key point we need to sort out.
>>>>
>>>> What do you mean by "link between all operations done at
>>>> accel-chosen time" and why that's important?
>>>
>>>
>>> For understanding by a reader that tries to figure this out,
>>> (see the gid MODULE_INIT_ACCEL_CPU comment elsewhere in the thread).
>>
>> Right, but how does the module_call_init(MODULE_INIT_ACCEL_CPU)
>> indirection makes this easier to figure out than just looking at
>> a accel_init() function that makes regular function calls?
> 
> 
> I agree, if we accomplish a single accel_init() call that does everything (accelerator initialization and arch independent ops initialization and arch dependent specialization of the x86 cpu),
> that would be the best outcome in my view also.
> 
> 
>>
>>
>>>
>>> And it could be that the high level plan to make accelerators fully dynamically loadable plugins in the future
>>> also conditioned me to want to have a very clear demarcation line around the choice of the accelerator.
>>
>> We have dynamically loadable modules for other QOM types,
>> already, and they just use type_init().  I don't see why an extra
>> module_init() type makes this easier.
>>
>>>
>>>
>>>>
>>>> accel_init_machine() has 2-3 lines of code with side effects.  It
>>>> calls AccelClass.init_machine(), which may may have hundreds of
>>>
>>>
>>> could we initialize also all arch-dependent stuff in here?
>>
>> You can, if you use a wrapper + stub, like arch_cpu_accel_init().
>>
> 
> As mentioned elsewhere, I'll try to avoid stubs. One is too many I think in the codebase (well one is probably ok, but you get what I mean, I don't like their proliferation).
> 
>>
>>>
>>>
>>>> lines of code.  accel_setup_post() has one additional method
>>>> call, which is triggered at a slightly different moment.
>>>>
>>>> You are using MODULE_INIT_ACCEL for 2 additional lines of code:
>>>> - the cpus_register_accel() call
>>>> - the x86_cpu_accel_init() call
>>>>
>>>> What makes those 2 lines of code so special, to make them deserve
>>>> a completely new mechanism to trigger them, instead of using
>>>> trivial function calls inside a accel_init() function?
>>>>
>>>
>>> ...can we do also the x86_cpu_accel_init inside accel_init()?
>>>
>>>
>>> In any case I'll try also the alternative, it would be nice if I could bring everything together under the same roof,
>>> and easily discoverable, both the arch-specific steps that we need to do at accel-chosen time and the non-arch-specific steps.
>>
>> One way to bring everything together under the same roof is to
>> call everything inside a accel_init() function.
> 
> Will try!
> 
> 
>>
>>
>>>
>>> Hope this helps clarifying where I am coming from,
>>> but I am open to have my mind changed, also trying the alternatives you propose here could help me see first hand how things play out.
>>
>> Thanks!
>>
> 
> Thanks,
> 
> Ciao,
> 
> Claudio
> 






^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 12/12] accel: centralize initialization of CpusAccelOps
  2020-11-25 11:48               ` Claudio Fontana
@ 2020-11-25 14:51                 ` Eduardo Habkost
  0 siblings, 0 replies; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-25 14:51 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Wed, Nov 25, 2020 at 12:48:22PM +0100, Claudio Fontana wrote:
> On 11/25/20 10:32 AM, Claudio Fontana wrote:
> > On 11/24/20 9:34 PM, Eduardo Habkost wrote:
> >> On Tue, Nov 24, 2020 at 08:39:33PM +0100, Claudio Fontana wrote:
> >>> On 11/24/20 8:27 PM, Eduardo Habkost wrote:
> >>>> On Tue, Nov 24, 2020 at 07:52:15PM +0100, Claudio Fontana wrote:
> >>>> [...]
> >>>>>>> +    }
> >>>>>>
> >>>>>> Additionally, if you call arch_cpu_accel_init() here, you won't
> >>>>>> need MODULE_INIT_ACCEL_CPU anymore.  The
> >>>>>>
> >>>>>>   module_call_init(MODULE_INIT_ACCEL_CPU)
> >>>>>>
> >>>>>> call with implicit dependencies on runtime state inside vl.c and
> >>>>>> *-user/main.c becomes a trivial:
> >>>>>>
> >>>>>>   accel_init(accel)
> >>>>>>
> >>>>>> call in accel_init_machine() and *-user:main().
> 
> 
> On this one I see an issue:
> 
> the *-user_main() would still need an ac->machine_init() call to initialize tcg itself,
> currently the accelerator initialization is put into ac->machine_init
> 
> (tcg_init, kvm_init, xen_init, etc).
> 
> Or are you proposing to move tcg initialization away from the current ->machine_init(),
> into the new ac->init called by accel_init()?

Yes.  Anything that requires MachineState (and is
softmmu-specific) would go to ->machine_init().  Anything that is
not softmmu-specific would go to ->init().

> 
> This would make tcg even more different from the other accelerators.

That's true, but isn't this only because TCG is the only one that
really needs it?

> 
> Or are you proposing for all accelerators to separate the initialization of the accelerator itself
> from the machine state input, leading to, for example, separating kvm-all.c kvm_init() into two
> functions, one which takes the input from MachineState and puts it into the AccelState, and
> another one which actually then initializes kvm proper? And same for all accels?

That would be possible (and maybe a good idea), but not necessary
to make it work.

> 
> In my view we could still do in *-user main.c,
> 
> ac = ACCEL_GET_CLASS(current_accel())
> ac->machine_init(NULL);
> ac->init_cpu_interfaces(ac);

That would work too.  I would implement it as an accel_init(NULL)
call, however, to avoid duplicating the code from
accel_init_machine().

Calling ->machine_init(NULL) is just a bit surprising because of
the name (calling machine_init() when there's no machine), and
because we know most accelerators will crash if getting a NULL
argument.

Anyway, the split between ->machine_init() and ->init() is just a
suggestion.  Keeping a single init method that accepts a NULL
MachineState* as argument is not my favourite option, but it
works.

Whatever you choose, my only ask is to document clearly the
expectations and requirements of the AccelClass methods you are
using.


> 
> to solve this, or something like that, but also the option of fixing all accelerators to separate
> the gathering of the input from the MachineState to the actual accelerator initialization is
> a possibility to me.
> 
> Ciao,
> 
> Claudio

Thank you very much for your patience!  I think we're going on
the right direction.

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 21:31     ` Eduardo Habkost
  2020-11-25  9:26       ` Claudio Fontana
@ 2020-11-26 10:57       ` Claudio Fontana
  2020-11-26 13:44         ` Eduardo Habkost
  1 sibling, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 10:57 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Cameron Esfahani, Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Emilio G . Cota,
	haxm-team, Colin Xu, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Wenchao Wang

On 11/24/20 10:31 PM, Eduardo Habkost wrote:
> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
>> On 24/11/20 17:22, Claudio Fontana wrote:
>>> +static void x86_cpu_accel_init(void)
>>>  {
>>> -    X86CPUAccelClass *acc;
>>> +    const char *ac_name;
>>> +    ObjectClass *ac;
>>> +    char *xac_name;
>>> +    ObjectClass *xac;
>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>>> -    g_assert(acc != NULL);
>>> +    ac = object_get_class(OBJECT(current_accel()));
>>> +    g_assert(ac != NULL);
>>> +    ac_name = object_class_get_name(ac);
>>> +    g_assert(ac_name != NULL);
>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>>> +    xac = object_class_by_name(xac_name);
>>> +    g_free(xac_name);
>>> +
>>> +    if (xac) {
>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>>> +    }
>>>  }
>>> +
>>> +accel_cpu_init(x86_cpu_accel_init);
>>
>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
>> rather make them functions in CPUClass (which you find and call via
>> CPU_RESOLVING_TYPE) and AccelClass respectively.
> 
> Making x86_cpu_accel_init() be a CPUClass method sounds like a
> good idea.  This way we won't need a arch_cpu_accel_init() stub
> for non-x86.
> 
> accel.c can't use cpu.h, correct?  We can add a:
> 
>   CPUClass *arch_base_cpu_type(void)
>   {
>       return object_class_by_name(CPU_RESOLVING_TYPE);
>   }
> 
> function to arch_init.c, to allow target-independent code call
> target-specific code.
> 

Hi Eduardo,

we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c

however, it would be very useful to put a:

#define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
#define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)

in an H file somewhere, for convenience for the programmer that has to implement subclasses in target/xxx/

But it is tough to find a header where CPU_RESOLVING_TYPE can be used.

We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?

So we'd end up having

accel-cpu

instead of the previous

accel-x86_64-cpu

on top of the hierarchy.

Ciao,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-24 16:22 ` [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
  2020-11-24 17:08   ` Eduardo Habkost
@ 2020-11-26 11:25   ` Philippe Mathieu-Daudé
  2020-11-26 12:03     ` Claudio Fontana
  1 sibling, 1 reply; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-26 11:25 UTC (permalink / raw)
  To: Claudio Fontana, Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Colin Xu, Anthony Perard,
	Bruce Rogers, Olaf Hering

On 11/24/20 5:22 PM, Claudio Fontana wrote:
> apply this to the registration of the cpus accel interfaces,
> 
> but this will be also in preparation for later use of this
> new module init step to also register per-accel x86 cpu type
> interfaces.
> 
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
>  accel/kvm/kvm-all.c         | 11 +++++++++--
>  accel/qtest/qtest.c         | 10 +++++++++-
>  accel/tcg/tcg-all.c         |  8 --------
>  accel/tcg/tcg-cpus.c        | 15 +++++++++++++++
>  accel/xen/xen-all.c         | 12 +++++++++---
>  include/qemu/module.h       |  2 ++
>  roms/qboot                  |  2 +-
>  softmmu/vl.c                |  6 ++++++
>  target/i386/hax/hax-all.c   | 12 +++++++++---
>  target/i386/hvf/hvf.c       | 10 +++++++++-
>  target/i386/whpx/whpx-all.c | 11 +++++++++--
>  11 files changed, 78 insertions(+), 21 deletions(-)
...
> diff --git a/roms/qboot b/roms/qboot
> index a5300c4949..cb1c49e0cf 160000
> --- a/roms/qboot
> +++ b/roms/qboot
> @@ -1 +1 @@
> -Subproject commit a5300c4949b8d4de2d34bedfaed66793f48ec948
> +Subproject commit cb1c49e0cfac99b9961d136ac0194da62c28cf64

Hmmm unrelated change I presume.



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-26 11:25   ` Philippe Mathieu-Daudé
@ 2020-11-26 12:03     ` Claudio Fontana
  0 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 12:03 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé,
	Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Colin Xu, Anthony Perard,
	Bruce Rogers, Olaf Hering

On 11/26/20 12:25 PM, Philippe Mathieu-Daudé wrote:
> On 11/24/20 5:22 PM, Claudio Fontana wrote:
>> apply this to the registration of the cpus accel interfaces,
>>
>> but this will be also in preparation for later use of this
>> new module init step to also register per-accel x86 cpu type
>> interfaces.
>>
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
>>  accel/kvm/kvm-all.c         | 11 +++++++++--
>>  accel/qtest/qtest.c         | 10 +++++++++-
>>  accel/tcg/tcg-all.c         |  8 --------
>>  accel/tcg/tcg-cpus.c        | 15 +++++++++++++++
>>  accel/xen/xen-all.c         | 12 +++++++++---
>>  include/qemu/module.h       |  2 ++
>>  roms/qboot                  |  2 +-
>>  softmmu/vl.c                |  6 ++++++
>>  target/i386/hax/hax-all.c   | 12 +++++++++---
>>  target/i386/hvf/hvf.c       | 10 +++++++++-
>>  target/i386/whpx/whpx-all.c | 11 +++++++++--
>>  11 files changed, 78 insertions(+), 21 deletions(-)
> ...
>> diff --git a/roms/qboot b/roms/qboot
>> index a5300c4949..cb1c49e0cf 160000
>> --- a/roms/qboot
>> +++ b/roms/qboot
>> @@ -1 +1 @@
>> -Subproject commit a5300c4949b8d4de2d34bedfaed66793f48ec948
>> +Subproject commit cb1c49e0cfac99b9961d136ac0194da62c28cf64
> 
> Hmmm unrelated change I presume.
> 

Hi Philippe, yes, clearly,

Thanks!

Ciao,

CLaudio



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-25  9:30             ` Paolo Bonzini
  2020-11-25 10:42               ` Claudio Fontana
@ 2020-11-26 12:45               ` Claudio Fontana
  1 sibling, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 12:45 UTC (permalink / raw)
  To: Paolo Bonzini, Eduardo Habkost
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Paul Durrant, Olaf Hering, Jason Wang, Marcelo Tosatti,
	Richard Henderson, qemu-devel, Cameron Esfahani, Bruce Rogers,
	Roman Bolshakov, Emilio G . Cota, haxm-team, Peter Xu,
	Anthony Perard, Sunil Muthuswamy, Dario Faggioli,
	Philippe Mathieu-Daudé,
	Colin Xu

On 11/25/20 10:30 AM, Paolo Bonzini wrote:
> On 25/11/20 10:21, Claudio Fontana wrote:
>> Hi Paolo,
>>
>> in RFC v5 , module init for ACCEL_CPU is not conditional anymore, right?
>> But the fact that its behavior depends on current_accel() still disqualifies it?
>> It is called right after the accelerator is chosen and initialized
>> in RFC v5, this still is "in the middle of the machine creation sequence"?
> Yes, machine creation basically starts after command line parsing, or 
> perhaps even _with_ command line parsing.  Basically once the user can 
> control the flow it is already too late.
> 
>> I am trying to find the actual things to fix, since when doing RFC
>> v5  I tried to specifically address two points:
>>
>> 1) no if () inside module init functions
>>
>> 2) no proliferation of module init functions
>>
>> which I accomplished via AccelClass extension to user mode, current_accel(), and class lookup.
> 
> Yes, the rest is great, I'm just not sure that MODULE_INIT_ACCEL_CPU is 
> useful and if virtual functions on accel and CPU_RESOLVING_TYPE can 
> achieve the same.
> 
>> If MODULE_INIT_ACCEL_CPU remains an option, where would you like to see the call so that it is not "in the middle"?
> 
> No later than the runstate_init() call, roughly.
> 
> Paolo
> 

Hi Paolo, not super-related to the context above,

during the implementation I am trying to offer

accel/accel-softmmu.c
accel/accel-common.c
accel/accel-user.c

But I don't seem able to use CONFIG_USER_ONLY in accel-common.c .

in accel/meson.build I am saying

 common_ss.add(files('accel-common.c'))
 softmmu_ss.add(files('accel-softmmu.c'))
 user_ss.add(files('accel-user.c'))

But this doesn't work, if I use common_ss. If I use specific_ss, it works.

So the term "common" is a bit overloaded, it means stuff for libcommon and such, not common between softmmu and user, right?

Ciao,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 10:57       ` Claudio Fontana
@ 2020-11-26 13:44         ` Eduardo Habkost
  2020-11-26 14:33           ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-26 13:44 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
> > On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
> >> On 24/11/20 17:22, Claudio Fontana wrote:
> >>> +static void x86_cpu_accel_init(void)
> >>>  {
> >>> -    X86CPUAccelClass *acc;
> >>> +    const char *ac_name;
> >>> +    ObjectClass *ac;
> >>> +    char *xac_name;
> >>> +    ObjectClass *xac;
> >>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> >>> -    g_assert(acc != NULL);
> >>> +    ac = object_get_class(OBJECT(current_accel()));
> >>> +    g_assert(ac != NULL);
> >>> +    ac_name = object_class_get_name(ac);
> >>> +    g_assert(ac_name != NULL);
> >>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> >>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> >>> +    xac = object_class_by_name(xac_name);
> >>> +    g_free(xac_name);
> >>> +
> >>> +    if (xac) {
> >>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> >>> +    }
> >>>  }
> >>> +
> >>> +accel_cpu_init(x86_cpu_accel_init);
> >>
> >> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
> >> rather make them functions in CPUClass (which you find and call via
> >> CPU_RESOLVING_TYPE) and AccelClass respectively.
> > 
> > Making x86_cpu_accel_init() be a CPUClass method sounds like a
> > good idea.  This way we won't need a arch_cpu_accel_init() stub
> > for non-x86.
> > 
> > accel.c can't use cpu.h, correct?  We can add a:
> > 
> >   CPUClass *arch_base_cpu_type(void)
> >   {
> >       return object_class_by_name(CPU_RESOLVING_TYPE);
> >   }
> > 
> > function to arch_init.c, to allow target-independent code call
> > target-specific code.
> > 
> 
> Hi Eduardo,
> 
> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c

That would work, too.

> 
> however, it would be very useful to put a:
> 
> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
> 
> in an H file somewhere, for convenience for the programmer that
> has to implement subclasses in target/xxx/

Absolutely.

> 
> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.

cpu-all.h?

> 
> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
> 
> So we'd end up having
> 
> accel-cpu
> 
> instead of the previous
> 
> accel-x86_64-cpu
> 
> on top of the hierarchy.

It seems OK to have a accel-cpu type at the top, but I don't see
why it solves the problem above.  What exactly would be the value
of `kvm_cpu_accel.name`?

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 13:44         ` Eduardo Habkost
@ 2020-11-26 14:33           ` Claudio Fontana
  2020-11-26 14:49             ` Eduardo Habkost
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 14:33 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/26/20 2:44 PM, Eduardo Habkost wrote:
> On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
>> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
>>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
>>>> On 24/11/20 17:22, Claudio Fontana wrote:
>>>>> +static void x86_cpu_accel_init(void)
>>>>>  {
>>>>> -    X86CPUAccelClass *acc;
>>>>> +    const char *ac_name;
>>>>> +    ObjectClass *ac;
>>>>> +    char *xac_name;
>>>>> +    ObjectClass *xac;
>>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>>>>> -    g_assert(acc != NULL);
>>>>> +    ac = object_get_class(OBJECT(current_accel()));
>>>>> +    g_assert(ac != NULL);
>>>>> +    ac_name = object_class_get_name(ac);
>>>>> +    g_assert(ac_name != NULL);
>>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>>>>> +    xac = object_class_by_name(xac_name);
>>>>> +    g_free(xac_name);
>>>>> +
>>>>> +    if (xac) {
>>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>>>>> +    }
>>>>>  }
>>>>> +
>>>>> +accel_cpu_init(x86_cpu_accel_init);
>>>>
>>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
>>>> rather make them functions in CPUClass (which you find and call via
>>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
>>>
>>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
>>> good idea.  This way we won't need a arch_cpu_accel_init() stub
>>> for non-x86.
>>>
>>> accel.c can't use cpu.h, correct?  We can add a:
>>>
>>>   CPUClass *arch_base_cpu_type(void)
>>>   {
>>>       return object_class_by_name(CPU_RESOLVING_TYPE);
>>>   }
>>>
>>> function to arch_init.c, to allow target-independent code call
>>> target-specific code.
>>>
>>
>> Hi Eduardo,
>>
>> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
> 
> That would work, too.
> 
>>
>> however, it would be very useful to put a:
>>
>> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
>> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
>>
>> in an H file somewhere, for convenience for the programmer that
>> has to implement subclasses in target/xxx/
> 
> Absolutely.
> 
>>
>> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
> 
> cpu-all.h?
> 
>>
>> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
>> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
>>
>> So we'd end up having
>>
>> accel-cpu
>>
>> instead of the previous
>>
>> accel-x86_64-cpu
>>
>> on top of the hierarchy.
> 
> It seems OK to have a accel-cpu type at the top, but I don't see
> why it solves the problem above.  What exactly would be the value
> of `kvm_cpu_accel.name`?
> 

It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).

But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?

Ciao,

Claudio




^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-24 20:13   ` Paolo Bonzini
  2020-11-24 21:31     ` Eduardo Habkost
  2020-11-25  9:24     ` Claudio Fontana
@ 2020-11-26 14:42     ` Claudio Fontana
  2 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 14:42 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé,
	Emilio G . Cota
  Cc: Laurent Vivier, Eduardo Habkost, Paul Durrant, Jason Wang,
	Marcelo Tosatti, qemu-devel, Peter Xu, Dario Faggioli,
	Cameron Esfahani, haxm-team, Colin Xu, Anthony Perard,
	Bruce Rogers, Olaf Hering

On 11/24/20 9:13 PM, Paolo Bonzini wrote:
> On 24/11/20 17:22, Claudio Fontana wrote:
>> +static void x86_cpu_accel_init(void)
>>  {
>> -    X86CPUAccelClass *acc;
>> +    const char *ac_name;
>> +    ObjectClass *ac;
>> +    char *xac_name;
>> +    ObjectClass *xac;
>>  
>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>> -    g_assert(acc != NULL);
>> +    ac = object_get_class(OBJECT(current_accel()));
>> +    g_assert(ac != NULL);
>> +    ac_name = object_class_get_name(ac);
>> +    g_assert(ac_name != NULL);
>>  
>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>> +    xac = object_class_by_name(xac_name);
>> +    g_free(xac_name);
>> +
>> +    if (xac) {
>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>> +    }
>>  }
>> +
>> +accel_cpu_init(x86_cpu_accel_init);
> 
> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd 
> rather make them functions in CPUClass (which you find and call via 
> CPU_RESOLVING_TYPE) and AccelClass respectively.
> 
> Paolo
> 

Hi Paolo,

this works well.

The only thing is, setting the ops in the AccelClass is basically useless:
we need to cache the AccelClass * in cpus.c anyway, so I ended up not putting it in AccelClass, as nobody ends up using it.

Maybe you could look for this in the series I am posting later today,

Ciao, thanks!

Claudio



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 14:33           ` Claudio Fontana
@ 2020-11-26 14:49             ` Eduardo Habkost
  2020-11-26 14:55               ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-26 14:49 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Thu, Nov 26, 2020 at 03:33:17PM +0100, Claudio Fontana wrote:
> On 11/26/20 2:44 PM, Eduardo Habkost wrote:
> > On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
> >> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
> >>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
> >>>> On 24/11/20 17:22, Claudio Fontana wrote:
> >>>>> +static void x86_cpu_accel_init(void)
> >>>>>  {
> >>>>> -    X86CPUAccelClass *acc;
> >>>>> +    const char *ac_name;
> >>>>> +    ObjectClass *ac;
> >>>>> +    char *xac_name;
> >>>>> +    ObjectClass *xac;
> >>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> >>>>> -    g_assert(acc != NULL);
> >>>>> +    ac = object_get_class(OBJECT(current_accel()));
> >>>>> +    g_assert(ac != NULL);
> >>>>> +    ac_name = object_class_get_name(ac);
> >>>>> +    g_assert(ac_name != NULL);
> >>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> >>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> >>>>> +    xac = object_class_by_name(xac_name);
> >>>>> +    g_free(xac_name);
> >>>>> +
> >>>>> +    if (xac) {
> >>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> >>>>> +    }
> >>>>>  }
> >>>>> +
> >>>>> +accel_cpu_init(x86_cpu_accel_init);
> >>>>
> >>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
> >>>> rather make them functions in CPUClass (which you find and call via
> >>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
> >>>
> >>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
> >>> good idea.  This way we won't need a arch_cpu_accel_init() stub
> >>> for non-x86.
> >>>
> >>> accel.c can't use cpu.h, correct?  We can add a:
> >>>
> >>>   CPUClass *arch_base_cpu_type(void)
> >>>   {
> >>>       return object_class_by_name(CPU_RESOLVING_TYPE);
> >>>   }
> >>>
> >>> function to arch_init.c, to allow target-independent code call
> >>> target-specific code.
> >>>
> >>
> >> Hi Eduardo,
> >>
> >> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
> > 
> > That would work, too.
> > 
> >>
> >> however, it would be very useful to put a:
> >>
> >> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
> >> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
> >>
> >> in an H file somewhere, for convenience for the programmer that
> >> has to implement subclasses in target/xxx/
> > 
> > Absolutely.
> > 
> >>
> >> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
> > 
> > cpu-all.h?
> > 
> >>
> >> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
> >> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
> >>
> >> So we'd end up having
> >>
> >> accel-cpu
> >>
> >> instead of the previous
> >>
> >> accel-x86_64-cpu
> >>
> >> on top of the hierarchy.
> > 
> > It seems OK to have a accel-cpu type at the top, but I don't see
> > why it solves the problem above.  What exactly would be the value
> > of `kvm_cpu_accel.name`?
> > 
> 
> It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
> resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).
> 
> But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?

I don't have a specific preference, but I still wonder how
exactly you would name the X86CPUAccel implemented at
target/i386/kvm, and how exactly you would look for it when
initializing the accelerator.

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 14:49             ` Eduardo Habkost
@ 2020-11-26 14:55               ` Claudio Fontana
  2020-11-26 15:14                 ` Eduardo Habkost
  2020-11-26 15:14                 ` Paolo Bonzini
  0 siblings, 2 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 14:55 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/26/20 3:49 PM, Eduardo Habkost wrote:
> On Thu, Nov 26, 2020 at 03:33:17PM +0100, Claudio Fontana wrote:
>> On 11/26/20 2:44 PM, Eduardo Habkost wrote:
>>> On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
>>>> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
>>>>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
>>>>>> On 24/11/20 17:22, Claudio Fontana wrote:
>>>>>>> +static void x86_cpu_accel_init(void)
>>>>>>>  {
>>>>>>> -    X86CPUAccelClass *acc;
>>>>>>> +    const char *ac_name;
>>>>>>> +    ObjectClass *ac;
>>>>>>> +    char *xac_name;
>>>>>>> +    ObjectClass *xac;
>>>>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>>>>>>> -    g_assert(acc != NULL);
>>>>>>> +    ac = object_get_class(OBJECT(current_accel()));
>>>>>>> +    g_assert(ac != NULL);
>>>>>>> +    ac_name = object_class_get_name(ac);
>>>>>>> +    g_assert(ac_name != NULL);
>>>>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>>>>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>>>>>>> +    xac = object_class_by_name(xac_name);
>>>>>>> +    g_free(xac_name);
>>>>>>> +
>>>>>>> +    if (xac) {
>>>>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>>>>>>> +    }
>>>>>>>  }
>>>>>>> +
>>>>>>> +accel_cpu_init(x86_cpu_accel_init);
>>>>>>
>>>>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
>>>>>> rather make them functions in CPUClass (which you find and call via
>>>>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
>>>>>
>>>>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
>>>>> good idea.  This way we won't need a arch_cpu_accel_init() stub
>>>>> for non-x86.
>>>>>
>>>>> accel.c can't use cpu.h, correct?  We can add a:
>>>>>
>>>>>   CPUClass *arch_base_cpu_type(void)
>>>>>   {
>>>>>       return object_class_by_name(CPU_RESOLVING_TYPE);
>>>>>   }
>>>>>
>>>>> function to arch_init.c, to allow target-independent code call
>>>>> target-specific code.
>>>>>
>>>>
>>>> Hi Eduardo,
>>>>
>>>> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
>>>
>>> That would work, too.
>>>
>>>>
>>>> however, it would be very useful to put a:
>>>>
>>>> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
>>>> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
>>>>
>>>> in an H file somewhere, for convenience for the programmer that
>>>> has to implement subclasses in target/xxx/
>>>
>>> Absolutely.
>>>
>>>>
>>>> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
>>>
>>> cpu-all.h?
>>>
>>>>
>>>> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
>>>> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
>>>>
>>>> So we'd end up having
>>>>
>>>> accel-cpu
>>>>
>>>> instead of the previous
>>>>
>>>> accel-x86_64-cpu
>>>>
>>>> on top of the hierarchy.
>>>
>>> It seems OK to have a accel-cpu type at the top, but I don't see
>>> why it solves the problem above.  What exactly would be the value
>>> of `kvm_cpu_accel.name`?
>>>
>>
>> It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
>> resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).
>>
>> But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?
> 
> I don't have a specific preference, but I still wonder how
> exactly you would name the X86CPUAccel implemented at
> target/i386/kvm, and how exactly you would look for it when
> initializing the accelerator.
> 

If we agree to use "accel-cpu" I would lookup "kvm-accel-cpu"
if we agree to use "accel-x86_64" aka "accel-" CPU_RESOLVING_TYPE, I would lookup "kvm-accel-" CPU_RESOLVING_TYPE

* initialize the arch-specific accel CpuClass interfaces */
static void accel_init_cpu_interfaces(AccelClass *ac, const char *cpu_type)
{
    const char *ac_name; /* AccelClass name */
    char *acc_name;      /* AccelCPUClass name */
    ObjectClass *acc;    /* AccelCPUClass */

    ac_name = object_class_get_name(OBJECT_CLASS(ac));
    g_assert(ac_name != NULL);

    acc_name = g_strdup_printf("%s-cpu", ac_name);
    acc = object_class_by_name(acc_name);
    g_free(acc_name);

    if (acc) {
        object_class_foreach(accel_init_cpu_interfaces_aux, cpu_type, false, acc);
    }
}

Ciao,

CLaudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 14:55               ` Claudio Fontana
@ 2020-11-26 15:14                 ` Eduardo Habkost
  2020-11-26 15:34                   ` Claudio Fontana
  2020-11-26 15:14                 ` Paolo Bonzini
  1 sibling, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-26 15:14 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Thu, Nov 26, 2020 at 03:55:37PM +0100, Claudio Fontana wrote:
> On 11/26/20 3:49 PM, Eduardo Habkost wrote:
> > On Thu, Nov 26, 2020 at 03:33:17PM +0100, Claudio Fontana wrote:
> >> On 11/26/20 2:44 PM, Eduardo Habkost wrote:
> >>> On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
> >>>> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
> >>>>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
> >>>>>> On 24/11/20 17:22, Claudio Fontana wrote:
> >>>>>>> +static void x86_cpu_accel_init(void)
> >>>>>>>  {
> >>>>>>> -    X86CPUAccelClass *acc;
> >>>>>>> +    const char *ac_name;
> >>>>>>> +    ObjectClass *ac;
> >>>>>>> +    char *xac_name;
> >>>>>>> +    ObjectClass *xac;
> >>>>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> >>>>>>> -    g_assert(acc != NULL);
> >>>>>>> +    ac = object_get_class(OBJECT(current_accel()));
> >>>>>>> +    g_assert(ac != NULL);
> >>>>>>> +    ac_name = object_class_get_name(ac);
> >>>>>>> +    g_assert(ac_name != NULL);
> >>>>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> >>>>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> >>>>>>> +    xac = object_class_by_name(xac_name);
> >>>>>>> +    g_free(xac_name);
> >>>>>>> +
> >>>>>>> +    if (xac) {
> >>>>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> >>>>>>> +    }
> >>>>>>>  }
> >>>>>>> +
> >>>>>>> +accel_cpu_init(x86_cpu_accel_init);
> >>>>>>
> >>>>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
> >>>>>> rather make them functions in CPUClass (which you find and call via
> >>>>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
> >>>>>
> >>>>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
> >>>>> good idea.  This way we won't need a arch_cpu_accel_init() stub
> >>>>> for non-x86.
> >>>>>
> >>>>> accel.c can't use cpu.h, correct?  We can add a:
> >>>>>
> >>>>>   CPUClass *arch_base_cpu_type(void)
> >>>>>   {
> >>>>>       return object_class_by_name(CPU_RESOLVING_TYPE);
> >>>>>   }
> >>>>>
> >>>>> function to arch_init.c, to allow target-independent code call
> >>>>> target-specific code.
> >>>>>
> >>>>
> >>>> Hi Eduardo,
> >>>>
> >>>> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
> >>>
> >>> That would work, too.
> >>>
> >>>>
> >>>> however, it would be very useful to put a:
> >>>>
> >>>> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
> >>>> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
> >>>>
> >>>> in an H file somewhere, for convenience for the programmer that
> >>>> has to implement subclasses in target/xxx/
> >>>
> >>> Absolutely.
> >>>
> >>>>
> >>>> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
> >>>
> >>> cpu-all.h?
> >>>
> >>>>
> >>>> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
> >>>> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
> >>>>
> >>>> So we'd end up having
> >>>>
> >>>> accel-cpu
> >>>>
> >>>> instead of the previous
> >>>>
> >>>> accel-x86_64-cpu
> >>>>
> >>>> on top of the hierarchy.
> >>>
> >>> It seems OK to have a accel-cpu type at the top, but I don't see
> >>> why it solves the problem above.  What exactly would be the value
> >>> of `kvm_cpu_accel.name`?
> >>>
> >>
> >> It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
> >> resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).
> >>
> >> But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?
> > 
> > I don't have a specific preference, but I still wonder how
> > exactly you would name the X86CPUAccel implemented at
> > target/i386/kvm, and how exactly you would look for it when
> > initializing the accelerator.
> > 
> 
> If we agree to use "accel-cpu" I would lookup "kvm-accel-cpu"

The structure in target/i386/kvm is x86-specific and
kvm-specific.  If we name it "kvm-accel-cpu", how would you name
the equivalent structures at target/s390x/kvm, target/arm/kvm,
target/ppc/kvm?

The same question would apply to target/*/tcg*, and to other
accelerators.

> if we agree to use "accel-x86_64" aka "accel-" CPU_RESOLVING_TYPE, I would lookup "kvm-accel-" CPU_RESOLVING_TYPE
> 
> * initialize the arch-specific accel CpuClass interfaces */
> static void accel_init_cpu_interfaces(AccelClass *ac, const char *cpu_type)
> {
>     const char *ac_name; /* AccelClass name */
>     char *acc_name;      /* AccelCPUClass name */
>     ObjectClass *acc;    /* AccelCPUClass */
> 
>     ac_name = object_class_get_name(OBJECT_CLASS(ac));
>     g_assert(ac_name != NULL);
> 
>     acc_name = g_strdup_printf("%s-cpu", ac_name);
>     acc = object_class_by_name(acc_name);
>     g_free(acc_name);
> 
>     if (acc) {
>         object_class_foreach(accel_init_cpu_interfaces_aux, cpu_type, false, acc);
>     }
> }
> 
> Ciao,
> 
> CLaudio
> 

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 14:55               ` Claudio Fontana
  2020-11-26 15:14                 ` Eduardo Habkost
@ 2020-11-26 15:14                 ` Paolo Bonzini
  1 sibling, 0 replies; 51+ messages in thread
From: Paolo Bonzini @ 2020-11-26 15:14 UTC (permalink / raw)
  To: Claudio Fontana, Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Cameron Esfahani, Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Emilio G . Cota,
	haxm-team, Colin Xu, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Wenchao Wang

On 26/11/20 15:55, Claudio Fontana wrote:
> If we agree to use "accel-cpu" I would lookup "kvm-accel-cpu"
> if we agree to use "accel-x86_64" aka "accel-" CPU_RESOLVING_TYPE, I would lookup "kvm-accel-" CPU_RESOLVING_TYPE
> 
> * initialize the arch-specific accel CpuClass interfaces */
> static void accel_init_cpu_interfaces(AccelClass *ac, const char *cpu_type)
> {
>      const char *ac_name; /* AccelClass name */
>      char *acc_name;      /* AccelCPUClass name */
>      ObjectClass *acc;    /* AccelCPUClass */
> 
>      ac_name = object_class_get_name(OBJECT_CLASS(ac));
>      g_assert(ac_name != NULL);
> 
>      acc_name = g_strdup_printf("%s-cpu", ac_name);
>      acc = object_class_by_name(acc_name);
>      g_free(acc_name);
> 
>      if (acc) {
>          object_class_foreach(accel_init_cpu_interfaces_aux, cpu_type, false, acc);
>      }
> }

I would use the second; there's no reason to have allow only one CPU 
type, it's just a limitation of QEMU.

Paolo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 15:14                 ` Eduardo Habkost
@ 2020-11-26 15:34                   ` Claudio Fontana
  2020-11-26 15:48                     ` Eduardo Habkost
  0 siblings, 1 reply; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 15:34 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/26/20 4:14 PM, Eduardo Habkost wrote:
> On Thu, Nov 26, 2020 at 03:55:37PM +0100, Claudio Fontana wrote:
>> On 11/26/20 3:49 PM, Eduardo Habkost wrote:
>>> On Thu, Nov 26, 2020 at 03:33:17PM +0100, Claudio Fontana wrote:
>>>> On 11/26/20 2:44 PM, Eduardo Habkost wrote:
>>>>> On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
>>>>>> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
>>>>>>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
>>>>>>>> On 24/11/20 17:22, Claudio Fontana wrote:
>>>>>>>>> +static void x86_cpu_accel_init(void)
>>>>>>>>>  {
>>>>>>>>> -    X86CPUAccelClass *acc;
>>>>>>>>> +    const char *ac_name;
>>>>>>>>> +    ObjectClass *ac;
>>>>>>>>> +    char *xac_name;
>>>>>>>>> +    ObjectClass *xac;
>>>>>>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>>>>>>>>> -    g_assert(acc != NULL);
>>>>>>>>> +    ac = object_get_class(OBJECT(current_accel()));
>>>>>>>>> +    g_assert(ac != NULL);
>>>>>>>>> +    ac_name = object_class_get_name(ac);
>>>>>>>>> +    g_assert(ac_name != NULL);
>>>>>>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>>>>>>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>>>>>>>>> +    xac = object_class_by_name(xac_name);
>>>>>>>>> +    g_free(xac_name);
>>>>>>>>> +
>>>>>>>>> +    if (xac) {
>>>>>>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>>>>>>>>> +    }
>>>>>>>>>  }
>>>>>>>>> +
>>>>>>>>> +accel_cpu_init(x86_cpu_accel_init);
>>>>>>>>
>>>>>>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
>>>>>>>> rather make them functions in CPUClass (which you find and call via
>>>>>>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
>>>>>>>
>>>>>>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
>>>>>>> good idea.  This way we won't need a arch_cpu_accel_init() stub
>>>>>>> for non-x86.
>>>>>>>
>>>>>>> accel.c can't use cpu.h, correct?  We can add a:
>>>>>>>
>>>>>>>   CPUClass *arch_base_cpu_type(void)
>>>>>>>   {
>>>>>>>       return object_class_by_name(CPU_RESOLVING_TYPE);
>>>>>>>   }
>>>>>>>
>>>>>>> function to arch_init.c, to allow target-independent code call
>>>>>>> target-specific code.
>>>>>>>
>>>>>>
>>>>>> Hi Eduardo,
>>>>>>
>>>>>> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
>>>>>
>>>>> That would work, too.
>>>>>
>>>>>>
>>>>>> however, it would be very useful to put a:
>>>>>>
>>>>>> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
>>>>>> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
>>>>>>
>>>>>> in an H file somewhere, for convenience for the programmer that
>>>>>> has to implement subclasses in target/xxx/
>>>>>
>>>>> Absolutely.
>>>>>
>>>>>>
>>>>>> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
>>>>>
>>>>> cpu-all.h?
>>>>>
>>>>>>
>>>>>> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
>>>>>> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
>>>>>>
>>>>>> So we'd end up having
>>>>>>
>>>>>> accel-cpu
>>>>>>
>>>>>> instead of the previous
>>>>>>
>>>>>> accel-x86_64-cpu
>>>>>>
>>>>>> on top of the hierarchy.
>>>>>
>>>>> It seems OK to have a accel-cpu type at the top, but I don't see
>>>>> why it solves the problem above.  What exactly would be the value
>>>>> of `kvm_cpu_accel.name`?
>>>>>
>>>>
>>>> It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
>>>> resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).
>>>>
>>>> But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?
>>>
>>> I don't have a specific preference, but I still wonder how
>>> exactly you would name the X86CPUAccel implemented at
>>> target/i386/kvm, and how exactly you would look for it when
>>> initializing the accelerator.
>>>
>>
>> If we agree to use "accel-cpu" I would lookup "kvm-accel-cpu"
> 
> The structure in target/i386/kvm is x86-specific and
> kvm-specific.  If we name it "kvm-accel-cpu", how would you name
> the equivalent structures at target/s390x/kvm, target/arm/kvm,
> target/ppc/kvm?

The same way; only one of them would be compiled into the target binary, so the lookup would not collide in practice,
but I wonder whether we want separate names anyway.

Ciao,

Claudio

> 
> The same question would apply to target/*/tcg*, and to other
> accelerators.
> 
>> if we agree to use "accel-x86_64" aka "accel-" CPU_RESOLVING_TYPE, I would lookup "kvm-accel-" CPU_RESOLVING_TYPE
>>
>> * initialize the arch-specific accel CpuClass interfaces */
>> static void accel_init_cpu_interfaces(AccelClass *ac, const char *cpu_type)
>> {
>>     const char *ac_name; /* AccelClass name */
>>     char *acc_name;      /* AccelCPUClass name */
>>     ObjectClass *acc;    /* AccelCPUClass */
>>
>>     ac_name = object_class_get_name(OBJECT_CLASS(ac));
>>     g_assert(ac_name != NULL);
>>
>>     acc_name = g_strdup_printf("%s-cpu", ac_name);
>>     acc = object_class_by_name(acc_name);
>>     g_free(acc_name);
>>
>>     if (acc) {
>>         object_class_foreach(accel_init_cpu_interfaces_aux, cpu_type, false, acc);
>>     }
>> }
>>
>> Ciao,
>>
>> CLaudio
>>
> 



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 15:34                   ` Claudio Fontana
@ 2020-11-26 15:48                     ` Eduardo Habkost
  2020-11-26 15:49                       ` Claudio Fontana
  0 siblings, 1 reply; 51+ messages in thread
From: Eduardo Habkost @ 2020-11-26 15:48 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Thu, Nov 26, 2020 at 04:34:17PM +0100, Claudio Fontana wrote:
> On 11/26/20 4:14 PM, Eduardo Habkost wrote:
> > On Thu, Nov 26, 2020 at 03:55:37PM +0100, Claudio Fontana wrote:
> >> On 11/26/20 3:49 PM, Eduardo Habkost wrote:
> >>> On Thu, Nov 26, 2020 at 03:33:17PM +0100, Claudio Fontana wrote:
> >>>> On 11/26/20 2:44 PM, Eduardo Habkost wrote:
> >>>>> On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
> >>>>>> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
> >>>>>>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
> >>>>>>>> On 24/11/20 17:22, Claudio Fontana wrote:
> >>>>>>>>> +static void x86_cpu_accel_init(void)
> >>>>>>>>>  {
> >>>>>>>>> -    X86CPUAccelClass *acc;
> >>>>>>>>> +    const char *ac_name;
> >>>>>>>>> +    ObjectClass *ac;
> >>>>>>>>> +    char *xac_name;
> >>>>>>>>> +    ObjectClass *xac;
> >>>>>>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
> >>>>>>>>> -    g_assert(acc != NULL);
> >>>>>>>>> +    ac = object_get_class(OBJECT(current_accel()));
> >>>>>>>>> +    g_assert(ac != NULL);
> >>>>>>>>> +    ac_name = object_class_get_name(ac);
> >>>>>>>>> +    g_assert(ac_name != NULL);
> >>>>>>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
> >>>>>>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
> >>>>>>>>> +    xac = object_class_by_name(xac_name);
> >>>>>>>>> +    g_free(xac_name);
> >>>>>>>>> +
> >>>>>>>>> +    if (xac) {
> >>>>>>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
> >>>>>>>>> +    }
> >>>>>>>>>  }
> >>>>>>>>> +
> >>>>>>>>> +accel_cpu_init(x86_cpu_accel_init);
> >>>>>>>>
> >>>>>>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
> >>>>>>>> rather make them functions in CPUClass (which you find and call via
> >>>>>>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
> >>>>>>>
> >>>>>>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
> >>>>>>> good idea.  This way we won't need a arch_cpu_accel_init() stub
> >>>>>>> for non-x86.
> >>>>>>>
> >>>>>>> accel.c can't use cpu.h, correct?  We can add a:
> >>>>>>>
> >>>>>>>   CPUClass *arch_base_cpu_type(void)
> >>>>>>>   {
> >>>>>>>       return object_class_by_name(CPU_RESOLVING_TYPE);
> >>>>>>>   }
> >>>>>>>
> >>>>>>> function to arch_init.c, to allow target-independent code call
> >>>>>>> target-specific code.
> >>>>>>>
> >>>>>>
> >>>>>> Hi Eduardo,
> >>>>>>
> >>>>>> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
> >>>>>
> >>>>> That would work, too.
> >>>>>
> >>>>>>
> >>>>>> however, it would be very useful to put a:
> >>>>>>
> >>>>>> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
> >>>>>> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
> >>>>>>
> >>>>>> in an H file somewhere, for convenience for the programmer that
> >>>>>> has to implement subclasses in target/xxx/
> >>>>>
> >>>>> Absolutely.
> >>>>>
> >>>>>>
> >>>>>> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
> >>>>>
> >>>>> cpu-all.h?
> >>>>>
> >>>>>>
> >>>>>> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
> >>>>>> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
> >>>>>>
> >>>>>> So we'd end up having
> >>>>>>
> >>>>>> accel-cpu
> >>>>>>
> >>>>>> instead of the previous
> >>>>>>
> >>>>>> accel-x86_64-cpu
> >>>>>>
> >>>>>> on top of the hierarchy.
> >>>>>
> >>>>> It seems OK to have a accel-cpu type at the top, but I don't see
> >>>>> why it solves the problem above.  What exactly would be the value
> >>>>> of `kvm_cpu_accel.name`?
> >>>>>
> >>>>
> >>>> It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
> >>>> resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).
> >>>>
> >>>> But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?
> >>>
> >>> I don't have a specific preference, but I still wonder how
> >>> exactly you would name the X86CPUAccel implemented at
> >>> target/i386/kvm, and how exactly you would look for it when
> >>> initializing the accelerator.
> >>>
> >>
> >> If we agree to use "accel-cpu" I would lookup "kvm-accel-cpu"
> > 
> > The structure in target/i386/kvm is x86-specific and
> > kvm-specific.  If we name it "kvm-accel-cpu", how would you name
> > the equivalent structures at target/s390x/kvm, target/arm/kvm,
> > target/ppc/kvm?
> 
> The same way; only one of them would be compiled into the target binary, so the lookup would not collide in practice,

That's not always going to be true.  Maybe for KVM it will, but
not necessarily for TCG.

> but I wonder whether we want separate names anyway.

I believe we do.  Avoiding duplicate QOM type names is a good
idea in either case.

-- 
Eduardo



^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces
  2020-11-26 15:48                     ` Eduardo Habkost
@ 2020-11-26 15:49                       ` Claudio Fontana
  0 siblings, 0 replies; 51+ messages in thread
From: Claudio Fontana @ 2020-11-26 15:49 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Olaf Hering, Stefano Stabellini, Bruce Rogers,
	Emilio G . Cota, Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Richard Henderson, Cameron Esfahani,
	Dario Faggioli, Roman Bolshakov, Sunil Muthuswamy,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On 11/26/20 4:48 PM, Eduardo Habkost wrote:
> On Thu, Nov 26, 2020 at 04:34:17PM +0100, Claudio Fontana wrote:
>> On 11/26/20 4:14 PM, Eduardo Habkost wrote:
>>> On Thu, Nov 26, 2020 at 03:55:37PM +0100, Claudio Fontana wrote:
>>>> On 11/26/20 3:49 PM, Eduardo Habkost wrote:
>>>>> On Thu, Nov 26, 2020 at 03:33:17PM +0100, Claudio Fontana wrote:
>>>>>> On 11/26/20 2:44 PM, Eduardo Habkost wrote:
>>>>>>> On Thu, Nov 26, 2020 at 11:57:28AM +0100, Claudio Fontana wrote:
>>>>>>>> On 11/24/20 10:31 PM, Eduardo Habkost wrote:
>>>>>>>>> On Tue, Nov 24, 2020 at 09:13:13PM +0100, Paolo Bonzini wrote:
>>>>>>>>>> On 24/11/20 17:22, Claudio Fontana wrote:
>>>>>>>>>>> +static void x86_cpu_accel_init(void)
>>>>>>>>>>>  {
>>>>>>>>>>> -    X86CPUAccelClass *acc;
>>>>>>>>>>> +    const char *ac_name;
>>>>>>>>>>> +    ObjectClass *ac;
>>>>>>>>>>> +    char *xac_name;
>>>>>>>>>>> +    ObjectClass *xac;
>>>>>>>>>>> -    acc = X86_CPU_ACCEL_CLASS(object_class_by_name(accel_name));
>>>>>>>>>>> -    g_assert(acc != NULL);
>>>>>>>>>>> +    ac = object_get_class(OBJECT(current_accel()));
>>>>>>>>>>> +    g_assert(ac != NULL);
>>>>>>>>>>> +    ac_name = object_class_get_name(ac);
>>>>>>>>>>> +    g_assert(ac_name != NULL);
>>>>>>>>>>> -    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &acc);
>>>>>>>>>>> +    xac_name = g_strdup_printf("%s-%s", ac_name, TYPE_X86_CPU);
>>>>>>>>>>> +    xac = object_class_by_name(xac_name);
>>>>>>>>>>> +    g_free(xac_name);
>>>>>>>>>>> +
>>>>>>>>>>> +    if (xac) {
>>>>>>>>>>> +        object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, xac);
>>>>>>>>>>> +    }
>>>>>>>>>>>  }
>>>>>>>>>>> +
>>>>>>>>>>> +accel_cpu_init(x86_cpu_accel_init);
>>>>>>>>>>
>>>>>>>>>> If this and cpus_accel_ops_init are the only call to accel_cpu_init, I'd
>>>>>>>>>> rather make them functions in CPUClass (which you find and call via
>>>>>>>>>> CPU_RESOLVING_TYPE) and AccelClass respectively.
>>>>>>>>>
>>>>>>>>> Making x86_cpu_accel_init() be a CPUClass method sounds like a
>>>>>>>>> good idea.  This way we won't need a arch_cpu_accel_init() stub
>>>>>>>>> for non-x86.
>>>>>>>>>
>>>>>>>>> accel.c can't use cpu.h, correct?  We can add a:
>>>>>>>>>
>>>>>>>>>   CPUClass *arch_base_cpu_type(void)
>>>>>>>>>   {
>>>>>>>>>       return object_class_by_name(CPU_RESOLVING_TYPE);
>>>>>>>>>   }
>>>>>>>>>
>>>>>>>>> function to arch_init.c, to allow target-independent code call
>>>>>>>>> target-specific code.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Hi Eduardo,
>>>>>>>>
>>>>>>>> we can't use arch-init because it is softmmu only, but we could put this in $(top_srcdir)/cpu.c
>>>>>>>
>>>>>>> That would work, too.
>>>>>>>
>>>>>>>>
>>>>>>>> however, it would be very useful to put a:
>>>>>>>>
>>>>>>>> #define TYPE_ACCEL_CPU "accel-" CPU_RESOLVING_TYPE
>>>>>>>> #define ACCEL_CPU_NAME(name) (name "-" TYPE_ACCEL_CPU)
>>>>>>>>
>>>>>>>> in an H file somewhere, for convenience for the programmer that
>>>>>>>> has to implement subclasses in target/xxx/
>>>>>>>
>>>>>>> Absolutely.
>>>>>>>
>>>>>>>>
>>>>>>>> But it is tough to find a header where CPU_RESOLVING_TYPE can be used.
>>>>>>>
>>>>>>> cpu-all.h?
>>>>>>>
>>>>>>>>
>>>>>>>> We could I guess just use plain "cpu" instead of CPU_RESOLVING_TYPE,
>>>>>>>> maybe that would be acceptable too? The interface ends up in CPUClass, so maybe ok?
>>>>>>>>
>>>>>>>> So we'd end up having
>>>>>>>>
>>>>>>>> accel-cpu
>>>>>>>>
>>>>>>>> instead of the previous
>>>>>>>>
>>>>>>>> accel-x86_64-cpu
>>>>>>>>
>>>>>>>> on top of the hierarchy.
>>>>>>>
>>>>>>> It seems OK to have a accel-cpu type at the top, but I don't see
>>>>>>> why it solves the problem above.  What exactly would be the value
>>>>>>> of `kvm_cpu_accel.name`?
>>>>>>>
>>>>>>
>>>>>> It does solve the problem, because we can put then all AccelOpsClass and AccelCPUClass stuff in accel.h,
>>>>>> resolve everything in accel/accel-*.c, and make a generic solution fairly self-contained (already tested, will post soonish).
>>>>>>
>>>>>> But I'll try cpu-all.h if it's preferred to have accel-x86_64-cpu, accel-XXX-cpu on top, I wonder what the preference would be?
>>>>>
>>>>> I don't have a specific preference, but I still wonder how
>>>>> exactly you would name the X86CPUAccel implemented at
>>>>> target/i386/kvm, and how exactly you would look for it when
>>>>> initializing the accelerator.
>>>>>
>>>>
>>>> If we agree to use "accel-cpu" I would lookup "kvm-accel-cpu"
>>>
>>> The structure in target/i386/kvm is x86-specific and
>>> kvm-specific.  If we name it "kvm-accel-cpu", how would you name
>>> the equivalent structures at target/s390x/kvm, target/arm/kvm,
>>> target/ppc/kvm?
>>
>> The same way; only one of them would be compiled into the target binary, so the lookup would not collide in practice,
> 
> That's not always going to be true.  Maybe for KVM it will, but
> not necessarily for TCG.
> 
>> but I wonder whether we want separate names anyway.
> 
> I believe we do.  Avoiding duplicate QOM type names is a good
> idea in either case.
> 

Ok will try, for now I CPU_RESOLVING_TYPE is not playing nice with my attempts..

Ciao,

Claudio


^ permalink raw reply	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2020-11-26 16:04 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-24 16:21 [RFC v5 00/12] i386 cleanup Claudio Fontana
2020-11-24 16:21 ` [RFC v5 01/12] i386: move kvm accel files into kvm/ Claudio Fontana
2020-11-24 16:22 ` [RFC v5 02/12] i386: move whpx accel files into whpx/ Claudio Fontana
2020-11-24 16:22 ` [RFC v5 03/12] i386: move hax accel files into hax/ Claudio Fontana
2020-11-24 16:22 ` [RFC v5 04/12] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
2020-11-24 16:22 ` [RFC v5 05/12] i386: move TCG accel files into tcg/ Claudio Fontana
2020-11-24 16:22 ` [RFC v5 06/12] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
2020-11-24 16:22 ` [RFC v5 07/12] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
2020-11-24 16:22 ` [RFC v5 08/12] accel: extend AccelState and AccelClass to user-mode Claudio Fontana
2020-11-24 17:56   ` Eduardo Habkost
2020-11-24 18:16     ` Claudio Fontana
2020-11-24 16:22 ` [RFC v5 09/12] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
2020-11-24 17:08   ` Eduardo Habkost
2020-11-24 18:29     ` Claudio Fontana
2020-11-24 19:08       ` Eduardo Habkost
2020-11-24 20:01         ` Paolo Bonzini
2020-11-25  9:21           ` Claudio Fontana
2020-11-25  9:30             ` Paolo Bonzini
2020-11-25 10:42               ` Claudio Fontana
2020-11-26 12:45               ` Claudio Fontana
2020-11-26 11:25   ` Philippe Mathieu-Daudé
2020-11-26 12:03     ` Claudio Fontana
2020-11-24 16:22 ` [RFC v5 10/12] i386: split cpu accelerators from cpu.c Claudio Fontana
2020-11-24 16:22 ` [RFC v5 11/12] i386: centralize initialization of cpu accel interfaces Claudio Fontana
2020-11-24 16:59   ` Eduardo Habkost
2020-11-24 18:38     ` Claudio Fontana
2020-11-24 20:13   ` Paolo Bonzini
2020-11-24 21:31     ` Eduardo Habkost
2020-11-25  9:26       ` Claudio Fontana
2020-11-26 10:57       ` Claudio Fontana
2020-11-26 13:44         ` Eduardo Habkost
2020-11-26 14:33           ` Claudio Fontana
2020-11-26 14:49             ` Eduardo Habkost
2020-11-26 14:55               ` Claudio Fontana
2020-11-26 15:14                 ` Eduardo Habkost
2020-11-26 15:34                   ` Claudio Fontana
2020-11-26 15:48                     ` Eduardo Habkost
2020-11-26 15:49                       ` Claudio Fontana
2020-11-26 15:14                 ` Paolo Bonzini
2020-11-25  9:24     ` Claudio Fontana
2020-11-26 14:42     ` Claudio Fontana
2020-11-24 16:22 ` [RFC v5 12/12] accel: centralize initialization of CpusAccelOps Claudio Fontana
2020-11-24 17:48   ` Eduardo Habkost
2020-11-24 18:52     ` Claudio Fontana
2020-11-24 19:27       ` Eduardo Habkost
2020-11-24 19:39         ` Claudio Fontana
2020-11-24 20:34           ` Eduardo Habkost
2020-11-25  9:32             ` Claudio Fontana
2020-11-25 11:48               ` Claudio Fontana
2020-11-25 14:51                 ` Eduardo Habkost
2020-11-24 20:14 ` [RFC v5 00/12] i386 cleanup Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.