All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v1 00/10] i386 cleanup
@ 2020-11-09 17:27 Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 01/10] i386: move kvm accel files into accel/kvm/ Claudio Fontana
                   ` (10 more replies)
  0 siblings, 11 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

Hi all,

this is very much a RFC, I have started to look at the i386
target dir and how to start refactoring and splitting up
things better, moving more and more of the code to
accelerator-specific parts that are conditionally compiled.

In this RFC I start by moving all i386-specific accelerators into
target/i386/accel/, away from the main target directory,

then I go on and strip away all the cpu dump code out of helper.c
into a new file. There is a large amount of checkpatch warnings
and errors, but this is due to the copy paste of the old code,
we might need to clean up the state of the dump code in a later
change if necessary.

After that I take out tcg-specific stuff from cpu.h and from
helper.c and put it in helper-tcg.h and in a new tcg-cpu module,
(that will be renamed later in the series as its role changes).

After this I considered and implemented a few options,
but after some initial evaluation I concluded that a good idea
could possibly be to introduce a new MODULE_INIT phase,

MODULE_INIT_ACCEL_CPU

that I could use to put all existing cpus accel interface
initializations,
and that I could also use to put all accelerator specific
cpu module registrations, deferring the usual registration
at MODULE_INIT_QOM time.
This deferring allows to make all x86 cpu models children
of an accel-specific cpu type, in turn having as parent
the generic TYPE_X86_CPU.

There are for sure other options out there, so let me know if
this way seems promising, or if you have other ideas on how
to proceed here, especially in the last 3 patches..

Motivation and higher level steps:

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

Thank you for your comments,

Ciao,

Claudio

Claudio Fontana (10):
  i386: move kvm accel files into accel/kvm/
  i386: move whpx accel files to accel/whpx/
  i386: move hax accel files to accel/hax/
  i386: move hvf accel files into accel/hvf/
  i386: move TCG accel files into accel/tcg/
  i386: move cpu dump out of helper.c into cpu-dump.c
  i386: move TCG cpu class initialization out of helper.c
  module: introduce MODULE_INIT_ACCEL_CPU
  i386: split cpu.c and defer x86 models registration
  module: add priority to module_init

 MAINTAINERS                                 |  12 +-
 accel/kvm/kvm-all.c                         |  11 +-
 accel/qtest/qtest.c                         |  10 +-
 accel/tcg/tcg-all.c                         |  11 +-
 accel/xen/xen-all.c                         |  12 +-
 bsd-user/main.c                             |   4 +
 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/qemu/module.h                       |  17 +
 linux-user/main.c                           |  10 +-
 meson.build                                 |   1 +
 softmmu/vl.c                                |   6 +
 target/i386/{ => accel/hax}/hax-all.c       |  12 +-
 target/i386/{ => accel/hax}/hax-cpus.c      |   0
 target/i386/{ => accel/hax}/hax-cpus.h      |   0
 target/i386/{ => accel/hax}/hax-i386.h      |   6 +-
 target/i386/{ => accel/hax}/hax-interface.h |   0
 target/i386/{ => accel/hax}/hax-mem.c       |   0
 target/i386/{ => accel/hax}/hax-posix.c     |   0
 target/i386/{ => accel/hax}/hax-posix.h     |   0
 target/i386/{ => accel/hax}/hax-windows.c   |   0
 target/i386/{ => accel/hax}/hax-windows.h   |   0
 target/i386/accel/hax/meson.build           |   7 +
 target/i386/{ => accel}/hvf/README.md       |   0
 target/i386/accel/hvf/hvf-cpu-type.c        |  78 +++
 target/i386/{ => accel}/hvf/hvf-cpus.c      |   0
 target/i386/{ => accel}/hvf/hvf-cpus.h      |   0
 target/i386/{ => accel}/hvf/hvf-i386.h      |   0
 target/i386/{ => accel}/hvf/hvf.c           |  10 +-
 target/i386/{ => accel}/hvf/meson.build     |   1 +
 target/i386/{ => accel}/hvf/panic.h         |   0
 target/i386/{ => accel}/hvf/vmcs.h          |   0
 target/i386/{ => accel}/hvf/vmx.h           |   0
 target/i386/{ => accel}/hvf/x86.c           |   0
 target/i386/{ => accel}/hvf/x86.h           |   0
 target/i386/{ => accel}/hvf/x86_cpuid.c     |   0
 target/i386/{ => accel}/hvf/x86_decode.c    |   0
 target/i386/{ => accel}/hvf/x86_decode.h    |   0
 target/i386/{ => accel}/hvf/x86_descr.c     |   0
 target/i386/{ => accel}/hvf/x86_descr.h     |   0
 target/i386/{ => accel}/hvf/x86_emu.c       |   0
 target/i386/{ => accel}/hvf/x86_emu.h       |   0
 target/i386/{ => accel}/hvf/x86_flags.c     |   0
 target/i386/{ => accel}/hvf/x86_flags.h     |   0
 target/i386/{ => accel}/hvf/x86_mmu.c       |   0
 target/i386/{ => accel}/hvf/x86_mmu.h       |   0
 target/i386/{ => accel}/hvf/x86_task.c      |   0
 target/i386/{ => accel}/hvf/x86_task.h      |   0
 target/i386/{ => accel}/hvf/x86hvf.c        |   0
 target/i386/{ => accel}/hvf/x86hvf.h        |   0
 target/i386/{ => accel/kvm}/hyperv-proto.h  |   0
 target/i386/{ => accel/kvm}/hyperv-stub.c   |   0
 target/i386/{ => accel/kvm}/hyperv.c        |   0
 target/i386/{ => accel/kvm}/hyperv.h        |   0
 target/i386/accel/kvm/kvm-cpu-type.c        | 161 ++++++
 target/i386/accel/kvm/kvm-cpu-type.h        |  41 ++
 target/i386/{ => accel/kvm}/kvm-stub.c      |   0
 target/i386/{ => accel/kvm}/kvm.c           |   3 +-
 target/i386/{ => accel/kvm}/kvm_i386.h      |   0
 target/i386/accel/kvm/meson.build           |   8 +
 target/i386/accel/kvm/trace-events          |   7 +
 target/i386/accel/kvm/trace.h               |   1 +
 target/i386/{ => accel/tcg}/bpt_helper.c    |   1 +
 target/i386/{ => accel/tcg}/cc_helper.c     |   1 +
 target/i386/{ => accel/tcg}/excp_helper.c   |   1 +
 target/i386/{ => accel/tcg}/fpu_helper.c    |  33 +-
 target/i386/{ => accel/tcg}/int_helper.c    |   1 +
 target/i386/{ => accel/tcg}/mem_helper.c    |   1 +
 target/i386/accel/tcg/meson.build           |  14 +
 target/i386/{ => accel/tcg}/misc_helper.c   |   1 +
 target/i386/{ => accel/tcg}/mpx_helper.c    |   1 +
 target/i386/{ => accel/tcg}/seg_helper.c    |   1 +
 target/i386/{ => accel/tcg}/smm_helper.c    |   2 +
 target/i386/{ => accel/tcg}/svm_helper.c    |   1 +
 target/i386/accel/tcg/tcg-cpu-type.c        | 176 +++++++
 target/i386/accel/tcg/tcg-cpu-type.h        |  25 +
 target/i386/{ => accel/tcg}/tcg-stub.c      |   0
 target/i386/{ => accel/tcg}/translate.c     |   1 +
 target/i386/accel/whpx/meson.build          |   4 +
 target/i386/{ => accel/whpx}/whp-dispatch.h |   0
 target/i386/{ => accel/whpx}/whpx-all.c     |  11 +-
 target/i386/{ => accel/whpx}/whpx-cpus.c    |   0
 target/i386/{ => accel/whpx}/whpx-cpus.h    |   0
 target/i386/cpu-dump.c                      | 538 +++++++++++++++++++
 target/i386/cpu.c                           | 489 ++++--------------
 target/i386/cpu.h                           | 126 +----
 target/i386/helper-tcg.h                    | 112 ++++
 target/i386/helper.c                        | 539 +-------------------
 target/i386/host-cpu.c                      | 201 ++++++++
 target/i386/host-cpu.h                      |  21 +
 target/i386/machine.c                       |   4 +-
 target/i386/meson.build                     |  41 +-
 target/i386/trace-events                    |   6 -
 99 files changed, 1678 insertions(+), 1118 deletions(-)
 rename target/i386/{ => accel/hax}/hax-all.c (99%)
 rename target/i386/{ => accel/hax}/hax-cpus.c (100%)
 rename target/i386/{ => accel/hax}/hax-cpus.h (100%)
 rename target/i386/{ => accel/hax}/hax-i386.h (95%)
 rename target/i386/{ => accel/hax}/hax-interface.h (100%)
 rename target/i386/{ => accel/hax}/hax-mem.c (100%)
 rename target/i386/{ => accel/hax}/hax-posix.c (100%)
 rename target/i386/{ => accel/hax}/hax-posix.h (100%)
 rename target/i386/{ => accel/hax}/hax-windows.c (100%)
 rename target/i386/{ => accel/hax}/hax-windows.h (100%)
 create mode 100644 target/i386/accel/hax/meson.build
 rename target/i386/{ => accel}/hvf/README.md (100%)
 create mode 100644 target/i386/accel/hvf/hvf-cpu-type.c
 rename target/i386/{ => accel}/hvf/hvf-cpus.c (100%)
 rename target/i386/{ => accel}/hvf/hvf-cpus.h (100%)
 rename target/i386/{ => accel}/hvf/hvf-i386.h (100%)
 rename target/i386/{ => accel}/hvf/hvf.c (99%)
 rename target/i386/{ => accel}/hvf/meson.build (92%)
 rename target/i386/{ => accel}/hvf/panic.h (100%)
 rename target/i386/{ => accel}/hvf/vmcs.h (100%)
 rename target/i386/{ => accel}/hvf/vmx.h (100%)
 rename target/i386/{ => accel}/hvf/x86.c (100%)
 rename target/i386/{ => accel}/hvf/x86.h (100%)
 rename target/i386/{ => accel}/hvf/x86_cpuid.c (100%)
 rename target/i386/{ => accel}/hvf/x86_decode.c (100%)
 rename target/i386/{ => accel}/hvf/x86_decode.h (100%)
 rename target/i386/{ => accel}/hvf/x86_descr.c (100%)
 rename target/i386/{ => accel}/hvf/x86_descr.h (100%)
 rename target/i386/{ => accel}/hvf/x86_emu.c (100%)
 rename target/i386/{ => accel}/hvf/x86_emu.h (100%)
 rename target/i386/{ => accel}/hvf/x86_flags.c (100%)
 rename target/i386/{ => accel}/hvf/x86_flags.h (100%)
 rename target/i386/{ => accel}/hvf/x86_mmu.c (100%)
 rename target/i386/{ => accel}/hvf/x86_mmu.h (100%)
 rename target/i386/{ => accel}/hvf/x86_task.c (100%)
 rename target/i386/{ => accel}/hvf/x86_task.h (100%)
 rename target/i386/{ => accel}/hvf/x86hvf.c (100%)
 rename target/i386/{ => accel}/hvf/x86hvf.h (100%)
 rename target/i386/{ => accel/kvm}/hyperv-proto.h (100%)
 rename target/i386/{ => accel/kvm}/hyperv-stub.c (100%)
 rename target/i386/{ => accel/kvm}/hyperv.c (100%)
 rename target/i386/{ => accel/kvm}/hyperv.h (100%)
 create mode 100644 target/i386/accel/kvm/kvm-cpu-type.c
 create mode 100644 target/i386/accel/kvm/kvm-cpu-type.h
 rename target/i386/{ => accel/kvm}/kvm-stub.c (100%)
 rename target/i386/{ => accel/kvm}/kvm.c (99%)
 rename target/i386/{ => accel/kvm}/kvm_i386.h (100%)
 create mode 100644 target/i386/accel/kvm/meson.build
 create mode 100644 target/i386/accel/kvm/trace-events
 create mode 100644 target/i386/accel/kvm/trace.h
 rename target/i386/{ => accel/tcg}/bpt_helper.c (99%)
 rename target/i386/{ => accel/tcg}/cc_helper.c (99%)
 rename target/i386/{ => accel/tcg}/excp_helper.c (99%)
 rename target/i386/{ => accel/tcg}/fpu_helper.c (99%)
 rename target/i386/{ => accel/tcg}/int_helper.c (99%)
 rename target/i386/{ => accel/tcg}/mem_helper.c (99%)
 create mode 100644 target/i386/accel/tcg/meson.build
 rename target/i386/{ => accel/tcg}/misc_helper.c (99%)
 rename target/i386/{ => accel/tcg}/mpx_helper.c (99%)
 rename target/i386/{ => accel/tcg}/seg_helper.c (99%)
 rename target/i386/{ => accel/tcg}/smm_helper.c (99%)
 rename target/i386/{ => accel/tcg}/svm_helper.c (99%)
 create mode 100644 target/i386/accel/tcg/tcg-cpu-type.c
 create mode 100644 target/i386/accel/tcg/tcg-cpu-type.h
 rename target/i386/{ => accel/tcg}/tcg-stub.c (100%)
 rename target/i386/{ => accel/tcg}/translate.c (99%)
 create mode 100644 target/i386/accel/whpx/meson.build
 rename target/i386/{ => accel/whpx}/whp-dispatch.h (100%)
 rename target/i386/{ => accel/whpx}/whpx-all.c (99%)
 rename target/i386/{ => accel/whpx}/whpx-cpus.c (100%)
 rename target/i386/{ => accel/whpx}/whpx-cpus.h (100%)
 create mode 100644 target/i386/cpu-dump.c
 create mode 100644 target/i386/helper-tcg.h
 create mode 100644 target/i386/host-cpu.c
 create mode 100644 target/i386/host-cpu.h

-- 
2.26.2



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

* [RFC v1 01/10] i386: move kvm accel files into accel/kvm/
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 02/10] i386: move whpx accel files to accel/whpx/ Claudio Fontana
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, 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/{ => accel/kvm}/hyperv-proto.h | 0
 target/i386/{ => accel/kvm}/hyperv-stub.c  | 0
 target/i386/{ => accel/kvm}/hyperv.c       | 0
 target/i386/{ => accel/kvm}/hyperv.h       | 0
 target/i386/{ => accel/kvm}/kvm-stub.c     | 0
 target/i386/{ => accel/kvm}/kvm.c          | 0
 target/i386/{ => accel/kvm}/kvm_i386.h     | 0
 target/i386/accel/kvm/meson.build          | 3 +++
 target/i386/accel/kvm/trace-events         | 7 +++++++
 target/i386/accel/kvm/trace.h              | 1 +
 target/i386/cpu.c                          | 2 +-
 target/i386/cpu.h                          | 2 +-
 target/i386/helper.c                       | 2 +-
 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/{ => accel/kvm}/hyperv-proto.h (100%)
 rename target/i386/{ => accel/kvm}/hyperv-stub.c (100%)
 rename target/i386/{ => accel/kvm}/hyperv.c (100%)
 rename target/i386/{ => accel/kvm}/hyperv.h (100%)
 rename target/i386/{ => accel/kvm}/kvm-stub.c (100%)
 rename target/i386/{ => accel/kvm}/kvm.c (100%)
 rename target/i386/{ => accel/kvm}/kvm_i386.h (100%)
 create mode 100644 target/i386/accel/kvm/meson.build
 create mode 100644 target/i386/accel/kvm/trace-events
 create mode 100644 target/i386/accel/kvm/trace.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 63223e1183..2ce9b36c02 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -420,7 +420,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/accel/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..4d5ea83601 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 "accel/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..6a086173dc 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 "accel/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..a04593d80d 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 "accel/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..bd590f8ff2 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 "accel/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..63712fff0a 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 "accel/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 5e6c0023e0..f19b3f357b 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 "accel/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..71bc925ba5 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 "accel/kvm/kvm_i386.h"
 
 #define BIOS_FILENAME "bios.bin"
 
diff --git a/meson.build b/meson.build
index 39ac5cf6d8..eedf6d3f0f 100644
--- a/meson.build
+++ b/meson.build
@@ -1442,6 +1442,7 @@ trace_events_subdirs += [
   'target/arm',
   'target/hppa',
   'target/i386',
+  'target/i386/accel/kvm',
   'target/mips',
   'target/ppc',
   'target/riscv',
diff --git a/target/i386/hyperv-proto.h b/target/i386/accel/kvm/hyperv-proto.h
similarity index 100%
rename from target/i386/hyperv-proto.h
rename to target/i386/accel/kvm/hyperv-proto.h
diff --git a/target/i386/hyperv-stub.c b/target/i386/accel/kvm/hyperv-stub.c
similarity index 100%
rename from target/i386/hyperv-stub.c
rename to target/i386/accel/kvm/hyperv-stub.c
diff --git a/target/i386/hyperv.c b/target/i386/accel/kvm/hyperv.c
similarity index 100%
rename from target/i386/hyperv.c
rename to target/i386/accel/kvm/hyperv.c
diff --git a/target/i386/hyperv.h b/target/i386/accel/kvm/hyperv.h
similarity index 100%
rename from target/i386/hyperv.h
rename to target/i386/accel/kvm/hyperv.h
diff --git a/target/i386/kvm-stub.c b/target/i386/accel/kvm/kvm-stub.c
similarity index 100%
rename from target/i386/kvm-stub.c
rename to target/i386/accel/kvm/kvm-stub.c
diff --git a/target/i386/kvm.c b/target/i386/accel/kvm/kvm.c
similarity index 100%
rename from target/i386/kvm.c
rename to target/i386/accel/kvm/kvm.c
diff --git a/target/i386/kvm_i386.h b/target/i386/accel/kvm/kvm_i386.h
similarity index 100%
rename from target/i386/kvm_i386.h
rename to target/i386/accel/kvm/kvm_i386.h
diff --git a/target/i386/accel/kvm/meson.build b/target/i386/accel/kvm/meson.build
new file mode 100644
index 0000000000..1d66559187
--- /dev/null
+++ b/target/i386/accel/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/accel/kvm/trace-events b/target/i386/accel/kvm/trace-events
new file mode 100644
index 0000000000..b4e2d9e4ea
--- /dev/null
+++ b/target/i386/accel/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/accel/kvm/trace.h b/target/i386/accel/kvm/trace.h
new file mode 100644
index 0000000000..c82019982f
--- /dev/null
+++ b/target/i386/accel/kvm/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-target_i386_accel_kvm.h"
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 0d8606958e..b1a55a2b79 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 "accel/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 51c1d5f60a..d1f4c2fd2c 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 "accel/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 32fa21a7bb..25f2bf3137 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 "accel/kvm/kvm_i386.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/tcg.h"
 #include "sysemu/hw_accel.h"
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 233e46bb70..aef1fd4aa7 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 "accel/kvm/hyperv.h"
 #include "hw/i386/x86.h"
-#include "kvm_i386.h"
+#include "accel/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..629939b195 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('accel/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] 33+ messages in thread

* [RFC v1 02/10] i386: move whpx accel files to accel/whpx/
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 01/10] i386: move kvm accel files into accel/kvm/ Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 03/10] i386: move hax accel files to accel/hax/ Claudio Fontana
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

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

diff --git a/MAINTAINERS b/MAINTAINERS
index 2ce9b36c02..41b613b6a6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -446,10 +446,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/accel/whpx/
 F: include/sysemu/whpx.h
 
 Guest CPU Cores (Xen)
diff --git a/target/i386/accel/whpx/meson.build b/target/i386/accel/whpx/meson.build
new file mode 100644
index 0000000000..94a72c8efc
--- /dev/null
+++ b/target/i386/accel/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/accel/whpx/whp-dispatch.h
similarity index 100%
rename from target/i386/whp-dispatch.h
rename to target/i386/accel/whpx/whp-dispatch.h
diff --git a/target/i386/whpx-all.c b/target/i386/accel/whpx/whpx-all.c
similarity index 100%
rename from target/i386/whpx-all.c
rename to target/i386/accel/whpx/whpx-all.c
diff --git a/target/i386/whpx-cpus.c b/target/i386/accel/whpx/whpx-cpus.c
similarity index 100%
rename from target/i386/whpx-cpus.c
rename to target/i386/accel/whpx/whpx-cpus.c
diff --git a/target/i386/whpx-cpus.h b/target/i386/accel/whpx/whpx-cpus.h
similarity index 100%
rename from target/i386/whpx-cpus.h
rename to target/i386/accel/whpx/whpx-cpus.h
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 629939b195..6c43b7bfb0 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('accel/kvm')
+subdir('accel/whpx')
 subdir('hvf')
 
 target_arch += {'i386': i386_ss}
-- 
2.26.2



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

* [RFC v1 03/10] i386: move hax accel files to accel/hax/
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 01/10] i386: move kvm accel files into accel/kvm/ Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 02/10] i386: move whpx accel files to accel/whpx/ Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 04/10] i386: move hvf accel files into accel/hvf/ Claudio Fontana
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

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

diff --git a/MAINTAINERS b/MAINTAINERS
index 41b613b6a6..6dabd972c9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -486,7 +486,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/accel/hax/
 
 Hosts
 -----
diff --git a/target/i386/hax-all.c b/target/i386/accel/hax/hax-all.c
similarity index 100%
rename from target/i386/hax-all.c
rename to target/i386/accel/hax/hax-all.c
diff --git a/target/i386/hax-cpus.c b/target/i386/accel/hax/hax-cpus.c
similarity index 100%
rename from target/i386/hax-cpus.c
rename to target/i386/accel/hax/hax-cpus.c
diff --git a/target/i386/hax-cpus.h b/target/i386/accel/hax/hax-cpus.h
similarity index 100%
rename from target/i386/hax-cpus.h
rename to target/i386/accel/hax/hax-cpus.h
diff --git a/target/i386/hax-i386.h b/target/i386/accel/hax/hax-i386.h
similarity index 95%
rename from target/i386/hax-i386.h
rename to target/i386/accel/hax/hax-i386.h
index 48c4abe14e..efbb346238 100644
--- a/target/i386/hax-i386.h
+++ b/target/i386/accel/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/accel/hax/hax-interface.h
similarity index 100%
rename from target/i386/hax-interface.h
rename to target/i386/accel/hax/hax-interface.h
diff --git a/target/i386/hax-mem.c b/target/i386/accel/hax/hax-mem.c
similarity index 100%
rename from target/i386/hax-mem.c
rename to target/i386/accel/hax/hax-mem.c
diff --git a/target/i386/hax-posix.c b/target/i386/accel/hax/hax-posix.c
similarity index 100%
rename from target/i386/hax-posix.c
rename to target/i386/accel/hax/hax-posix.c
diff --git a/target/i386/hax-posix.h b/target/i386/accel/hax/hax-posix.h
similarity index 100%
rename from target/i386/hax-posix.h
rename to target/i386/accel/hax/hax-posix.h
diff --git a/target/i386/hax-windows.c b/target/i386/accel/hax/hax-windows.c
similarity index 100%
rename from target/i386/hax-windows.c
rename to target/i386/accel/hax/hax-windows.c
diff --git a/target/i386/hax-windows.h b/target/i386/accel/hax/hax-windows.h
similarity index 100%
rename from target/i386/hax-windows.h
rename to target/i386/accel/hax/hax-windows.h
diff --git a/target/i386/accel/hax/meson.build b/target/i386/accel/hax/meson.build
new file mode 100644
index 0000000000..77ea431b30
--- /dev/null
+++ b/target/i386/accel/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 6c43b7bfb0..34ec93dbef 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('accel/kvm')
+subdir('accel/hax')
 subdir('accel/whpx')
 subdir('hvf')
 
-- 
2.26.2



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

* [RFC v1 04/10] i386: move hvf accel files into accel/hvf/
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (2 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 03/10] i386: move hax accel files to accel/hax/ Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 05/10] i386: move TCG accel files into accel/tcg/ Claudio Fontana
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                              | 3 +--
 target/i386/{ => accel}/hvf/README.md    | 0
 target/i386/{ => accel}/hvf/hvf-cpus.c   | 0
 target/i386/{ => accel}/hvf/hvf-cpus.h   | 0
 target/i386/{ => accel}/hvf/hvf-i386.h   | 0
 target/i386/{ => accel}/hvf/hvf.c        | 0
 target/i386/{ => accel}/hvf/meson.build  | 0
 target/i386/{ => accel}/hvf/panic.h      | 0
 target/i386/{ => accel}/hvf/vmcs.h       | 0
 target/i386/{ => accel}/hvf/vmx.h        | 0
 target/i386/{ => accel}/hvf/x86.c        | 0
 target/i386/{ => accel}/hvf/x86.h        | 0
 target/i386/{ => accel}/hvf/x86_cpuid.c  | 0
 target/i386/{ => accel}/hvf/x86_decode.c | 0
 target/i386/{ => accel}/hvf/x86_decode.h | 0
 target/i386/{ => accel}/hvf/x86_descr.c  | 0
 target/i386/{ => accel}/hvf/x86_descr.h  | 0
 target/i386/{ => accel}/hvf/x86_emu.c    | 0
 target/i386/{ => accel}/hvf/x86_emu.h    | 0
 target/i386/{ => accel}/hvf/x86_flags.c  | 0
 target/i386/{ => accel}/hvf/x86_flags.h  | 0
 target/i386/{ => accel}/hvf/x86_mmu.c    | 0
 target/i386/{ => accel}/hvf/x86_mmu.h    | 0
 target/i386/{ => accel}/hvf/x86_task.c   | 0
 target/i386/{ => accel}/hvf/x86_task.h   | 0
 target/i386/{ => accel}/hvf/x86hvf.c     | 0
 target/i386/{ => accel}/hvf/x86hvf.h     | 0
 target/i386/meson.build                  | 2 +-
 28 files changed, 2 insertions(+), 3 deletions(-)
 rename target/i386/{ => accel}/hvf/README.md (100%)
 rename target/i386/{ => accel}/hvf/hvf-cpus.c (100%)
 rename target/i386/{ => accel}/hvf/hvf-cpus.h (100%)
 rename target/i386/{ => accel}/hvf/hvf-i386.h (100%)
 rename target/i386/{ => accel}/hvf/hvf.c (100%)
 rename target/i386/{ => accel}/hvf/meson.build (100%)
 rename target/i386/{ => accel}/hvf/panic.h (100%)
 rename target/i386/{ => accel}/hvf/vmcs.h (100%)
 rename target/i386/{ => accel}/hvf/vmx.h (100%)
 rename target/i386/{ => accel}/hvf/x86.c (100%)
 rename target/i386/{ => accel}/hvf/x86.h (100%)
 rename target/i386/{ => accel}/hvf/x86_cpuid.c (100%)
 rename target/i386/{ => accel}/hvf/x86_decode.c (100%)
 rename target/i386/{ => accel}/hvf/x86_decode.h (100%)
 rename target/i386/{ => accel}/hvf/x86_descr.c (100%)
 rename target/i386/{ => accel}/hvf/x86_descr.h (100%)
 rename target/i386/{ => accel}/hvf/x86_emu.c (100%)
 rename target/i386/{ => accel}/hvf/x86_emu.h (100%)
 rename target/i386/{ => accel}/hvf/x86_flags.c (100%)
 rename target/i386/{ => accel}/hvf/x86_flags.h (100%)
 rename target/i386/{ => accel}/hvf/x86_mmu.c (100%)
 rename target/i386/{ => accel}/hvf/x86_mmu.h (100%)
 rename target/i386/{ => accel}/hvf/x86_task.c (100%)
 rename target/i386/{ => accel}/hvf/x86_task.h (100%)
 rename target/i386/{ => accel}/hvf/x86hvf.c (100%)
 rename target/i386/{ => accel}/hvf/x86hvf.h (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 6dabd972c9..dd16c78f97 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -439,8 +439,7 @@ 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: target/i386/accel/hvf/
 F: include/sysemu/hvf.h
 
 WHPX CPUs
diff --git a/target/i386/hvf/README.md b/target/i386/accel/hvf/README.md
similarity index 100%
rename from target/i386/hvf/README.md
rename to target/i386/accel/hvf/README.md
diff --git a/target/i386/hvf/hvf-cpus.c b/target/i386/accel/hvf/hvf-cpus.c
similarity index 100%
rename from target/i386/hvf/hvf-cpus.c
rename to target/i386/accel/hvf/hvf-cpus.c
diff --git a/target/i386/hvf/hvf-cpus.h b/target/i386/accel/hvf/hvf-cpus.h
similarity index 100%
rename from target/i386/hvf/hvf-cpus.h
rename to target/i386/accel/hvf/hvf-cpus.h
diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/accel/hvf/hvf-i386.h
similarity index 100%
rename from target/i386/hvf/hvf-i386.h
rename to target/i386/accel/hvf/hvf-i386.h
diff --git a/target/i386/hvf/hvf.c b/target/i386/accel/hvf/hvf.c
similarity index 100%
rename from target/i386/hvf/hvf.c
rename to target/i386/accel/hvf/hvf.c
diff --git a/target/i386/hvf/meson.build b/target/i386/accel/hvf/meson.build
similarity index 100%
rename from target/i386/hvf/meson.build
rename to target/i386/accel/hvf/meson.build
diff --git a/target/i386/hvf/panic.h b/target/i386/accel/hvf/panic.h
similarity index 100%
rename from target/i386/hvf/panic.h
rename to target/i386/accel/hvf/panic.h
diff --git a/target/i386/hvf/vmcs.h b/target/i386/accel/hvf/vmcs.h
similarity index 100%
rename from target/i386/hvf/vmcs.h
rename to target/i386/accel/hvf/vmcs.h
diff --git a/target/i386/hvf/vmx.h b/target/i386/accel/hvf/vmx.h
similarity index 100%
rename from target/i386/hvf/vmx.h
rename to target/i386/accel/hvf/vmx.h
diff --git a/target/i386/hvf/x86.c b/target/i386/accel/hvf/x86.c
similarity index 100%
rename from target/i386/hvf/x86.c
rename to target/i386/accel/hvf/x86.c
diff --git a/target/i386/hvf/x86.h b/target/i386/accel/hvf/x86.h
similarity index 100%
rename from target/i386/hvf/x86.h
rename to target/i386/accel/hvf/x86.h
diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/accel/hvf/x86_cpuid.c
similarity index 100%
rename from target/i386/hvf/x86_cpuid.c
rename to target/i386/accel/hvf/x86_cpuid.c
diff --git a/target/i386/hvf/x86_decode.c b/target/i386/accel/hvf/x86_decode.c
similarity index 100%
rename from target/i386/hvf/x86_decode.c
rename to target/i386/accel/hvf/x86_decode.c
diff --git a/target/i386/hvf/x86_decode.h b/target/i386/accel/hvf/x86_decode.h
similarity index 100%
rename from target/i386/hvf/x86_decode.h
rename to target/i386/accel/hvf/x86_decode.h
diff --git a/target/i386/hvf/x86_descr.c b/target/i386/accel/hvf/x86_descr.c
similarity index 100%
rename from target/i386/hvf/x86_descr.c
rename to target/i386/accel/hvf/x86_descr.c
diff --git a/target/i386/hvf/x86_descr.h b/target/i386/accel/hvf/x86_descr.h
similarity index 100%
rename from target/i386/hvf/x86_descr.h
rename to target/i386/accel/hvf/x86_descr.h
diff --git a/target/i386/hvf/x86_emu.c b/target/i386/accel/hvf/x86_emu.c
similarity index 100%
rename from target/i386/hvf/x86_emu.c
rename to target/i386/accel/hvf/x86_emu.c
diff --git a/target/i386/hvf/x86_emu.h b/target/i386/accel/hvf/x86_emu.h
similarity index 100%
rename from target/i386/hvf/x86_emu.h
rename to target/i386/accel/hvf/x86_emu.h
diff --git a/target/i386/hvf/x86_flags.c b/target/i386/accel/hvf/x86_flags.c
similarity index 100%
rename from target/i386/hvf/x86_flags.c
rename to target/i386/accel/hvf/x86_flags.c
diff --git a/target/i386/hvf/x86_flags.h b/target/i386/accel/hvf/x86_flags.h
similarity index 100%
rename from target/i386/hvf/x86_flags.h
rename to target/i386/accel/hvf/x86_flags.h
diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/accel/hvf/x86_mmu.c
similarity index 100%
rename from target/i386/hvf/x86_mmu.c
rename to target/i386/accel/hvf/x86_mmu.c
diff --git a/target/i386/hvf/x86_mmu.h b/target/i386/accel/hvf/x86_mmu.h
similarity index 100%
rename from target/i386/hvf/x86_mmu.h
rename to target/i386/accel/hvf/x86_mmu.h
diff --git a/target/i386/hvf/x86_task.c b/target/i386/accel/hvf/x86_task.c
similarity index 100%
rename from target/i386/hvf/x86_task.c
rename to target/i386/accel/hvf/x86_task.c
diff --git a/target/i386/hvf/x86_task.h b/target/i386/accel/hvf/x86_task.h
similarity index 100%
rename from target/i386/hvf/x86_task.h
rename to target/i386/accel/hvf/x86_task.h
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/accel/hvf/x86hvf.c
similarity index 100%
rename from target/i386/hvf/x86hvf.c
rename to target/i386/accel/hvf/x86hvf.c
diff --git a/target/i386/hvf/x86hvf.h b/target/i386/accel/hvf/x86hvf.h
similarity index 100%
rename from target/i386/hvf/x86hvf.h
rename to target/i386/accel/hvf/x86hvf.h
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 34ec93dbef..da070e4e54 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -31,7 +31,7 @@ i386_softmmu_ss.add(files(
 subdir('accel/kvm')
 subdir('accel/hax')
 subdir('accel/whpx')
-subdir('hvf')
+subdir('accel/hvf')
 
 target_arch += {'i386': i386_ss}
 target_softmmu_arch += {'i386': i386_softmmu_ss}
-- 
2.26.2



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

* [RFC v1 05/10] i386: move TCG accel files into accel/tcg/
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (3 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 04/10] i386: move hvf accel files into accel/hvf/ Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 06/10] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

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

diff --git a/target/i386/bpt_helper.c b/target/i386/accel/tcg/bpt_helper.c
similarity index 100%
rename from target/i386/bpt_helper.c
rename to target/i386/accel/tcg/bpt_helper.c
diff --git a/target/i386/cc_helper.c b/target/i386/accel/tcg/cc_helper.c
similarity index 100%
rename from target/i386/cc_helper.c
rename to target/i386/accel/tcg/cc_helper.c
diff --git a/target/i386/excp_helper.c b/target/i386/accel/tcg/excp_helper.c
similarity index 100%
rename from target/i386/excp_helper.c
rename to target/i386/accel/tcg/excp_helper.c
diff --git a/target/i386/fpu_helper.c b/target/i386/accel/tcg/fpu_helper.c
similarity index 100%
rename from target/i386/fpu_helper.c
rename to target/i386/accel/tcg/fpu_helper.c
diff --git a/target/i386/int_helper.c b/target/i386/accel/tcg/int_helper.c
similarity index 100%
rename from target/i386/int_helper.c
rename to target/i386/accel/tcg/int_helper.c
diff --git a/target/i386/mem_helper.c b/target/i386/accel/tcg/mem_helper.c
similarity index 100%
rename from target/i386/mem_helper.c
rename to target/i386/accel/tcg/mem_helper.c
diff --git a/target/i386/accel/tcg/meson.build b/target/i386/accel/tcg/meson.build
new file mode 100644
index 0000000000..02794226c2
--- /dev/null
+++ b/target/i386/accel/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/accel/tcg/misc_helper.c
similarity index 100%
rename from target/i386/misc_helper.c
rename to target/i386/accel/tcg/misc_helper.c
diff --git a/target/i386/mpx_helper.c b/target/i386/accel/tcg/mpx_helper.c
similarity index 100%
rename from target/i386/mpx_helper.c
rename to target/i386/accel/tcg/mpx_helper.c
diff --git a/target/i386/seg_helper.c b/target/i386/accel/tcg/seg_helper.c
similarity index 100%
rename from target/i386/seg_helper.c
rename to target/i386/accel/tcg/seg_helper.c
diff --git a/target/i386/smm_helper.c b/target/i386/accel/tcg/smm_helper.c
similarity index 100%
rename from target/i386/smm_helper.c
rename to target/i386/accel/tcg/smm_helper.c
diff --git a/target/i386/svm_helper.c b/target/i386/accel/tcg/svm_helper.c
similarity index 100%
rename from target/i386/svm_helper.c
rename to target/i386/accel/tcg/svm_helper.c
diff --git a/target/i386/tcg-stub.c b/target/i386/accel/tcg/tcg-stub.c
similarity index 100%
rename from target/i386/tcg-stub.c
rename to target/i386/accel/tcg/tcg-stub.c
diff --git a/target/i386/translate.c b/target/i386/accel/tcg/translate.c
similarity index 100%
rename from target/i386/translate.c
rename to target/i386/accel/tcg/translate.c
diff --git a/target/i386/meson.build b/target/i386/meson.build
index da070e4e54..55a5b27f1d 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('accel/kvm')
 subdir('accel/hax')
 subdir('accel/whpx')
 subdir('accel/hvf')
+subdir('accel/tcg')
 
 target_arch += {'i386': i386_ss}
 target_softmmu_arch += {'i386': i386_softmmu_ss}
-- 
2.26.2



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

* [RFC v1 06/10] i386: move cpu dump out of helper.c into cpu-dump.c
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (4 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 05/10] i386: move TCG accel files into accel/tcg/ Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, 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 d1f4c2fd2c..d4772185df 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 25f2bf3137..a78fc4b4aa 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 "accel/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 55a5b27f1d..7da5521364 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] 33+ messages in thread

* [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (5 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 06/10] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:39   ` Paolo Bonzini
  2020-11-09 17:27 ` [RFC v1 08/10] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 target/i386/accel/tcg/bpt_helper.c  |   1 +
 target/i386/accel/tcg/cc_helper.c   |   1 +
 target/i386/accel/tcg/excp_helper.c |   1 +
 target/i386/accel/tcg/fpu_helper.c  |  33 ++++----
 target/i386/accel/tcg/int_helper.c  |   1 +
 target/i386/accel/tcg/mem_helper.c  |   1 +
 target/i386/accel/tcg/misc_helper.c |   1 +
 target/i386/accel/tcg/mpx_helper.c  |   1 +
 target/i386/accel/tcg/seg_helper.c  |   1 +
 target/i386/accel/tcg/smm_helper.c  |   2 +
 target/i386/accel/tcg/svm_helper.c  |   1 +
 target/i386/accel/tcg/translate.c   |   1 +
 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 ++++
 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/accel/tcg/bpt_helper.c b/target/i386/accel/tcg/bpt_helper.c
index c3a8ea73c9..5a551ce06e 100644
--- a/target/i386/accel/tcg/bpt_helper.c
+++ b/target/i386/accel/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/accel/tcg/cc_helper.c b/target/i386/accel/tcg/cc_helper.c
index c9c90e10db..0b4c5b2cee 100644
--- a/target/i386/accel/tcg/cc_helper.c
+++ b/target/i386/accel/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/accel/tcg/excp_helper.c b/target/i386/accel/tcg/excp_helper.c
index b10c7ecbcc..7cf690652e 100644
--- a/target/i386/accel/tcg/excp_helper.c
+++ b/target/i386/accel/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/accel/tcg/fpu_helper.c b/target/i386/accel/tcg/fpu_helper.c
index 4ea73874d8..28703a41a2 100644
--- a/target/i386/accel/tcg/fpu_helper.c
+++ b/target/i386/accel/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/accel/tcg/int_helper.c b/target/i386/accel/tcg/int_helper.c
index 334469ca8c..5fedb851f3 100644
--- a/target/i386/accel/tcg/int_helper.c
+++ b/target/i386/accel/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/accel/tcg/mem_helper.c b/target/i386/accel/tcg/mem_helper.c
index 3a6d3ae2ef..1f6808d311 100644
--- a/target/i386/accel/tcg/mem_helper.c
+++ b/target/i386/accel/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/accel/tcg/misc_helper.c b/target/i386/accel/tcg/misc_helper.c
index b6b1d41b14..9afcd11ea1 100644
--- a/target/i386/accel/tcg/misc_helper.c
+++ b/target/i386/accel/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/accel/tcg/mpx_helper.c b/target/i386/accel/tcg/mpx_helper.c
index ade5d245d2..329aeef780 100644
--- a/target/i386/accel/tcg/mpx_helper.c
+++ b/target/i386/accel/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/accel/tcg/seg_helper.c b/target/i386/accel/tcg/seg_helper.c
index be88938c2a..bad751c495 100644
--- a/target/i386/accel/tcg/seg_helper.c
+++ b/target/i386/accel/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/accel/tcg/smm_helper.c b/target/i386/accel/tcg/smm_helper.c
index eb5aa6eb3d..ede197a379 100644
--- a/target/i386/accel/tcg/smm_helper.c
+++ b/target/i386/accel/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/accel/tcg/svm_helper.c b/target/i386/accel/tcg/svm_helper.c
index 6224387eab..202832762e 100644
--- a/target/i386/accel/tcg/svm_helper.c
+++ b/target/i386/accel/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/accel/tcg/translate.c b/target/i386/accel/tcg/translate.c
index caea6f5fb1..bb64070365 100644
--- a/target/i386/accel/tcg/translate.c
+++ b/target/i386/accel/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"
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b1a55a2b79..b185789d88 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 d4772185df..f1bce16b53 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 a78fc4b4aa..0af4c1adf2 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -24,10 +24,8 @@
 #include "sysemu/runstate.h"
 #include "accel/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)
@@ -574,27 +572,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 7da5521364..50c8fba6cb 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 */
-- 
2.26.2



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

* [RFC v1 08/10] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (6 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, 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 defer the registration of the cpu models,
in order to make them subclasses of a per-accel cpu type.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 accel/kvm/kvm-all.c               | 11 +++++++++--
 accel/qtest/qtest.c               | 10 +++++++++-
 accel/tcg/tcg-all.c               | 11 +++++++++--
 accel/xen/xen-all.c               | 12 +++++++++---
 include/qemu/module.h             |  2 ++
 softmmu/vl.c                      |  6 ++++++
 target/i386/accel/hax/hax-all.c   | 12 +++++++++---
 target/i386/accel/hvf/hvf.c       | 10 +++++++++-
 target/i386/accel/whpx/whpx-all.c | 11 +++++++++--
 9 files changed, 71 insertions(+), 14 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 b282cea5cf..8d14059e32 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 fa1208158f..9ffedc8151 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -104,8 +104,6 @@ static int tcg_init(MachineState *ms)
 
     tcg_exec_init(s->tb_size * 1024 * 1024);
     mttcg_enabled = s->mttcg_enabled;
-    cpus_register_accel(&tcg_cpus);
-
     return 0;
 }
 
@@ -201,3 +199,12 @@ static void register_accel_types(void)
 }
 
 type_init(register_accel_types);
+
+static void tcg_accel_cpu_init(void)
+{
+    if (tcg_enabled()) {
+        cpus_register_accel(&tcg_cpus);
+    }
+}
+
+accel_cpu_init(tcg_accel_cpu_init);
diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c
index 878a4089d9..6932a9f364 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/softmmu/vl.c b/softmmu/vl.c
index a537a0377f..6a6363902d 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4174,6 +4174,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/accel/hax/hax-all.c b/target/i386/accel/hax/hax-all.c
index fecfe8cd6e..3bada019f5 100644
--- a/target/i386/accel/hax/hax-all.c
+++ b/target/i386/accel/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/accel/hvf/hvf.c b/target/i386/accel/hvf/hvf.c
index ed9356565c..249b77797f 100644
--- a/target/i386/accel/hvf/hvf.c
+++ b/target/i386/accel/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/accel/whpx/whpx-all.c b/target/i386/accel/whpx/whpx-all.c
index f4f3e33eac..2e715e2bc6 100644
--- a/target/i386/accel/whpx/whpx-all.c
+++ b/target/i386/accel/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] 33+ messages in thread

* [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (7 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 08/10] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:34   ` Paolo Bonzini
                     ` (3 more replies)
  2020-11-09 17:27 ` [RFC v1 10/10] module: add priority to module_init Claudio Fontana
  2020-11-09 17:45 ` [RFC v1 00/10] i386 cleanup no-reply
  10 siblings, 4 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, 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-type.c   KVM x86 cpu type
hvf-cpu-type.c   HVF x86 cpu type
tcg-cpu-type.c   TCG x86 cpu type

Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
so that accel-specific types can be used as parent types for all
cpu models. Use the generic TYPE_X86_CPU only if no
accel-specific specialization is enabled.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 bsd-user/main.c                      |   4 +
 hw/i386/pc_piix.c                    |   1 +
 linux-user/main.c                    |  10 +-
 softmmu/vl.c                         |   2 +-
 target/i386/accel/hvf/hvf-cpu-type.c |  78 +++++
 target/i386/accel/hvf/meson.build    |   1 +
 target/i386/accel/kvm/kvm-cpu-type.c | 161 ++++++++++
 target/i386/accel/kvm/kvm-cpu-type.h |  41 +++
 target/i386/accel/kvm/kvm.c          |   3 +-
 target/i386/accel/kvm/meson.build    |   7 +-
 target/i386/accel/tcg/meson.build    |   3 +-
 target/i386/accel/tcg/tcg-cpu-type.c | 176 +++++++++++
 target/i386/accel/tcg/tcg-cpu-type.h |  25 ++
 target/i386/cpu.c                    | 454 +++++----------------------
 target/i386/cpu.h                    |  26 +-
 target/i386/host-cpu.c               | 201 ++++++++++++
 target/i386/host-cpu.h               |  21 ++
 target/i386/meson.build              |   8 +-
 target/i386/tcg-cpu.c                |  71 -----
 target/i386/tcg-cpu.h                |  15 -
 20 files changed, 834 insertions(+), 474 deletions(-)
 create mode 100644 target/i386/accel/hvf/hvf-cpu-type.c
 create mode 100644 target/i386/accel/kvm/kvm-cpu-type.c
 create mode 100644 target/i386/accel/kvm/kvm-cpu-type.h
 create mode 100644 target/i386/accel/tcg/tcg-cpu-type.c
 create mode 100644 target/i386/accel/tcg/tcg-cpu-type.h
 create mode 100644 target/i386/host-cpu.c
 create mode 100644 target/i386/host-cpu.h
 delete mode 100644 target/i386/tcg-cpu.c
 delete mode 100644 target/i386/tcg-cpu.h

diff --git a/bsd-user/main.c b/bsd-user/main.c
index ac40d79bfa..48dd4b8ba5 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -911,6 +911,10 @@ int main(int argc, char **argv)
 
     /* init tcg before creating CPUs and to get qemu_host_page_size */
     tcg_exec_init(0);
+    /*
+     * TCG has been initialized, now it is time to register the cpu models.
+     */
+    module_call_init(MODULE_INIT_ACCEL_CPU);
 
     cpu_type = parse_cpu_option(cpu_model);
     cpu = cpu_create(cpu_type);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 13d1628f13..a59c3e1457 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 "accel/kvm/kvm-cpu-type.h"
 
 #define MAX_IDE_BUS 2
 
diff --git a/linux-user/main.c b/linux-user/main.c
index 75c9785157..86ebd5db5e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -699,14 +699,18 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
+    /* init tcg before creating CPUs and to get qemu_host_page_size */
+    tcg_exec_init(0);
+    /*
+     * TCG has been initialized, now it is time to register the cpu models.
+     */
+    module_call_init(MODULE_INIT_ACCEL_CPU);
+
     if (cpu_model == NULL) {
         cpu_model = cpu_get_model(get_elf_eflags(execfd));
     }
     cpu_type = parse_cpu_option(cpu_model);
 
-    /* init tcg before creating CPUs and to get qemu_host_page_size */
-    tcg_exec_init(0);
-
     cpu = cpu_create(cpu_type);
     env = cpu->env_ptr;
     cpu_reset(cpu);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 6a6363902d..47cc938cef 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4176,7 +4176,7 @@ void qemu_init(int argc, char **argv, char **envp)
 
     /*
      * accelerator has been chosen and initialized, now it is time to
-     * register the cpu accel interface.
+     * register the cpu models, and the cpu accel interface.
      */
     module_call_init(MODULE_INIT_ACCEL_CPU);
 
diff --git a/target/i386/accel/hvf/hvf-cpu-type.c b/target/i386/accel/hvf/hvf-cpu-type.c
new file mode 100644
index 0000000000..dfe4ec4e9e
--- /dev/null
+++ b/target/i386/accel/hvf/hvf-cpu-type.c
@@ -0,0 +1,78 @@
+/*
+ * 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 "hvf-cpu-type.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "sysemu/hvf.h"
+
+
+static void hvf_cpu_common_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = host_cpu_realizefn;
+}
+
+static void hvf_cpu_max_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    CPUX86State *env = &cpu->env;
+
+    host_cpu_max_initfn(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_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+
+    host_cpu_initfn(obj);
+
+    /* Special cases not set in the X86CPUDefinition structs: */
+    /* TODO: in-kernel irqchip for hvf */
+
+    if (cpu->max_features) {
+        hvf_cpu_max_initfn(obj);
+    }
+}
+
+static const TypeInfo hvf_cpu_type_info = {
+    .name = X86_CPU_TYPE_NAME("hvf"),
+    .parent = TYPE_X86_CPU,
+
+    .instance_init = hvf_cpu_initfn,
+    .class_init = hvf_cpu_common_class_init,
+};
+
+static void hvf_cpu_register_base_type(void)
+{
+    type_register_static(&hvf_cpu_type_info);
+}
+
+type_init(hvf_cpu_register_base_type);
+
+void hvf_cpu_type_init(void)
+{
+    if (hvf_enabled()) {
+        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("hvf"));
+    }
+}
+
+accel_cpu_init(hvf_cpu_type_init);
diff --git a/target/i386/accel/hvf/meson.build b/target/i386/accel/hvf/meson.build
index 409c9a3f14..785dee72fc 100644
--- a/target/i386/accel/hvf/meson.build
+++ b/target/i386/accel/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',
+  'hvf-cpu-type.c',
 ))
diff --git a/target/i386/accel/kvm/kvm-cpu-type.c b/target/i386/accel/kvm/kvm-cpu-type.c
new file mode 100644
index 0000000000..f696f21e2b
--- /dev/null
+++ b/target/i386/accel/kvm/kvm-cpu-type.c
@@ -0,0 +1,161 @@
+/*
+ * 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-type.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+
+#include "kvm_i386.h"
+
+/* this information overloads the TYPE_X86_CPU type in x86-cpu.c */
+
+static void kvm_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+    X86CPU *cpu = X86_CPU(dev);
+    CPUX86State *env = &cpu->env;
+
+    /*
+     * also for KVM the realize order is important, since
+     * x86_cpu_realize() checks if nothing else has been set by the user,
+     * or by the specialized x86 cpus (KVM, HVF) in
+     * cpu->ucode_rev and cpu->phys_bits.
+     *
+     * So it's 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(dev, errp);
+}
+
+static void kvm_cpu_common_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    dc->realize = kvm_cpu_realizefn;
+}
+
+/*
+ * 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_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    CPUX86State *env = &cpu->env;
+    KVMState *s = kvm_state;
+
+    host_cpu_max_initfn(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_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+
+    host_cpu_initfn(obj);
+
+    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_initfn(obj);
+    }
+}
+
+static const TypeInfo kvm_cpu_type_info = {
+    .name = X86_CPU_TYPE_NAME("kvm"),
+    .parent = TYPE_X86_CPU,
+
+    .instance_init = kvm_cpu_initfn,
+    .class_init = kvm_cpu_common_class_init,
+};
+
+static void kvm_cpu_register_base_type(void)
+{
+    type_register_static(&kvm_cpu_type_info);
+}
+
+type_init(kvm_cpu_register_base_type);
+
+void kvm_cpu_type_init(void)
+{
+    if (kvm_enabled()) {
+        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("kvm"));
+        host_cpu_type_init();
+    }
+}
+
+accel_cpu_init(kvm_cpu_type_init);
diff --git a/target/i386/accel/kvm/kvm-cpu-type.h b/target/i386/accel/kvm/kvm-cpu-type.h
new file mode 100644
index 0000000000..2448f49222
--- /dev/null
+++ b/target/i386/accel/kvm/kvm-cpu-type.h
@@ -0,0 +1,41 @@
+/*
+ * i386 KVM CPU type 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/>.
+ */
+
+#ifndef KVM_CPU_TYPE_H
+#define KVM_CPU_TYPE_H
+
+#ifdef CONFIG_KVM
+void kvm_cpu_type_init(void);
+
+/*
+ * 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_TYPE_H */
diff --git a/target/i386/accel/kvm/kvm.c b/target/i386/accel/kvm/kvm.c
index cf46259534..829730d3c2 100644
--- a/target/i386/accel/kvm/kvm.c
+++ b/target/i386/accel/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/accel/kvm/meson.build b/target/i386/accel/kvm/meson.build
index 1d66559187..b6b32166b4 100644
--- a/target/i386/accel/kvm/meson.build
+++ b/target/i386/accel/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',
+  'kvm-cpu-type.c',
+))
+
 i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
diff --git a/target/i386/accel/tcg/meson.build b/target/i386/accel/tcg/meson.build
index 02794226c2..211ecef5f9 100644
--- a/target/i386/accel/tcg/meson.build
+++ b/target/i386/accel/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',
+  'tcg-cpu-type.c'), if_false: files('tcg-stub.c'))
diff --git a/target/i386/accel/tcg/tcg-cpu-type.c b/target/i386/accel/tcg/tcg-cpu-type.c
new file mode 100644
index 0000000000..f0ee4ef5f7
--- /dev/null
+++ b/target/i386/accel/tcg/tcg-cpu-type.c
@@ -0,0 +1,176 @@
+/*
+ * 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 "tcg-cpu-type.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(DeviceState *dev, Error **errp)
+{
+    X86CPU *cpu = X86_CPU(dev);
+    CPUState *cs = CPU(dev);
+
+    /*
+     * also for TCG the realize order is important,
+     * as the memory regions initialized here are needed
+     * in x86_cpu_realizefn()
+     */
+    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);
+
+    /* call the generic x86_cpu_realizefn() after regions initialized */
+    x86_cpu_realizefn(dev, errp);
+}
+#endif /* !CONFIG_USER_ONLY */
+
+static void tcg_cpu_common_class_init(ObjectClass *oc, void *data)
+{
+    CPUClass *cc = CPU_CLASS(oc);
+#ifndef CONFIG_USER_ONLY
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = tcg_cpu_realizefn;
+#endif /* !CONFIG_USER_ONLY */
+
+    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_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+
+    /* Special cases not set in the X86CPUDefinition structs: */
+    x86_cpu_apply_props(cpu, tcg_default_props);
+}
+
+static const TypeInfo tcg_cpu_type_info = {
+    .name = X86_CPU_TYPE_NAME("tcg"),
+    .parent = TYPE_X86_CPU,
+
+    .instance_init = tcg_cpu_initfn,
+    .class_init = tcg_cpu_common_class_init,
+};
+
+static void tcg_cpu_register_base_type(void)
+{
+    type_register_static(&tcg_cpu_type_info);
+}
+
+type_init(tcg_cpu_register_base_type);
+
+void tcg_cpu_type_init(void)
+{
+    if (tcg_enabled()) {
+        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("tcg"));
+    }
+}
+
+accel_cpu_init(tcg_cpu_type_init);
diff --git a/target/i386/accel/tcg/tcg-cpu-type.h b/target/i386/accel/tcg/tcg-cpu-type.h
new file mode 100644
index 0000000000..d741a8f6be
--- /dev/null
+++ b/target/i386/accel/tcg/tcg-cpu-type.h
@@ -0,0 +1,25 @@
+/*
+ * i386 TCG CPU type 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/>.
+ */
+
+#ifndef TCG_CPU_TYPE_H
+#define TCG_CPU_TYPE_H
+
+void tcg_cpu_type_init(void);
+
+#endif /* TCG_CPU_TYPE_H */
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b185789d88..b547c9d39d 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,27 +32,17 @@
 #include "sysemu/xen.h"
 #include "accel/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
 #include "exec/address-spaces.h"
 #include "hw/i386/apic_internal.h"
@@ -594,8 +582,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 +1551,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 +1575,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 +4071,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 +4112,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),
@@ -4246,98 +4131,38 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
     device_class_set_props(dc, max_x86_cpu_properties);
 }
 
-static void max_x86_cpu_initfn(Object *obj)
+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 = {
+static TypeInfo max_x86_cpu_type_info = {
     .name = X86_CPU_TYPE_NAME("max"),
-    .parent = TYPE_X86_CPU,
-    .instance_init = max_x86_cpu_initfn,
+    .parent = NULL, /* set by x86_cpu_register_cpu_models */
+
     .class_init = max_x86_cpu_class_init,
+    .instance_init = max_x86_cpu_initfn,
 };
 
-#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 +4888,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 +4935,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 +4961,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 +4970,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);
 
@@ -5400,12 +5208,13 @@ static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
     cc->deprecation_note = model->cpudef->deprecation_note;
 }
 
-static void x86_register_cpu_model_type(const char *name, X86CPUModel *model)
+static void x86_register_cpu_model_type(const char *name, X86CPUModel *model,
+                                        const char *parent_type)
 {
     g_autofree char *typename = x86_cpu_type_name(name);
     TypeInfo ti = {
         .name = typename,
-        .parent = TYPE_X86_CPU,
+        .parent = parent_type,
         .class_init = x86_cpu_cpudef_class_init,
         .class_data = model,
     };
@@ -5413,7 +5222,8 @@ static void x86_register_cpu_model_type(const char *name, X86CPUModel *model)
     type_register(&ti);
 }
 
-static void x86_register_cpudef_types(X86CPUDefinition *def)
+static void x86_register_cpudef(X86CPUDefinition *def,
+                                const char *parent_type)
 {
     X86CPUModel *m;
     const X86CPUVersionDefinition *vdef;
@@ -5430,7 +5240,7 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
     m->cpudef = def;
     m->version = CPU_VERSION_AUTO;
     m->is_alias = true;
-    x86_register_cpu_model_type(def->name, m);
+    x86_register_cpu_model_type(def->name, m, parent_type);
 
     /* Versioned models: */
 
@@ -5441,14 +5251,14 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
         m->cpudef = def;
         m->version = vdef->version;
         m->note = vdef->note;
-        x86_register_cpu_model_type(name, m);
+        x86_register_cpu_model_type(name, m, parent_type);
 
         if (vdef->alias) {
             X86CPUModel *am = g_new0(X86CPUModel, 1);
             am->cpudef = def;
             am->version = vdef->version;
             am->is_alias = true;
-            x86_register_cpu_model_type(vdef->alias, am);
+            x86_register_cpu_model_type(vdef->alias, am, parent_type);
         }
     }
 
@@ -6192,53 +6002,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) {
@@ -6512,7 +6281,7 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
     }
 }
 
-static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
+void x86_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
     X86CPU *cpu = X86_CPU(dev);
@@ -6521,27 +6290,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;
-        }
-    }
+    /*
+     * For accelerators that specialize the x86 cpu,
+     * this common code must be called after the accelerator-specific realizefn.
+     */
 
-    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 +6350,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 +6358,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,32 +6429,7 @@ 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
+    /* XXX this is the place for tcg region initialization XXX */
 
     qemu_init_vcpu(cs);
 
@@ -6932,7 +6632,7 @@ static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v,
 }
 #endif /* !CONFIG_USER_ONLY */
 
-static void x86_cpu_initfn(Object *obj)
+void x86_cpu_initfn(Object *obj)
 {
     X86CPU *cpu = X86_CPU(obj);
     X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
@@ -7230,7 +6930,7 @@ static Property x86_cpu_properties[] = {
     DEFINE_PROP_END_OF_LIST()
 };
 
-static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
+void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(oc);
     CPUClass *cc = CPU_CLASS(oc);
@@ -7249,10 +6949,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     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;
@@ -7341,25 +7037,49 @@ static void x86_cpu_base_class_init(ObjectClass *oc, void *data)
     xcc->ordering = 8;
 }
 
-static const TypeInfo x86_base_cpu_type_info = {
-        .name = X86_CPU_TYPE_NAME("base"),
-        .parent = TYPE_X86_CPU,
-        .class_init = x86_cpu_base_class_init,
+static TypeInfo x86_base_cpu_type_info = {
+    .name = X86_CPU_TYPE_NAME("base"),
+    .parent = NULL, /* set by x86_cpu_register_cpu_models */
+
+    .class_init = x86_cpu_base_class_init,
 };
 
-static void x86_cpu_register_types(void)
+/*
+ * x86 cpu types are only registered once accelerator is determined,
+ * passing the parent cpu type as an argument here.
+ */
+void x86_cpu_register_cpu_models(const char *parent_type)
 {
     int i;
 
-    type_register_static(&x86_cpu_type_info);
     for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
-        x86_register_cpudef_types(&builtin_x86_defs[i]);
+        x86_register_cpudef(&builtin_x86_defs[i], parent_type);
+    }
+    max_x86_cpu_type_info.parent = parent_type;
+    type_register(&max_x86_cpu_type_info);
+
+    x86_base_cpu_type_info.parent = parent_type;
+    type_register(&x86_base_cpu_type_info);
+}
+
+static void x86_cpu_register_base_type(void)
+{
+    type_register_static(&x86_cpu_type_info);
+}
+
+type_init(x86_cpu_register_base_type);
+
+/*
+ * generic initializer if no other specialization.
+ */
+static void x86_cpu_type_init(void)
+{
+    /*
+     * I would like something better than this check.
+     */
+    if (!tcg_enabled() && !kvm_enabled() && !hvf_enabled()) {
+        x86_cpu_register_cpu_models(TYPE_X86_CPU);
     }
-    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_init(x86_cpu_register_types)
+accel_cpu_init(x86_cpu_type_init);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index f1bce16b53..9232672eb2 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1905,13 +1905,26 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 
 /* cpu.c */
+void x86_cpu_register_cpu_models(const char *parent_type);
+
+void x86_cpu_initfn(Object *obj);
+void max_x86_cpu_initfn(Object *obj);
+void x86_cpu_realizefn(DeviceState *dev, Error **errp);
+void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
+                              uint32_t vendor2, uint32_t vendor3);
+void x86_cpu_common_class_init(ObjectClass *oc, void *data);
+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 +2124,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..65a0119f4b
--- /dev/null
+++ b/target/i386/host-cpu.c
@@ -0,0 +1,201 @@
+/*
+ * 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(DeviceState *dev, Error **errp)
+{
+    X86CPU *cpu = X86_CPU(dev);
+    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);
+    }
+    x86_cpu_realizefn(dev, 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_initfn(Object *obj)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    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_initfn(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("%s processor with all supported host features ",
+                        ACCEL_GET_CLASS(current_accel())->name);
+}
+
+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,
+};
+
+void host_cpu_type_init(void)
+{
+    type_register(&host_cpu_type_info);
+}
diff --git a/target/i386/host-cpu.h b/target/i386/host-cpu.h
new file mode 100644
index 0000000000..e9d4726833
--- /dev/null
+++ b/target/i386/host-cpu.h
@@ -0,0 +1,21 @@
+/*
+ * x86 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.
+ */
+
+#ifndef HOST_CPU_TYPE_H
+#define HOST_CPU_TYPE_H
+
+void host_cpu_type_init(void);
+
+void host_cpu_initfn(Object *obj);
+void host_cpu_realizefn(DeviceState *dev, Error **errp);
+void host_cpu_max_initfn(X86CPU *cpu);
+
+void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping);
+
+#endif /* HOST_CPU_TYPE_H */
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 50c8fba6cb..c84b0d6965 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 */
-- 
2.26.2



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

* [RFC v1 10/10] module: add priority to module_init
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (8 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
@ 2020-11-09 17:27 ` Claudio Fontana
  2020-11-09 17:45 ` [RFC v1 00/10] i386 cleanup no-reply
  10 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-09 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

add a new version of module_init that also takes a priority argument,
and use it to be able to run a constructor last for INIT_ACCEL_CPU,

and thus avoid the manual work of keeping track how to conditionalize
the generic x86 cpu models registration.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 include/qemu/module.h | 17 ++++++++++++++++-
 target/i386/cpu.c     | 16 ++++++++++++----
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/include/qemu/module.h b/include/qemu/module.h
index 485eda986a..1f4fac6791 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -30,6 +30,13 @@ static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
 {                                                                           \
     register_dso_module_init(function, type);                               \
 }
+
+#define module_init_prio(function, type, prio)                                 \
+static void __attribute__((constructor(prio))) do_qemu_init_ ## function(void) \
+{                                                                              \
+    register_dso_module_init(function, type);                                  \
+}
+
 #else
 /* This should not be used directly.  Use block_init etc. instead.  */
 #define module_init(function, type)                                         \
@@ -37,6 +44,11 @@ static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
 {                                                                           \
     register_module_init(function, type);                                   \
 }
+#define module_init_prio(function, type, prio)                                 \
+static void __attribute__((constructor(prio))) do_qemu_init_ ## function(void) \
+{                                                                              \
+    register_module_init(function, type);                                      \
+}
 #endif
 
 typedef enum {
@@ -55,7 +67,10 @@ 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 accel_cpu_init(function) \
+    module_init_prio(function, MODULE_INIT_ACCEL_CPU, 101)
+#define accel_cpu_init_last(function) \
+    module_init_prio(function, MODULE_INIT_ACCEL_CPU, 65535)
 #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/target/i386/cpu.c b/target/i386/cpu.c
index b547c9d39d..aeaebfde02 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7050,8 +7050,16 @@ static TypeInfo x86_base_cpu_type_info = {
  */
 void x86_cpu_register_cpu_models(const char *parent_type)
 {
+    static bool x86_cpu_models_registered;
     int i;
 
+    if (x86_cpu_models_registered) {
+        /*
+         * already registered by an accelerator-specific specialization
+         * of x86_cpu
+         */
+        return;
+    }
     for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
         x86_register_cpudef(&builtin_x86_defs[i], parent_type);
     }
@@ -7060,6 +7068,8 @@ void x86_cpu_register_cpu_models(const char *parent_type)
 
     x86_base_cpu_type_info.parent = parent_type;
     type_register(&x86_base_cpu_type_info);
+
+    x86_cpu_models_registered = true;
 }
 
 static void x86_cpu_register_base_type(void)
@@ -7077,9 +7087,7 @@ static void x86_cpu_type_init(void)
     /*
      * I would like something better than this check.
      */
-    if (!tcg_enabled() && !kvm_enabled() && !hvf_enabled()) {
-        x86_cpu_register_cpu_models(TYPE_X86_CPU);
-    }
+    x86_cpu_register_cpu_models(TYPE_X86_CPU);
 }
 
-accel_cpu_init(x86_cpu_type_init);
+accel_cpu_init_last(x86_cpu_type_init);
-- 
2.26.2



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
@ 2020-11-09 17:34   ` Paolo Bonzini
  2020-11-09 17:37   ` Paolo Bonzini
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-09 17:34 UTC (permalink / raw)
  To: Claudio Fontana, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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

On 09/11/20 18:27, Claudio Fontana wrote:
> |softmmu/vl.c | 2 +- target/i386/accel/hvf/hvf-cpu-type.c | 78 +++++ 
> target/i386/accel/hvf/meson.build | 1 + 
> target/i386/accel/kvm/kvm-cpu-type.c | 161 ++++++++++ 
> target/i386/accel/kvm/kvm-cpu-type.h | 41 +++ 
> target/i386/accel/kvm/kvm.c | 3 +- target/i386/accel/kvm/meson.build | 7 
> +- target/i386/accel/tcg/meson.build | 3 +- 
> target/i386/accel/tcg/tcg-cpu-type.c | 176 +++++++++++ 
> target/i386/accel/tcg/tcg-cpu-type.h | 25 ++|

Name the files just cpu.c/cpu.h?

(As an aside, I would skip the accel/ directory for the sake of 
conciseness).

Paolo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
  2020-11-09 17:34   ` Paolo Bonzini
@ 2020-11-09 17:37   ` Paolo Bonzini
  2020-11-09 18:03   ` Daniel P. Berrangé
  2020-11-09 19:04   ` Eduardo Habkost
  3 siblings, 0 replies; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-09 17:37 UTC (permalink / raw)
  To: Claudio Fontana, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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

On 09/11/20 18:27, Claudio Fontana wrote:
> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU, so that 
> accel-specific types can be used as parent types for all cpu models. Use 
> the generic TYPE_X86_CPU only if no accel-specific specialization is 
> enabled.

Can we use an accel-specific ops struct, and avoid having accel-specific 
types?  Having dynamic types like these would make it very hard to build 
a schema of QOM objects.

Paolo



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

* Re: [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c
  2020-11-09 17:27 ` [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
@ 2020-11-09 17:39   ` Paolo Bonzini
  2020-11-10 10:05     ` Claudio Fontana
  0 siblings, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-09 17:39 UTC (permalink / raw)
  To: Claudio Fontana, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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

On 09/11/20 18:27, Claudio Fontana wrote:
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
>   target/i386/accel/tcg/bpt_helper.c  |   1 +
>   target/i386/accel/tcg/cc_helper.c   |   1 +
>   target/i386/accel/tcg/excp_helper.c |   1 +
>   target/i386/accel/tcg/fpu_helper.c  |  33 ++++----
>   target/i386/accel/tcg/int_helper.c  |   1 +
>   target/i386/accel/tcg/mem_helper.c  |   1 +
>   target/i386/accel/tcg/misc_helper.c |   1 +
>   target/i386/accel/tcg/mpx_helper.c  |   1 +
>   target/i386/accel/tcg/seg_helper.c  |   1 +
>   target/i386/accel/tcg/smm_helper.c  |   2 +
>   target/i386/accel/tcg/svm_helper.c  |   1 +
>   target/i386/accel/tcg/translate.c   |   1 +
>   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 ++++
>   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/accel/tcg/bpt_helper.c b/target/i386/accel/tcg/bpt_helper.c
> index c3a8ea73c9..5a551ce06e 100644
> --- a/target/i386/accel/tcg/bpt_helper.c
> +++ b/target/i386/accel/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/accel/tcg/cc_helper.c b/target/i386/accel/tcg/cc_helper.c
> index c9c90e10db..0b4c5b2cee 100644
> --- a/target/i386/accel/tcg/cc_helper.c
> +++ b/target/i386/accel/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/accel/tcg/excp_helper.c b/target/i386/accel/tcg/excp_helper.c
> index b10c7ecbcc..7cf690652e 100644
> --- a/target/i386/accel/tcg/excp_helper.c
> +++ b/target/i386/accel/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/accel/tcg/fpu_helper.c b/target/i386/accel/tcg/fpu_helper.c
> index 4ea73874d8..28703a41a2 100644
> --- a/target/i386/accel/tcg/fpu_helper.c
> +++ b/target/i386/accel/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/accel/tcg/int_helper.c b/target/i386/accel/tcg/int_helper.c
> index 334469ca8c..5fedb851f3 100644
> --- a/target/i386/accel/tcg/int_helper.c
> +++ b/target/i386/accel/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/accel/tcg/mem_helper.c b/target/i386/accel/tcg/mem_helper.c
> index 3a6d3ae2ef..1f6808d311 100644
> --- a/target/i386/accel/tcg/mem_helper.c
> +++ b/target/i386/accel/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/accel/tcg/misc_helper.c b/target/i386/accel/tcg/misc_helper.c
> index b6b1d41b14..9afcd11ea1 100644
> --- a/target/i386/accel/tcg/misc_helper.c
> +++ b/target/i386/accel/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/accel/tcg/mpx_helper.c b/target/i386/accel/tcg/mpx_helper.c
> index ade5d245d2..329aeef780 100644
> --- a/target/i386/accel/tcg/mpx_helper.c
> +++ b/target/i386/accel/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/accel/tcg/seg_helper.c b/target/i386/accel/tcg/seg_helper.c
> index be88938c2a..bad751c495 100644
> --- a/target/i386/accel/tcg/seg_helper.c
> +++ b/target/i386/accel/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/accel/tcg/smm_helper.c b/target/i386/accel/tcg/smm_helper.c
> index eb5aa6eb3d..ede197a379 100644
> --- a/target/i386/accel/tcg/smm_helper.c
> +++ b/target/i386/accel/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/accel/tcg/svm_helper.c b/target/i386/accel/tcg/svm_helper.c
> index 6224387eab..202832762e 100644
> --- a/target/i386/accel/tcg/svm_helper.c
> +++ b/target/i386/accel/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/accel/tcg/translate.c b/target/i386/accel/tcg/translate.c
> index caea6f5fb1..bb64070365 100644
> --- a/target/i386/accel/tcg/translate.c
> +++ b/target/i386/accel/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"
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index b1a55a2b79..b185789d88 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 d4772185df..f1bce16b53 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 a78fc4b4aa..0af4c1adf2 100644
> --- a/target/i386/helper.c
> +++ b/target/i386/helper.c
> @@ -24,10 +24,8 @@
>   #include "sysemu/runstate.h"
>   #include "accel/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)
> @@ -574,27 +572,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 7da5521364..50c8fba6cb 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 */
> 

Up to this patch I think it's a no brainer, modulo the bikeshedding on 
paths.

Paolo



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

* Re: [RFC v1 00/10] i386 cleanup
  2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
                   ` (9 preceding siblings ...)
  2020-11-09 17:27 ` [RFC v1 10/10] module: add priority to module_init Claudio Fontana
@ 2020-11-09 17:45 ` no-reply
  10 siblings, 0 replies; 33+ messages in thread
From: no-reply @ 2020-11-09 17:45 UTC (permalink / raw)
  To: cfontana
  Cc: paul, jasowang, qemu-devel, peterx, haxm-team, colin.xu,
	sstabellini, brogers, cfontana, anthony.perard, philmd, lvivier,
	thuth, ehabkost, dirty, dfaggioli, r.bolshakov, sunilmut, rth,
	mtosatti, wenchao.wang, pbonzini

Patchew URL: https://patchew.org/QEMU/20201109172755.16500-1-cfontana@suse.de/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20201109172755.16500-1-cfontana@suse.de
Subject: [RFC v1 00/10] i386 cleanup
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20201109090422.2445166-1-f4bug@amsat.org -> patchew/20201109090422.2445166-1-f4bug@amsat.org
 - [tag update]      patchew/20201109162621.18885-1-peter.maydell@linaro.org -> patchew/20201109162621.18885-1-peter.maydell@linaro.org
 * [new tag]         patchew/20201109172755.16500-1-cfontana@suse.de -> patchew/20201109172755.16500-1-cfontana@suse.de
Switched to a new branch 'test'
79d85c4 module: add priority to module_init
c947a1f i386: split cpu.c and defer x86 models registration
22999b7 module: introduce MODULE_INIT_ACCEL_CPU
41dd5f6 i386: move TCG cpu class initialization out of helper.c
09b68b7 i386: move cpu dump out of helper.c into cpu-dump.c
dd91165 i386: move TCG accel files into accel/tcg/
c341f6d i386: move hvf accel files into accel/hvf/
76dbf66 i386: move hax accel files to accel/hax/
2c0221e i386: move whpx accel files to accel/whpx/
41d7cb1 i386: move kvm accel files into accel/kvm/

=== OUTPUT BEGIN ===
1/10 Checking commit 41d7cb1d063e (i386: move kvm accel files into accel/kvm/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#128: 
rename from target/i386/hyperv-proto.h

total: 0 errors, 1 warnings, 150 lines checked

Patch 1/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/10 Checking commit 2c0221e3dcf3 (i386: move whpx accel files to accel/whpx/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#27: 
new file mode 100644

total: 0 errors, 1 warnings, 32 lines checked

Patch 2/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/10 Checking commit 76dbf6695e74 (i386: move hax accel files to accel/hax/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#25: 
rename from target/i386/hax-all.c

total: 0 errors, 1 warnings, 47 lines checked

Patch 3/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/10 Checking commit c341f6d31a78 (i386: move hvf accel files into accel/hvf/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#26: 
rename from target/i386/hvf/README.md

total: 0 errors, 1 warnings, 17 lines checked

Patch 4/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/10 Checking commit dd91165f2ce0 (i386: move TCG accel files into accel/tcg/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#12: 
rename from target/i386/bpt_helper.c

total: 0 errors, 1 warnings, 39 lines checked

Patch 5/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/10 Checking commit 09b68b7a3ccb (i386: move cpu dump out of helper.c into cpu-dump.c)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#11: 
new file mode 100644

ERROR: braces {} are necessary for all arms of this statement
#128: FILE: target/i386/cpu-dump.c:113:
+    if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
[...]

WARNING: Block comments use a leading /* on a separate line
#172: FILE: target/i386/cpu-dump.c:157:
+/* ARRAY_SIZE check is not required because

WARNING: Block comments use a leading /* on a separate line
#211: FILE: target/i386/cpu-dump.c:196:
+/* ARRAY_SIZE check is not required because

ERROR: line over 90 characters
#373: FILE: target/i386/cpu-dump.c:358:
+        qemu_fprintf(f, "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"

ERROR: line over 90 characters
#374: FILE: target/i386/cpu-dump.c:359:
+                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"

ERROR: line over 90 characters
#375: FILE: target/i386/cpu-dump.c:360:
+                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"

ERROR: line over 90 characters
#376: FILE: target/i386/cpu-dump.c:361:
+                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"

ERROR: line over 90 characters
#377: FILE: target/i386/cpu-dump.c:362:
+                     "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",

ERROR: space required before the open parenthesis '('
#436: FILE: target/i386/cpu-dump.c:421:
+    for(i = 0; i < 6; i++) {

WARNING: line over 80 characters
#448: FILE: target/i386/cpu-dump.c:433:
+        qemu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",

ERROR: space required before the open parenthesis '('
#453: FILE: target/i386/cpu-dump.c:438:
+        for(i = 0; i < 4; i++)

ERROR: braces {} are necessary for all arms of this statement
#453: FILE: target/i386/cpu-dump.c:438:
+        for(i = 0; i < 4; i++)
[...]

ERROR: space required before the open parenthesis '('
#469: FILE: target/i386/cpu-dump.c:454:
+        for(i = 0; i < 4; i++) {

ERROR: braces {} are necessary for all arms of this statement
#476: FILE: target/i386/cpu-dump.c:461:
+        if ((unsigned)env->cc_op < CC_OP_NB)
[...]
+        else
[...]

WARNING: line over 80 characters
#477: FILE: target/i386/cpu-dump.c:462:
+            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);

ERROR: space required before the open parenthesis '('
#497: FILE: target/i386/cpu-dump.c:482:
+        for(i = 0; i < 8; i++) {

ERROR: spaces required around that '=' (ctx:VxV)
#507: FILE: target/i386/cpu-dump.c:492:
+        for(i=0;i<8;i++) {
              ^

ERROR: space required after that ';' (ctx:VxV)
#507: FILE: target/i386/cpu-dump.c:492:
+        for(i=0;i<8;i++) {
                ^

ERROR: spaces required around that '<' (ctx:VxV)
#507: FILE: target/i386/cpu-dump.c:492:
+        for(i=0;i<8;i++) {
                  ^

ERROR: space required after that ';' (ctx:VxV)
#507: FILE: target/i386/cpu-dump.c:492:
+        for(i=0;i<8;i++) {
                    ^

ERROR: space required before the open parenthesis '('
#507: FILE: target/i386/cpu-dump.c:492:
+        for(i=0;i<8;i++) {

ERROR: braces {} are necessary for all arms of this statement
#512: FILE: target/i386/cpu-dump.c:497:
+            if ((i & 1) == 1)
[...]
+            else
[...]

ERROR: braces {} are necessary for all arms of this statement
#517: FILE: target/i386/cpu-dump.c:502:
+        if (env->hflags & HF_CS64_MASK)
[...]
+        else
[...]

ERROR: spaces required around that '=' (ctx:VxV)
#521: FILE: target/i386/cpu-dump.c:506:
+        for(i=0;i<nb;i++) {
              ^

ERROR: space required after that ';' (ctx:VxV)
#521: FILE: target/i386/cpu-dump.c:506:
+        for(i=0;i<nb;i++) {
                ^

ERROR: spaces required around that '<' (ctx:VxV)
#521: FILE: target/i386/cpu-dump.c:506:
+        for(i=0;i<nb;i++) {
                  ^

ERROR: space required after that ';' (ctx:VxV)
#521: FILE: target/i386/cpu-dump.c:506:
+        for(i=0;i<nb;i++) {
                     ^

ERROR: space required before the open parenthesis '('
#521: FILE: target/i386/cpu-dump.c:506:
+        for(i=0;i<nb;i++) {

ERROR: braces {} are necessary for all arms of this statement
#528: FILE: target/i386/cpu-dump.c:513:
+            if ((i & 1) == 1)
[...]
+            else
[...]

total: 25 errors, 5 warnings, 1078 lines checked

Patch 6/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

7/10 Checking commit 41dd5f6ce813 (i386: move TCG cpu class initialization out of helper.c)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#466: 
new file mode 100644

total: 0 errors, 1 warnings, 610 lines checked

Patch 7/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/10 Checking commit 22999b75bce2 (module: introduce MODULE_INIT_ACCEL_CPU)
9/10 Checking commit c947a1fbb439 (i386: split cpu.c and defer x86 models registration)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#90: 
new file mode 100644

WARNING: line over 80 characters
#549: FILE: target/i386/accel/tcg/tcg-cpu-type.c:101:
+    memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);

total: 0 errors, 2 warnings, 1501 lines checked

Patch 9/10 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
10/10 Checking commit 79d85c44139c (module: add priority to module_init)
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20201109172755.16500-1-cfontana@suse.de/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
  2020-11-09 17:34   ` Paolo Bonzini
  2020-11-09 17:37   ` Paolo Bonzini
@ 2020-11-09 18:03   ` Daniel P. Berrangé
  2020-11-10  9:40     ` Claudio Fontana
  2020-11-09 19:04   ` Eduardo Habkost
  3 siblings, 1 reply; 33+ messages in thread
From: Daniel P. Berrangé @ 2020-11-09 18:03 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Eduardo Habkost,
	Colin Xu, Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Cameron Esfahani,
	haxm-team, Wenchao Wang, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson

On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
> 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-type.c   KVM x86 cpu type
> hvf-cpu-type.c   HVF x86 cpu type
> tcg-cpu-type.c   TCG x86 cpu type
> 
> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
> so that accel-specific types can be used as parent types for all
> cpu models. Use the generic TYPE_X86_CPU only if no
> accel-specific specialization is enabled.

Can you give more info on why this is needed and/or desirable ?

Dynamically changing the class hierarchy of CPUs at runtime feels
like a rather suspicious approach to me.

It is contrary to work we've been doing recently to try to make all
classes be fully statically defined by getting rid of dynamic properties,
such that introspection of classes does not depend on other CLI flags
you might have passed.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
                     ` (2 preceding siblings ...)
  2020-11-09 18:03   ` Daniel P. Berrangé
@ 2020-11-09 19:04   ` Eduardo Habkost
  2020-11-10  9:49     ` Claudio Fontana
  3 siblings, 1 reply; 33+ messages in thread
From: Eduardo Habkost @ 2020-11-09 19:04 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Stefano Stabellini, Markus Armbruster, Bruce Rogers,
	Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Cameron Esfahani, Dario Faggioli,
	Roman Bolshakov, Sunil Muthuswamy, John Snow, Richard Henderson,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
> 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-type.c   KVM x86 cpu type
> hvf-cpu-type.c   HVF x86 cpu type
> tcg-cpu-type.c   TCG x86 cpu type
> 
> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
> so that accel-specific types can be used as parent types for all
> cpu models. Use the generic TYPE_X86_CPU only if no
> accel-specific specialization is enabled.

This is very unfriendly to introspection, I don't think this is
the direction we want to go with the QOM type hierarchy.

Why do you need inheritance here?  accel-specific behavior can be
delegated to a separate object, instead of requiring the CPU
object to inherit from a accel-specific class.

In case inheritance is really the best mechanism for this, I'd
prefer to register accel-specific subclasses unconditionally, and
make cpu_class_by_name() resolve to the right accel-specific
class name.

> 
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
>  bsd-user/main.c                      |   4 +
>  hw/i386/pc_piix.c                    |   1 +
>  linux-user/main.c                    |  10 +-
>  softmmu/vl.c                         |   2 +-
>  target/i386/accel/hvf/hvf-cpu-type.c |  78 +++++
>  target/i386/accel/hvf/meson.build    |   1 +
>  target/i386/accel/kvm/kvm-cpu-type.c | 161 ++++++++++
>  target/i386/accel/kvm/kvm-cpu-type.h |  41 +++
>  target/i386/accel/kvm/kvm.c          |   3 +-
>  target/i386/accel/kvm/meson.build    |   7 +-
>  target/i386/accel/tcg/meson.build    |   3 +-
>  target/i386/accel/tcg/tcg-cpu-type.c | 176 +++++++++++
>  target/i386/accel/tcg/tcg-cpu-type.h |  25 ++
>  target/i386/cpu.c                    | 454 +++++----------------------
>  target/i386/cpu.h                    |  26 +-
>  target/i386/host-cpu.c               | 201 ++++++++++++
>  target/i386/host-cpu.h               |  21 ++
>  target/i386/meson.build              |   8 +-
>  target/i386/tcg-cpu.c                |  71 -----
>  target/i386/tcg-cpu.h                |  15 -
>  20 files changed, 834 insertions(+), 474 deletions(-)
>  create mode 100644 target/i386/accel/hvf/hvf-cpu-type.c
>  create mode 100644 target/i386/accel/kvm/kvm-cpu-type.c
>  create mode 100644 target/i386/accel/kvm/kvm-cpu-type.h
>  create mode 100644 target/i386/accel/tcg/tcg-cpu-type.c
>  create mode 100644 target/i386/accel/tcg/tcg-cpu-type.h
>  create mode 100644 target/i386/host-cpu.c
>  create mode 100644 target/i386/host-cpu.h
>  delete mode 100644 target/i386/tcg-cpu.c
>  delete mode 100644 target/i386/tcg-cpu.h
> 
> diff --git a/bsd-user/main.c b/bsd-user/main.c
> index ac40d79bfa..48dd4b8ba5 100644
> --- a/bsd-user/main.c
> +++ b/bsd-user/main.c
> @@ -911,6 +911,10 @@ int main(int argc, char **argv)
>  
>      /* init tcg before creating CPUs and to get qemu_host_page_size */
>      tcg_exec_init(0);
> +    /*
> +     * TCG has been initialized, now it is time to register the cpu models.
> +     */
> +    module_call_init(MODULE_INIT_ACCEL_CPU);
>  
>      cpu_type = parse_cpu_option(cpu_model);
>      cpu = cpu_create(cpu_type);
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 13d1628f13..a59c3e1457 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 "accel/kvm/kvm-cpu-type.h"
>  
>  #define MAX_IDE_BUS 2
>  
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 75c9785157..86ebd5db5e 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -699,14 +699,18 @@ int main(int argc, char **argv, char **envp)
>          }
>      }
>  
> +    /* init tcg before creating CPUs and to get qemu_host_page_size */
> +    tcg_exec_init(0);
> +    /*
> +     * TCG has been initialized, now it is time to register the cpu models.
> +     */
> +    module_call_init(MODULE_INIT_ACCEL_CPU);
> +
>      if (cpu_model == NULL) {
>          cpu_model = cpu_get_model(get_elf_eflags(execfd));
>      }
>      cpu_type = parse_cpu_option(cpu_model);
>  
> -    /* init tcg before creating CPUs and to get qemu_host_page_size */
> -    tcg_exec_init(0);
> -
>      cpu = cpu_create(cpu_type);
>      env = cpu->env_ptr;
>      cpu_reset(cpu);
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 6a6363902d..47cc938cef 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -4176,7 +4176,7 @@ void qemu_init(int argc, char **argv, char **envp)
>  
>      /*
>       * accelerator has been chosen and initialized, now it is time to
> -     * register the cpu accel interface.
> +     * register the cpu models, and the cpu accel interface.
>       */
>      module_call_init(MODULE_INIT_ACCEL_CPU);
>  
> diff --git a/target/i386/accel/hvf/hvf-cpu-type.c b/target/i386/accel/hvf/hvf-cpu-type.c
> new file mode 100644
> index 0000000000..dfe4ec4e9e
> --- /dev/null
> +++ b/target/i386/accel/hvf/hvf-cpu-type.c
> @@ -0,0 +1,78 @@
> +/*
> + * 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 "hvf-cpu-type.h"
> +#include "qapi/error.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/boards.h"
> +#include "sysemu/hvf.h"
> +
> +
> +static void hvf_cpu_common_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->realize = host_cpu_realizefn;
> +}
> +
> +static void hvf_cpu_max_initfn(Object *obj)
> +{
> +    X86CPU *cpu = X86_CPU(obj);
> +    CPUX86State *env = &cpu->env;
> +
> +    host_cpu_max_initfn(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_initfn(Object *obj)
> +{
> +    X86CPU *cpu = X86_CPU(obj);
> +
> +    host_cpu_initfn(obj);
> +
> +    /* Special cases not set in the X86CPUDefinition structs: */
> +    /* TODO: in-kernel irqchip for hvf */
> +
> +    if (cpu->max_features) {
> +        hvf_cpu_max_initfn(obj);
> +    }
> +}
> +
> +static const TypeInfo hvf_cpu_type_info = {
> +    .name = X86_CPU_TYPE_NAME("hvf"),
> +    .parent = TYPE_X86_CPU,
> +
> +    .instance_init = hvf_cpu_initfn,
> +    .class_init = hvf_cpu_common_class_init,
> +};
> +
> +static void hvf_cpu_register_base_type(void)
> +{
> +    type_register_static(&hvf_cpu_type_info);
> +}
> +
> +type_init(hvf_cpu_register_base_type);
> +
> +void hvf_cpu_type_init(void)
> +{
> +    if (hvf_enabled()) {
> +        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("hvf"));
> +    }
> +}
> +
> +accel_cpu_init(hvf_cpu_type_init);
> diff --git a/target/i386/accel/hvf/meson.build b/target/i386/accel/hvf/meson.build
> index 409c9a3f14..785dee72fc 100644
> --- a/target/i386/accel/hvf/meson.build
> +++ b/target/i386/accel/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',
> +  'hvf-cpu-type.c',
>  ))
> diff --git a/target/i386/accel/kvm/kvm-cpu-type.c b/target/i386/accel/kvm/kvm-cpu-type.c
> new file mode 100644
> index 0000000000..f696f21e2b
> --- /dev/null
> +++ b/target/i386/accel/kvm/kvm-cpu-type.c
> @@ -0,0 +1,161 @@
> +/*
> + * 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-type.h"
> +#include "qapi/error.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/boards.h"
> +
> +#include "kvm_i386.h"
> +
> +/* this information overloads the TYPE_X86_CPU type in x86-cpu.c */
> +
> +static void kvm_cpu_realizefn(DeviceState *dev, Error **errp)
> +{
> +    X86CPU *cpu = X86_CPU(dev);
> +    CPUX86State *env = &cpu->env;
> +
> +    /*
> +     * also for KVM the realize order is important, since
> +     * x86_cpu_realize() checks if nothing else has been set by the user,
> +     * or by the specialized x86 cpus (KVM, HVF) in
> +     * cpu->ucode_rev and cpu->phys_bits.
> +     *
> +     * So it's 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(dev, errp);
> +}
> +
> +static void kvm_cpu_common_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    dc->realize = kvm_cpu_realizefn;
> +}
> +
> +/*
> + * 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_initfn(Object *obj)
> +{
> +    X86CPU *cpu = X86_CPU(obj);
> +    CPUX86State *env = &cpu->env;
> +    KVMState *s = kvm_state;
> +
> +    host_cpu_max_initfn(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_initfn(Object *obj)
> +{
> +    X86CPU *cpu = X86_CPU(obj);
> +
> +    host_cpu_initfn(obj);
> +
> +    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_initfn(obj);
> +    }
> +}
> +
> +static const TypeInfo kvm_cpu_type_info = {
> +    .name = X86_CPU_TYPE_NAME("kvm"),
> +    .parent = TYPE_X86_CPU,
> +
> +    .instance_init = kvm_cpu_initfn,
> +    .class_init = kvm_cpu_common_class_init,
> +};
> +
> +static void kvm_cpu_register_base_type(void)
> +{
> +    type_register_static(&kvm_cpu_type_info);
> +}
> +
> +type_init(kvm_cpu_register_base_type);
> +
> +void kvm_cpu_type_init(void)
> +{
> +    if (kvm_enabled()) {
> +        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("kvm"));
> +        host_cpu_type_init();
> +    }
> +}
> +
> +accel_cpu_init(kvm_cpu_type_init);
> diff --git a/target/i386/accel/kvm/kvm-cpu-type.h b/target/i386/accel/kvm/kvm-cpu-type.h
> new file mode 100644
> index 0000000000..2448f49222
> --- /dev/null
> +++ b/target/i386/accel/kvm/kvm-cpu-type.h
> @@ -0,0 +1,41 @@
> +/*
> + * i386 KVM CPU type 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/>.
> + */
> +
> +#ifndef KVM_CPU_TYPE_H
> +#define KVM_CPU_TYPE_H
> +
> +#ifdef CONFIG_KVM
> +void kvm_cpu_type_init(void);
> +
> +/*
> + * 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_TYPE_H */
> diff --git a/target/i386/accel/kvm/kvm.c b/target/i386/accel/kvm/kvm.c
> index cf46259534..829730d3c2 100644
> --- a/target/i386/accel/kvm/kvm.c
> +++ b/target/i386/accel/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/accel/kvm/meson.build b/target/i386/accel/kvm/meson.build
> index 1d66559187..b6b32166b4 100644
> --- a/target/i386/accel/kvm/meson.build
> +++ b/target/i386/accel/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',
> +  'kvm-cpu-type.c',
> +))
> +
>  i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
> diff --git a/target/i386/accel/tcg/meson.build b/target/i386/accel/tcg/meson.build
> index 02794226c2..211ecef5f9 100644
> --- a/target/i386/accel/tcg/meson.build
> +++ b/target/i386/accel/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',
> +  'tcg-cpu-type.c'), if_false: files('tcg-stub.c'))
> diff --git a/target/i386/accel/tcg/tcg-cpu-type.c b/target/i386/accel/tcg/tcg-cpu-type.c
> new file mode 100644
> index 0000000000..f0ee4ef5f7
> --- /dev/null
> +++ b/target/i386/accel/tcg/tcg-cpu-type.c
> @@ -0,0 +1,176 @@
> +/*
> + * 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 "tcg-cpu-type.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(DeviceState *dev, Error **errp)
> +{
> +    X86CPU *cpu = X86_CPU(dev);
> +    CPUState *cs = CPU(dev);
> +
> +    /*
> +     * also for TCG the realize order is important,
> +     * as the memory regions initialized here are needed
> +     * in x86_cpu_realizefn()
> +     */
> +    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);
> +
> +    /* call the generic x86_cpu_realizefn() after regions initialized */
> +    x86_cpu_realizefn(dev, errp);
> +}
> +#endif /* !CONFIG_USER_ONLY */
> +
> +static void tcg_cpu_common_class_init(ObjectClass *oc, void *data)
> +{
> +    CPUClass *cc = CPU_CLASS(oc);
> +#ifndef CONFIG_USER_ONLY
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->realize = tcg_cpu_realizefn;
> +#endif /* !CONFIG_USER_ONLY */
> +
> +    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_initfn(Object *obj)
> +{
> +    X86CPU *cpu = X86_CPU(obj);
> +
> +    /* Special cases not set in the X86CPUDefinition structs: */
> +    x86_cpu_apply_props(cpu, tcg_default_props);
> +}
> +
> +static const TypeInfo tcg_cpu_type_info = {
> +    .name = X86_CPU_TYPE_NAME("tcg"),
> +    .parent = TYPE_X86_CPU,
> +
> +    .instance_init = tcg_cpu_initfn,
> +    .class_init = tcg_cpu_common_class_init,
> +};
> +
> +static void tcg_cpu_register_base_type(void)
> +{
> +    type_register_static(&tcg_cpu_type_info);
> +}
> +
> +type_init(tcg_cpu_register_base_type);
> +
> +void tcg_cpu_type_init(void)
> +{
> +    if (tcg_enabled()) {
> +        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("tcg"));
> +    }
> +}
> +
> +accel_cpu_init(tcg_cpu_type_init);
> diff --git a/target/i386/accel/tcg/tcg-cpu-type.h b/target/i386/accel/tcg/tcg-cpu-type.h
> new file mode 100644
> index 0000000000..d741a8f6be
> --- /dev/null
> +++ b/target/i386/accel/tcg/tcg-cpu-type.h
> @@ -0,0 +1,25 @@
> +/*
> + * i386 TCG CPU type 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/>.
> + */
> +
> +#ifndef TCG_CPU_TYPE_H
> +#define TCG_CPU_TYPE_H
> +
> +void tcg_cpu_type_init(void);
> +
> +#endif /* TCG_CPU_TYPE_H */
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index b185789d88..b547c9d39d 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,27 +32,17 @@
>  #include "sysemu/xen.h"
>  #include "accel/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
>  #include "exec/address-spaces.h"
>  #include "hw/i386/apic_internal.h"
> @@ -594,8 +582,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 +1551,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 +1575,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 +4071,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 +4112,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),
> @@ -4246,98 +4131,38 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
>      device_class_set_props(dc, max_x86_cpu_properties);
>  }
>  
> -static void max_x86_cpu_initfn(Object *obj)
> +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 = {
> +static TypeInfo max_x86_cpu_type_info = {
>      .name = X86_CPU_TYPE_NAME("max"),
> -    .parent = TYPE_X86_CPU,
> -    .instance_init = max_x86_cpu_initfn,
> +    .parent = NULL, /* set by x86_cpu_register_cpu_models */
> +
>      .class_init = max_x86_cpu_class_init,
> +    .instance_init = max_x86_cpu_initfn,
>  };
>  
> -#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 +4888,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 +4935,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 +4961,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 +4970,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);
>  
> @@ -5400,12 +5208,13 @@ static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
>      cc->deprecation_note = model->cpudef->deprecation_note;
>  }
>  
> -static void x86_register_cpu_model_type(const char *name, X86CPUModel *model)
> +static void x86_register_cpu_model_type(const char *name, X86CPUModel *model,
> +                                        const char *parent_type)
>  {
>      g_autofree char *typename = x86_cpu_type_name(name);
>      TypeInfo ti = {
>          .name = typename,
> -        .parent = TYPE_X86_CPU,
> +        .parent = parent_type,
>          .class_init = x86_cpu_cpudef_class_init,
>          .class_data = model,
>      };
> @@ -5413,7 +5222,8 @@ static void x86_register_cpu_model_type(const char *name, X86CPUModel *model)
>      type_register(&ti);
>  }
>  
> -static void x86_register_cpudef_types(X86CPUDefinition *def)
> +static void x86_register_cpudef(X86CPUDefinition *def,
> +                                const char *parent_type)
>  {
>      X86CPUModel *m;
>      const X86CPUVersionDefinition *vdef;
> @@ -5430,7 +5240,7 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
>      m->cpudef = def;
>      m->version = CPU_VERSION_AUTO;
>      m->is_alias = true;
> -    x86_register_cpu_model_type(def->name, m);
> +    x86_register_cpu_model_type(def->name, m, parent_type);
>  
>      /* Versioned models: */
>  
> @@ -5441,14 +5251,14 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
>          m->cpudef = def;
>          m->version = vdef->version;
>          m->note = vdef->note;
> -        x86_register_cpu_model_type(name, m);
> +        x86_register_cpu_model_type(name, m, parent_type);
>  
>          if (vdef->alias) {
>              X86CPUModel *am = g_new0(X86CPUModel, 1);
>              am->cpudef = def;
>              am->version = vdef->version;
>              am->is_alias = true;
> -            x86_register_cpu_model_type(vdef->alias, am);
> +            x86_register_cpu_model_type(vdef->alias, am, parent_type);
>          }
>      }
>  
> @@ -6192,53 +6002,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) {
> @@ -6512,7 +6281,7 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
>      }
>  }
>  
> -static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
> +void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>  {
>      CPUState *cs = CPU(dev);
>      X86CPU *cpu = X86_CPU(dev);
> @@ -6521,27 +6290,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;
> -        }
> -    }
> +    /*
> +     * For accelerators that specialize the x86 cpu,
> +     * this common code must be called after the accelerator-specific realizefn.
> +     */
>  
> -    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 +6350,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 +6358,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,32 +6429,7 @@ 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
> +    /* XXX this is the place for tcg region initialization XXX */
>  
>      qemu_init_vcpu(cs);
>  
> @@ -6932,7 +6632,7 @@ static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v,
>  }
>  #endif /* !CONFIG_USER_ONLY */
>  
> -static void x86_cpu_initfn(Object *obj)
> +void x86_cpu_initfn(Object *obj)
>  {
>      X86CPU *cpu = X86_CPU(obj);
>      X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
> @@ -7230,7 +6930,7 @@ static Property x86_cpu_properties[] = {
>      DEFINE_PROP_END_OF_LIST()
>  };
>  
> -static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
> +void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>  {
>      X86CPUClass *xcc = X86_CPU_CLASS(oc);
>      CPUClass *cc = CPU_CLASS(oc);
> @@ -7249,10 +6949,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>      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;
> @@ -7341,25 +7037,49 @@ static void x86_cpu_base_class_init(ObjectClass *oc, void *data)
>      xcc->ordering = 8;
>  }
>  
> -static const TypeInfo x86_base_cpu_type_info = {
> -        .name = X86_CPU_TYPE_NAME("base"),
> -        .parent = TYPE_X86_CPU,
> -        .class_init = x86_cpu_base_class_init,
> +static TypeInfo x86_base_cpu_type_info = {
> +    .name = X86_CPU_TYPE_NAME("base"),
> +    .parent = NULL, /* set by x86_cpu_register_cpu_models */
> +
> +    .class_init = x86_cpu_base_class_init,
>  };
>  
> -static void x86_cpu_register_types(void)
> +/*
> + * x86 cpu types are only registered once accelerator is determined,
> + * passing the parent cpu type as an argument here.
> + */
> +void x86_cpu_register_cpu_models(const char *parent_type)
>  {
>      int i;
>  
> -    type_register_static(&x86_cpu_type_info);
>      for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
> -        x86_register_cpudef_types(&builtin_x86_defs[i]);
> +        x86_register_cpudef(&builtin_x86_defs[i], parent_type);
> +    }
> +    max_x86_cpu_type_info.parent = parent_type;
> +    type_register(&max_x86_cpu_type_info);
> +
> +    x86_base_cpu_type_info.parent = parent_type;
> +    type_register(&x86_base_cpu_type_info);
> +}
> +
> +static void x86_cpu_register_base_type(void)
> +{
> +    type_register_static(&x86_cpu_type_info);
> +}
> +
> +type_init(x86_cpu_register_base_type);
> +
> +/*
> + * generic initializer if no other specialization.
> + */
> +static void x86_cpu_type_init(void)
> +{
> +    /*
> +     * I would like something better than this check.
> +     */
> +    if (!tcg_enabled() && !kvm_enabled() && !hvf_enabled()) {
> +        x86_cpu_register_cpu_models(TYPE_X86_CPU);
>      }
> -    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_init(x86_cpu_register_types)
> +accel_cpu_init(x86_cpu_type_init);
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index f1bce16b53..9232672eb2 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1905,13 +1905,26 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo,
>                             void *puc);
>  
>  /* cpu.c */
> +void x86_cpu_register_cpu_models(const char *parent_type);
> +
> +void x86_cpu_initfn(Object *obj);
> +void max_x86_cpu_initfn(Object *obj);
> +void x86_cpu_realizefn(DeviceState *dev, Error **errp);
> +void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
> +                              uint32_t vendor2, uint32_t vendor3);
> +void x86_cpu_common_class_init(ObjectClass *oc, void *data);
> +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 +2124,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..65a0119f4b
> --- /dev/null
> +++ b/target/i386/host-cpu.c
> @@ -0,0 +1,201 @@
> +/*
> + * 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(DeviceState *dev, Error **errp)
> +{
> +    X86CPU *cpu = X86_CPU(dev);
> +    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);
> +    }
> +    x86_cpu_realizefn(dev, 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_initfn(Object *obj)
> +{
> +    X86CPU *cpu = X86_CPU(obj);
> +    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_initfn(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("%s processor with all supported host features ",
> +                        ACCEL_GET_CLASS(current_accel())->name);
> +}
> +
> +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,
> +};
> +
> +void host_cpu_type_init(void)
> +{
> +    type_register(&host_cpu_type_info);
> +}
> diff --git a/target/i386/host-cpu.h b/target/i386/host-cpu.h
> new file mode 100644
> index 0000000000..e9d4726833
> --- /dev/null
> +++ b/target/i386/host-cpu.h
> @@ -0,0 +1,21 @@
> +/*
> + * x86 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.
> + */
> +
> +#ifndef HOST_CPU_TYPE_H
> +#define HOST_CPU_TYPE_H
> +
> +void host_cpu_type_init(void);
> +
> +void host_cpu_initfn(Object *obj);
> +void host_cpu_realizefn(DeviceState *dev, Error **errp);
> +void host_cpu_max_initfn(X86CPU *cpu);
> +
> +void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping);
> +
> +#endif /* HOST_CPU_TYPE_H */
> diff --git a/target/i386/meson.build b/target/i386/meson.build
> index 50c8fba6cb..c84b0d6965 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 */
> -- 
> 2.26.2
> 

-- 
Eduardo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 18:03   ` Daniel P. Berrangé
@ 2020-11-10  9:40     ` Claudio Fontana
  2020-11-10 10:04       ` Daniel P. Berrangé
  0 siblings, 1 reply; 33+ messages in thread
From: Claudio Fontana @ 2020-11-10  9:40 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Eduardo Habkost,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, haxm-team,
	Colin Xu, Anthony Perard, Paolo Bonzini, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson, Wenchao Wang

On 11/9/20 7:03 PM, Daniel P. Berrangé wrote:
> On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
>> 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-type.c   KVM x86 cpu type
>> hvf-cpu-type.c   HVF x86 cpu type
>> tcg-cpu-type.c   TCG x86 cpu type
>>
>> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
>> so that accel-specific types can be used as parent types for all
>> cpu models. Use the generic TYPE_X86_CPU only if no
>> accel-specific specialization is enabled.
> 
> Can you give more info on why this is needed and/or desirable ?

Hello Daniel, there is a pointer to the overall higher level motivation in the cover letter.

But I am not pushing for this specific mechanism to be used, as mentioned in the cover letter.

If we need another mechanism to achieve that (not delaying the x86 model registration and make them inherit from the specialized class), but something else,
I would be happy to get additional ideas.

> 
> Dynamically changing the class hierarchy of CPUs at runtime feels
> like a rather suspicious approach to me

TYPE_X86_CPU is base type is registered as usual.
New accel-specialized types are defined (TYPE_TCG_CPU, TYPE_KVM_CPU, TYPE_HVF_CPU), also using normal type registration.

The missing step is how to adapt all the cpu models to use the functionality.

The accelerator that is finally chosen to be used is only known at a specific point in the qemu initialization.
This point of time I defined as MODULE_INIT_ACCEL_CPU.

That is the time when we know how the CPU should actually really behave (how it should be realized, etc).

In this series I realized this by registering the cpu models only at MODULE_INIT_ACCEL_CPU time, and not earlier.
But maybe there is a better idea on how to do it, and I am all ears.

.
> 
> It is contrary to work we've been doing recently to try to make all
> classes be fully statically defined by getting rid of dynamic properties,
> such that introspection of classes does not depend on other CLI flags
> you might have passed.

Understood, this goes against other requirements.

The dynamism introduced here is to register the cpu models at MODULE_INIT_ACCEL_CPU time instead of MODULE_INIT_QOM time.
As a result, for any chosen accelerator, the type tree and class tree is identical.

So maybe there is a way to leverage this to accommodate both needs?

> 
> 
> Regards,
> Daniel
> 



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-09 19:04   ` Eduardo Habkost
@ 2020-11-10  9:49     ` Claudio Fontana
  0 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-10  9:49 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Paul Durrant, Jason Wang, qemu-devel, Peter Xu, haxm-team,
	Colin Xu, Stefano Stabellini, Markus Armbruster, Bruce Rogers,
	Anthony Perard, Philippe Mathieu-Daudé,
	Laurent Vivier, Thomas Huth, Cameron Esfahani, Dario Faggioli,
	Roman Bolshakov, Sunil Muthuswamy, John Snow, Richard Henderson,
	Marcelo Tosatti, Wenchao Wang, Paolo Bonzini

Hello Eduardo,

thank you for your answer,

On 11/9/20 8:04 PM, Eduardo Habkost wrote:
> On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
>> 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-type.c   KVM x86 cpu type
>> hvf-cpu-type.c   HVF x86 cpu type
>> tcg-cpu-type.c   TCG x86 cpu type
>>
>> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
>> so that accel-specific types can be used as parent types for all
>> cpu models. Use the generic TYPE_X86_CPU only if no
>> accel-specific specialization is enabled.
> 
> This is very unfriendly to introspection, I don't think this is
> the direction we want to go with the QOM type hierarchy.
> 
> Why do you need inheritance here?  accel-specific behavior can be
> delegated to a separate object, instead of requiring the CPU
> object to inherit from a accel-specific class.


Looking in detail at QOM CPU I got the impression that really it's inheritance that makes sense here,
it just flows correctly I think from an OOP perspective.

I'd note that it's not really the specialized cpu types that are the problem.
TYPE_TCG_CPU , TYPE_KVM_CPU are defined statically as usual during MODULE_INIT_QOM time.

That part actually works surprisingly well and seems just the right thing to do to me.

It's the second step that is the contentious one I think, ie the CPU models registration.


> 
> In case inheritance is really the best mechanism for this, I'd
> prefer to register accel-specific subclasses unconditionally, and


Indeed, accel-specific sub types are already registered unconditionally.


> make cpu_class_by_name() resolve to the right accel-specific
> class name.


Ah! I'll look at this!
This might point into a new direction.

Thanks!

Claudio



> 
>>
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
>>  bsd-user/main.c                      |   4 +
>>  hw/i386/pc_piix.c                    |   1 +
>>  linux-user/main.c                    |  10 +-
>>  softmmu/vl.c                         |   2 +-
>>  target/i386/accel/hvf/hvf-cpu-type.c |  78 +++++
>>  target/i386/accel/hvf/meson.build    |   1 +
>>  target/i386/accel/kvm/kvm-cpu-type.c | 161 ++++++++++
>>  target/i386/accel/kvm/kvm-cpu-type.h |  41 +++
>>  target/i386/accel/kvm/kvm.c          |   3 +-
>>  target/i386/accel/kvm/meson.build    |   7 +-
>>  target/i386/accel/tcg/meson.build    |   3 +-
>>  target/i386/accel/tcg/tcg-cpu-type.c | 176 +++++++++++
>>  target/i386/accel/tcg/tcg-cpu-type.h |  25 ++
>>  target/i386/cpu.c                    | 454 +++++----------------------
>>  target/i386/cpu.h                    |  26 +-
>>  target/i386/host-cpu.c               | 201 ++++++++++++
>>  target/i386/host-cpu.h               |  21 ++
>>  target/i386/meson.build              |   8 +-
>>  target/i386/tcg-cpu.c                |  71 -----
>>  target/i386/tcg-cpu.h                |  15 -
>>  20 files changed, 834 insertions(+), 474 deletions(-)
>>  create mode 100644 target/i386/accel/hvf/hvf-cpu-type.c
>>  create mode 100644 target/i386/accel/kvm/kvm-cpu-type.c
>>  create mode 100644 target/i386/accel/kvm/kvm-cpu-type.h
>>  create mode 100644 target/i386/accel/tcg/tcg-cpu-type.c
>>  create mode 100644 target/i386/accel/tcg/tcg-cpu-type.h
>>  create mode 100644 target/i386/host-cpu.c
>>  create mode 100644 target/i386/host-cpu.h
>>  delete mode 100644 target/i386/tcg-cpu.c
>>  delete mode 100644 target/i386/tcg-cpu.h
>>
>> diff --git a/bsd-user/main.c b/bsd-user/main.c
>> index ac40d79bfa..48dd4b8ba5 100644
>> --- a/bsd-user/main.c
>> +++ b/bsd-user/main.c
>> @@ -911,6 +911,10 @@ int main(int argc, char **argv)
>>  
>>      /* init tcg before creating CPUs and to get qemu_host_page_size */
>>      tcg_exec_init(0);
>> +    /*
>> +     * TCG has been initialized, now it is time to register the cpu models.
>> +     */
>> +    module_call_init(MODULE_INIT_ACCEL_CPU);
>>  
>>      cpu_type = parse_cpu_option(cpu_model);
>>      cpu = cpu_create(cpu_type);
>> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
>> index 13d1628f13..a59c3e1457 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 "accel/kvm/kvm-cpu-type.h"
>>  
>>  #define MAX_IDE_BUS 2
>>  
>> diff --git a/linux-user/main.c b/linux-user/main.c
>> index 75c9785157..86ebd5db5e 100644
>> --- a/linux-user/main.c
>> +++ b/linux-user/main.c
>> @@ -699,14 +699,18 @@ int main(int argc, char **argv, char **envp)
>>          }
>>      }
>>  
>> +    /* init tcg before creating CPUs and to get qemu_host_page_size */
>> +    tcg_exec_init(0);
>> +    /*
>> +     * TCG has been initialized, now it is time to register the cpu models.
>> +     */
>> +    module_call_init(MODULE_INIT_ACCEL_CPU);
>> +
>>      if (cpu_model == NULL) {
>>          cpu_model = cpu_get_model(get_elf_eflags(execfd));
>>      }
>>      cpu_type = parse_cpu_option(cpu_model);
>>  
>> -    /* init tcg before creating CPUs and to get qemu_host_page_size */
>> -    tcg_exec_init(0);
>> -
>>      cpu = cpu_create(cpu_type);
>>      env = cpu->env_ptr;
>>      cpu_reset(cpu);
>> diff --git a/softmmu/vl.c b/softmmu/vl.c
>> index 6a6363902d..47cc938cef 100644
>> --- a/softmmu/vl.c
>> +++ b/softmmu/vl.c
>> @@ -4176,7 +4176,7 @@ void qemu_init(int argc, char **argv, char **envp)
>>  
>>      /*
>>       * accelerator has been chosen and initialized, now it is time to
>> -     * register the cpu accel interface.
>> +     * register the cpu models, and the cpu accel interface.
>>       */
>>      module_call_init(MODULE_INIT_ACCEL_CPU);
>>  
>> diff --git a/target/i386/accel/hvf/hvf-cpu-type.c b/target/i386/accel/hvf/hvf-cpu-type.c
>> new file mode 100644
>> index 0000000000..dfe4ec4e9e
>> --- /dev/null
>> +++ b/target/i386/accel/hvf/hvf-cpu-type.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * 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 "hvf-cpu-type.h"
>> +#include "qapi/error.h"
>> +#include "sysemu/sysemu.h"
>> +#include "hw/boards.h"
>> +#include "sysemu/hvf.h"
>> +
>> +
>> +static void hvf_cpu_common_class_init(ObjectClass *oc, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(oc);
>> +
>> +    dc->realize = host_cpu_realizefn;
>> +}
>> +
>> +static void hvf_cpu_max_initfn(Object *obj)
>> +{
>> +    X86CPU *cpu = X86_CPU(obj);
>> +    CPUX86State *env = &cpu->env;
>> +
>> +    host_cpu_max_initfn(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_initfn(Object *obj)
>> +{
>> +    X86CPU *cpu = X86_CPU(obj);
>> +
>> +    host_cpu_initfn(obj);
>> +
>> +    /* Special cases not set in the X86CPUDefinition structs: */
>> +    /* TODO: in-kernel irqchip for hvf */
>> +
>> +    if (cpu->max_features) {
>> +        hvf_cpu_max_initfn(obj);
>> +    }
>> +}
>> +
>> +static const TypeInfo hvf_cpu_type_info = {
>> +    .name = X86_CPU_TYPE_NAME("hvf"),
>> +    .parent = TYPE_X86_CPU,
>> +
>> +    .instance_init = hvf_cpu_initfn,
>> +    .class_init = hvf_cpu_common_class_init,
>> +};
>> +
>> +static void hvf_cpu_register_base_type(void)
>> +{
>> +    type_register_static(&hvf_cpu_type_info);
>> +}
>> +
>> +type_init(hvf_cpu_register_base_type);
>> +
>> +void hvf_cpu_type_init(void)
>> +{
>> +    if (hvf_enabled()) {
>> +        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("hvf"));
>> +    }
>> +}
>> +
>> +accel_cpu_init(hvf_cpu_type_init);
>> diff --git a/target/i386/accel/hvf/meson.build b/target/i386/accel/hvf/meson.build
>> index 409c9a3f14..785dee72fc 100644
>> --- a/target/i386/accel/hvf/meson.build
>> +++ b/target/i386/accel/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',
>> +  'hvf-cpu-type.c',
>>  ))
>> diff --git a/target/i386/accel/kvm/kvm-cpu-type.c b/target/i386/accel/kvm/kvm-cpu-type.c
>> new file mode 100644
>> index 0000000000..f696f21e2b
>> --- /dev/null
>> +++ b/target/i386/accel/kvm/kvm-cpu-type.c
>> @@ -0,0 +1,161 @@
>> +/*
>> + * 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-type.h"
>> +#include "qapi/error.h"
>> +#include "sysemu/sysemu.h"
>> +#include "hw/boards.h"
>> +
>> +#include "kvm_i386.h"
>> +
>> +/* this information overloads the TYPE_X86_CPU type in x86-cpu.c */
>> +
>> +static void kvm_cpu_realizefn(DeviceState *dev, Error **errp)
>> +{
>> +    X86CPU *cpu = X86_CPU(dev);
>> +    CPUX86State *env = &cpu->env;
>> +
>> +    /*
>> +     * also for KVM the realize order is important, since
>> +     * x86_cpu_realize() checks if nothing else has been set by the user,
>> +     * or by the specialized x86 cpus (KVM, HVF) in
>> +     * cpu->ucode_rev and cpu->phys_bits.
>> +     *
>> +     * So it's 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(dev, errp);
>> +}
>> +
>> +static void kvm_cpu_common_class_init(ObjectClass *oc, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(oc);
>> +    dc->realize = kvm_cpu_realizefn;
>> +}
>> +
>> +/*
>> + * 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_initfn(Object *obj)
>> +{
>> +    X86CPU *cpu = X86_CPU(obj);
>> +    CPUX86State *env = &cpu->env;
>> +    KVMState *s = kvm_state;
>> +
>> +    host_cpu_max_initfn(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_initfn(Object *obj)
>> +{
>> +    X86CPU *cpu = X86_CPU(obj);
>> +
>> +    host_cpu_initfn(obj);
>> +
>> +    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_initfn(obj);
>> +    }
>> +}
>> +
>> +static const TypeInfo kvm_cpu_type_info = {
>> +    .name = X86_CPU_TYPE_NAME("kvm"),
>> +    .parent = TYPE_X86_CPU,
>> +
>> +    .instance_init = kvm_cpu_initfn,
>> +    .class_init = kvm_cpu_common_class_init,
>> +};
>> +
>> +static void kvm_cpu_register_base_type(void)
>> +{
>> +    type_register_static(&kvm_cpu_type_info);
>> +}
>> +
>> +type_init(kvm_cpu_register_base_type);
>> +
>> +void kvm_cpu_type_init(void)
>> +{
>> +    if (kvm_enabled()) {
>> +        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("kvm"));
>> +        host_cpu_type_init();
>> +    }
>> +}
>> +
>> +accel_cpu_init(kvm_cpu_type_init);
>> diff --git a/target/i386/accel/kvm/kvm-cpu-type.h b/target/i386/accel/kvm/kvm-cpu-type.h
>> new file mode 100644
>> index 0000000000..2448f49222
>> --- /dev/null
>> +++ b/target/i386/accel/kvm/kvm-cpu-type.h
>> @@ -0,0 +1,41 @@
>> +/*
>> + * i386 KVM CPU type 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/>.
>> + */
>> +
>> +#ifndef KVM_CPU_TYPE_H
>> +#define KVM_CPU_TYPE_H
>> +
>> +#ifdef CONFIG_KVM
>> +void kvm_cpu_type_init(void);
>> +
>> +/*
>> + * 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_TYPE_H */
>> diff --git a/target/i386/accel/kvm/kvm.c b/target/i386/accel/kvm/kvm.c
>> index cf46259534..829730d3c2 100644
>> --- a/target/i386/accel/kvm/kvm.c
>> +++ b/target/i386/accel/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/accel/kvm/meson.build b/target/i386/accel/kvm/meson.build
>> index 1d66559187..b6b32166b4 100644
>> --- a/target/i386/accel/kvm/meson.build
>> +++ b/target/i386/accel/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',
>> +  'kvm-cpu-type.c',
>> +))
>> +
>>  i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
>> diff --git a/target/i386/accel/tcg/meson.build b/target/i386/accel/tcg/meson.build
>> index 02794226c2..211ecef5f9 100644
>> --- a/target/i386/accel/tcg/meson.build
>> +++ b/target/i386/accel/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',
>> +  'tcg-cpu-type.c'), if_false: files('tcg-stub.c'))
>> diff --git a/target/i386/accel/tcg/tcg-cpu-type.c b/target/i386/accel/tcg/tcg-cpu-type.c
>> new file mode 100644
>> index 0000000000..f0ee4ef5f7
>> --- /dev/null
>> +++ b/target/i386/accel/tcg/tcg-cpu-type.c
>> @@ -0,0 +1,176 @@
>> +/*
>> + * 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 "tcg-cpu-type.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(DeviceState *dev, Error **errp)
>> +{
>> +    X86CPU *cpu = X86_CPU(dev);
>> +    CPUState *cs = CPU(dev);
>> +
>> +    /*
>> +     * also for TCG the realize order is important,
>> +     * as the memory regions initialized here are needed
>> +     * in x86_cpu_realizefn()
>> +     */
>> +    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);
>> +
>> +    /* call the generic x86_cpu_realizefn() after regions initialized */
>> +    x86_cpu_realizefn(dev, errp);
>> +}
>> +#endif /* !CONFIG_USER_ONLY */
>> +
>> +static void tcg_cpu_common_class_init(ObjectClass *oc, void *data)
>> +{
>> +    CPUClass *cc = CPU_CLASS(oc);
>> +#ifndef CONFIG_USER_ONLY
>> +    DeviceClass *dc = DEVICE_CLASS(oc);
>> +
>> +    dc->realize = tcg_cpu_realizefn;
>> +#endif /* !CONFIG_USER_ONLY */
>> +
>> +    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_initfn(Object *obj)
>> +{
>> +    X86CPU *cpu = X86_CPU(obj);
>> +
>> +    /* Special cases not set in the X86CPUDefinition structs: */
>> +    x86_cpu_apply_props(cpu, tcg_default_props);
>> +}
>> +
>> +static const TypeInfo tcg_cpu_type_info = {
>> +    .name = X86_CPU_TYPE_NAME("tcg"),
>> +    .parent = TYPE_X86_CPU,
>> +
>> +    .instance_init = tcg_cpu_initfn,
>> +    .class_init = tcg_cpu_common_class_init,
>> +};
>> +
>> +static void tcg_cpu_register_base_type(void)
>> +{
>> +    type_register_static(&tcg_cpu_type_info);
>> +}
>> +
>> +type_init(tcg_cpu_register_base_type);
>> +
>> +void tcg_cpu_type_init(void)
>> +{
>> +    if (tcg_enabled()) {
>> +        x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("tcg"));
>> +    }
>> +}
>> +
>> +accel_cpu_init(tcg_cpu_type_init);
>> diff --git a/target/i386/accel/tcg/tcg-cpu-type.h b/target/i386/accel/tcg/tcg-cpu-type.h
>> new file mode 100644
>> index 0000000000..d741a8f6be
>> --- /dev/null
>> +++ b/target/i386/accel/tcg/tcg-cpu-type.h
>> @@ -0,0 +1,25 @@
>> +/*
>> + * i386 TCG CPU type 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/>.
>> + */
>> +
>> +#ifndef TCG_CPU_TYPE_H
>> +#define TCG_CPU_TYPE_H
>> +
>> +void tcg_cpu_type_init(void);
>> +
>> +#endif /* TCG_CPU_TYPE_H */
>> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
>> index b185789d88..b547c9d39d 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,27 +32,17 @@
>>  #include "sysemu/xen.h"
>>  #include "accel/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
>>  #include "exec/address-spaces.h"
>>  #include "hw/i386/apic_internal.h"
>> @@ -594,8 +582,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 +1551,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 +1575,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 +4071,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 +4112,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),
>> @@ -4246,98 +4131,38 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
>>      device_class_set_props(dc, max_x86_cpu_properties);
>>  }
>>  
>> -static void max_x86_cpu_initfn(Object *obj)
>> +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 = {
>> +static TypeInfo max_x86_cpu_type_info = {
>>      .name = X86_CPU_TYPE_NAME("max"),
>> -    .parent = TYPE_X86_CPU,
>> -    .instance_init = max_x86_cpu_initfn,
>> +    .parent = NULL, /* set by x86_cpu_register_cpu_models */
>> +
>>      .class_init = max_x86_cpu_class_init,
>> +    .instance_init = max_x86_cpu_initfn,
>>  };
>>  
>> -#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 +4888,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 +4935,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 +4961,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 +4970,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);
>>  
>> @@ -5400,12 +5208,13 @@ static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
>>      cc->deprecation_note = model->cpudef->deprecation_note;
>>  }
>>  
>> -static void x86_register_cpu_model_type(const char *name, X86CPUModel *model)
>> +static void x86_register_cpu_model_type(const char *name, X86CPUModel *model,
>> +                                        const char *parent_type)
>>  {
>>      g_autofree char *typename = x86_cpu_type_name(name);
>>      TypeInfo ti = {
>>          .name = typename,
>> -        .parent = TYPE_X86_CPU,
>> +        .parent = parent_type,
>>          .class_init = x86_cpu_cpudef_class_init,
>>          .class_data = model,
>>      };
>> @@ -5413,7 +5222,8 @@ static void x86_register_cpu_model_type(const char *name, X86CPUModel *model)
>>      type_register(&ti);
>>  }
>>  
>> -static void x86_register_cpudef_types(X86CPUDefinition *def)
>> +static void x86_register_cpudef(X86CPUDefinition *def,
>> +                                const char *parent_type)
>>  {
>>      X86CPUModel *m;
>>      const X86CPUVersionDefinition *vdef;
>> @@ -5430,7 +5240,7 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
>>      m->cpudef = def;
>>      m->version = CPU_VERSION_AUTO;
>>      m->is_alias = true;
>> -    x86_register_cpu_model_type(def->name, m);
>> +    x86_register_cpu_model_type(def->name, m, parent_type);
>>  
>>      /* Versioned models: */
>>  
>> @@ -5441,14 +5251,14 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
>>          m->cpudef = def;
>>          m->version = vdef->version;
>>          m->note = vdef->note;
>> -        x86_register_cpu_model_type(name, m);
>> +        x86_register_cpu_model_type(name, m, parent_type);
>>  
>>          if (vdef->alias) {
>>              X86CPUModel *am = g_new0(X86CPUModel, 1);
>>              am->cpudef = def;
>>              am->version = vdef->version;
>>              am->is_alias = true;
>> -            x86_register_cpu_model_type(vdef->alias, am);
>> +            x86_register_cpu_model_type(vdef->alias, am, parent_type);
>>          }
>>      }
>>  
>> @@ -6192,53 +6002,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) {
>> @@ -6512,7 +6281,7 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
>>      }
>>  }
>>  
>> -static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>> +void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>>  {
>>      CPUState *cs = CPU(dev);
>>      X86CPU *cpu = X86_CPU(dev);
>> @@ -6521,27 +6290,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;
>> -        }
>> -    }
>> +    /*
>> +     * For accelerators that specialize the x86 cpu,
>> +     * this common code must be called after the accelerator-specific realizefn.
>> +     */
>>  
>> -    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 +6350,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 +6358,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,32 +6429,7 @@ 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
>> +    /* XXX this is the place for tcg region initialization XXX */
>>  
>>      qemu_init_vcpu(cs);
>>  
>> @@ -6932,7 +6632,7 @@ static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v,
>>  }
>>  #endif /* !CONFIG_USER_ONLY */
>>  
>> -static void x86_cpu_initfn(Object *obj)
>> +void x86_cpu_initfn(Object *obj)
>>  {
>>      X86CPU *cpu = X86_CPU(obj);
>>      X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
>> @@ -7230,7 +6930,7 @@ static Property x86_cpu_properties[] = {
>>      DEFINE_PROP_END_OF_LIST()
>>  };
>>  
>> -static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>> +void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>>  {
>>      X86CPUClass *xcc = X86_CPU_CLASS(oc);
>>      CPUClass *cc = CPU_CLASS(oc);
>> @@ -7249,10 +6949,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>>      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;
>> @@ -7341,25 +7037,49 @@ static void x86_cpu_base_class_init(ObjectClass *oc, void *data)
>>      xcc->ordering = 8;
>>  }
>>  
>> -static const TypeInfo x86_base_cpu_type_info = {
>> -        .name = X86_CPU_TYPE_NAME("base"),
>> -        .parent = TYPE_X86_CPU,
>> -        .class_init = x86_cpu_base_class_init,
>> +static TypeInfo x86_base_cpu_type_info = {
>> +    .name = X86_CPU_TYPE_NAME("base"),
>> +    .parent = NULL, /* set by x86_cpu_register_cpu_models */
>> +
>> +    .class_init = x86_cpu_base_class_init,
>>  };
>>  
>> -static void x86_cpu_register_types(void)
>> +/*
>> + * x86 cpu types are only registered once accelerator is determined,
>> + * passing the parent cpu type as an argument here.
>> + */
>> +void x86_cpu_register_cpu_models(const char *parent_type)
>>  {
>>      int i;
>>  
>> -    type_register_static(&x86_cpu_type_info);
>>      for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
>> -        x86_register_cpudef_types(&builtin_x86_defs[i]);
>> +        x86_register_cpudef(&builtin_x86_defs[i], parent_type);
>> +    }
>> +    max_x86_cpu_type_info.parent = parent_type;
>> +    type_register(&max_x86_cpu_type_info);
>> +
>> +    x86_base_cpu_type_info.parent = parent_type;
>> +    type_register(&x86_base_cpu_type_info);
>> +}
>> +
>> +static void x86_cpu_register_base_type(void)
>> +{
>> +    type_register_static(&x86_cpu_type_info);
>> +}
>> +
>> +type_init(x86_cpu_register_base_type);
>> +
>> +/*
>> + * generic initializer if no other specialization.
>> + */
>> +static void x86_cpu_type_init(void)
>> +{
>> +    /*
>> +     * I would like something better than this check.
>> +     */
>> +    if (!tcg_enabled() && !kvm_enabled() && !hvf_enabled()) {
>> +        x86_cpu_register_cpu_models(TYPE_X86_CPU);
>>      }
>> -    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_init(x86_cpu_register_types)
>> +accel_cpu_init(x86_cpu_type_init);
>> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
>> index f1bce16b53..9232672eb2 100644
>> --- a/target/i386/cpu.h
>> +++ b/target/i386/cpu.h
>> @@ -1905,13 +1905,26 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo,
>>                             void *puc);
>>  
>>  /* cpu.c */
>> +void x86_cpu_register_cpu_models(const char *parent_type);
>> +
>> +void x86_cpu_initfn(Object *obj);
>> +void max_x86_cpu_initfn(Object *obj);
>> +void x86_cpu_realizefn(DeviceState *dev, Error **errp);
>> +void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
>> +                              uint32_t vendor2, uint32_t vendor3);
>> +void x86_cpu_common_class_init(ObjectClass *oc, void *data);
>> +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 +2124,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..65a0119f4b
>> --- /dev/null
>> +++ b/target/i386/host-cpu.c
>> @@ -0,0 +1,201 @@
>> +/*
>> + * 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(DeviceState *dev, Error **errp)
>> +{
>> +    X86CPU *cpu = X86_CPU(dev);
>> +    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);
>> +    }
>> +    x86_cpu_realizefn(dev, 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_initfn(Object *obj)
>> +{
>> +    X86CPU *cpu = X86_CPU(obj);
>> +    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_initfn(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("%s processor with all supported host features ",
>> +                        ACCEL_GET_CLASS(current_accel())->name);
>> +}
>> +
>> +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,
>> +};
>> +
>> +void host_cpu_type_init(void)
>> +{
>> +    type_register(&host_cpu_type_info);
>> +}
>> diff --git a/target/i386/host-cpu.h b/target/i386/host-cpu.h
>> new file mode 100644
>> index 0000000000..e9d4726833
>> --- /dev/null
>> +++ b/target/i386/host-cpu.h
>> @@ -0,0 +1,21 @@
>> +/*
>> + * x86 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.
>> + */
>> +
>> +#ifndef HOST_CPU_TYPE_H
>> +#define HOST_CPU_TYPE_H
>> +
>> +void host_cpu_type_init(void);
>> +
>> +void host_cpu_initfn(Object *obj);
>> +void host_cpu_realizefn(DeviceState *dev, Error **errp);
>> +void host_cpu_max_initfn(X86CPU *cpu);
>> +
>> +void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping);
>> +
>> +#endif /* HOST_CPU_TYPE_H */
>> diff --git a/target/i386/meson.build b/target/i386/meson.build
>> index 50c8fba6cb..c84b0d6965 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 */
>> -- 
>> 2.26.2
>>
> 



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10  9:40     ` Claudio Fontana
@ 2020-11-10 10:04       ` Daniel P. Berrangé
  2020-11-10 10:13         ` Claudio Fontana
  2020-11-10 10:41         ` Paolo Bonzini
  0 siblings, 2 replies; 33+ messages in thread
From: Daniel P. Berrangé @ 2020-11-10 10:04 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Eduardo Habkost,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On Tue, Nov 10, 2020 at 10:40:04AM +0100, Claudio Fontana wrote:
> On 11/9/20 7:03 PM, Daniel P. Berrangé wrote:
> > On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
> >> 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-type.c   KVM x86 cpu type
> >> hvf-cpu-type.c   HVF x86 cpu type
> >> tcg-cpu-type.c   TCG x86 cpu type
> >>
> >> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
> >> so that accel-specific types can be used as parent types for all
> >> cpu models. Use the generic TYPE_X86_CPU only if no
> >> accel-specific specialization is enabled.
> > 
> > Can you give more info on why this is needed and/or desirable ?
> 
> Hello Daniel, there is a pointer to the overall higher level motivation in the cover letter.
> 
> But I am not pushing for this specific mechanism to be used, as mentioned in the cover letter.
> 
> If we need another mechanism to achieve that (not delaying the x86 model registration and make them inherit from the specialized class), but something else,
> I would be happy to get additional ideas.
> 
> > 
> > Dynamically changing the class hierarchy of CPUs at runtime feels
> > like a rather suspicious approach to me
> 
> TYPE_X86_CPU is base type is registered as usual.
> New accel-specialized types are defined (TYPE_TCG_CPU, TYPE_KVM_CPU, TYPE_HVF_CPU), also using normal type registration.
> 
> The missing step is how to adapt all the cpu models to use the functionality.

If I understand the problem correctly, we have two distinct axis of
configurability

 - the CPU model definitions (Nehalem, Broadwell, Skylake, host, max)
 - the accelerator CPU implementations (tcg, kvm, hvf).

At runtime any pair of objects from these two axis can be combined.

We're trying to avoid defining classes for the combinatorial expansion
of these axis.

This patch series encodes these two axis in a single class hierarchy,
with the CPU implementations being a parent of the CPU model definitions.
It avoids the combinatorial expansion, by taking the approach of dynamically
defining the parent/child relation between CPU impl and CPU defintion at
runtime  baed on the choosen accelerator impl.

The fully static way to deal with this problem is to accept that distinct
axis should be represented as distinct class hierarchies.

ie, we should have one class hierarchy for CPU model definitions, and
one class hierarchy  for accelerator CPU implementations.

So at runtime we then get two object instances - a CPU implementation
and a CPU definition. The CPU implementation object should have a
property which is a link to the desired CPU definition.


> The accelerator that is finally chosen to be used is only known at a specific point in the qemu initialization.
> This point of time I defined as MODULE_INIT_ACCEL_CPU.
> 
> That is the time when we know how the CPU should actually really behave (how it should be realized, etc).
> 
> In this series I realized this by registering the cpu models only at MODULE_INIT_ACCEL_CPU time, and not earlier.
> But maybe there is a better idea on how to do it, and I am all ears.
> 
> .
> > 
> > It is contrary to work we've been doing recently to try to make all
> > classes be fully statically defined by getting rid of dynamic properties,
> > such that introspection of classes does not depend on other CLI flags
> > you might have passed.
> 
> Understood, this goes against other requirements.
> 
> The dynamism introduced here is to register the cpu models at MODULE_INIT_ACCEL_CPU time instead of MODULE_INIT_QOM time.
> As a result, for any chosen accelerator, the type tree and class tree is identical.

For introspection the goal is that the type tree and class tree is
identical for a *binary*, not an accelerator within a binary.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



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

* Re: [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c
  2020-11-09 17:39   ` Paolo Bonzini
@ 2020-11-10 10:05     ` Claudio Fontana
  2020-11-10 10:42       ` Paolo Bonzini
  0 siblings, 1 reply; 33+ messages in thread
From: Claudio Fontana @ 2020-11-10 10:05 UTC (permalink / raw)
  To: Paolo Bonzini, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

On 11/9/20 6:39 PM, Paolo Bonzini wrote:
> On 09/11/20 18:27, Claudio Fontana wrote:
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
>>   target/i386/accel/tcg/bpt_helper.c  |   1 +
>>   target/i386/accel/tcg/cc_helper.c   |   1 +
>>   target/i386/accel/tcg/excp_helper.c |   1 +
>>   target/i386/accel/tcg/fpu_helper.c  |  33 ++++----
>>   target/i386/accel/tcg/int_helper.c  |   1 +
>>   target/i386/accel/tcg/mem_helper.c  |   1 +
>>   target/i386/accel/tcg/misc_helper.c |   1 +
>>   target/i386/accel/tcg/mpx_helper.c  |   1 +
>>   target/i386/accel/tcg/seg_helper.c  |   1 +
>>   target/i386/accel/tcg/smm_helper.c  |   2 +
>>   target/i386/accel/tcg/svm_helper.c  |   1 +
>>   target/i386/accel/tcg/translate.c   |   1 +
>>   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 ++++
>>   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/accel/tcg/bpt_helper.c b/target/i386/accel/tcg/bpt_helper.c
>> index c3a8ea73c9..5a551ce06e 100644
>> --- a/target/i386/accel/tcg/bpt_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/cc_helper.c b/target/i386/accel/tcg/cc_helper.c
>> index c9c90e10db..0b4c5b2cee 100644
>> --- a/target/i386/accel/tcg/cc_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/excp_helper.c b/target/i386/accel/tcg/excp_helper.c
>> index b10c7ecbcc..7cf690652e 100644
>> --- a/target/i386/accel/tcg/excp_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/fpu_helper.c b/target/i386/accel/tcg/fpu_helper.c
>> index 4ea73874d8..28703a41a2 100644
>> --- a/target/i386/accel/tcg/fpu_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/int_helper.c b/target/i386/accel/tcg/int_helper.c
>> index 334469ca8c..5fedb851f3 100644
>> --- a/target/i386/accel/tcg/int_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/mem_helper.c b/target/i386/accel/tcg/mem_helper.c
>> index 3a6d3ae2ef..1f6808d311 100644
>> --- a/target/i386/accel/tcg/mem_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/misc_helper.c b/target/i386/accel/tcg/misc_helper.c
>> index b6b1d41b14..9afcd11ea1 100644
>> --- a/target/i386/accel/tcg/misc_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/mpx_helper.c b/target/i386/accel/tcg/mpx_helper.c
>> index ade5d245d2..329aeef780 100644
>> --- a/target/i386/accel/tcg/mpx_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/seg_helper.c b/target/i386/accel/tcg/seg_helper.c
>> index be88938c2a..bad751c495 100644
>> --- a/target/i386/accel/tcg/seg_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/smm_helper.c b/target/i386/accel/tcg/smm_helper.c
>> index eb5aa6eb3d..ede197a379 100644
>> --- a/target/i386/accel/tcg/smm_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/svm_helper.c b/target/i386/accel/tcg/svm_helper.c
>> index 6224387eab..202832762e 100644
>> --- a/target/i386/accel/tcg/svm_helper.c
>> +++ b/target/i386/accel/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/accel/tcg/translate.c b/target/i386/accel/tcg/translate.c
>> index caea6f5fb1..bb64070365 100644
>> --- a/target/i386/accel/tcg/translate.c
>> +++ b/target/i386/accel/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"
>> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
>> index b1a55a2b79..b185789d88 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 d4772185df..f1bce16b53 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 a78fc4b4aa..0af4c1adf2 100644
>> --- a/target/i386/helper.c
>> +++ b/target/i386/helper.c
>> @@ -24,10 +24,8 @@
>>   #include "sysemu/runstate.h"
>>   #include "accel/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)
>> @@ -574,27 +572,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 7da5521364..50c8fba6cb 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 */
>>
> 
> Up to this patch I think it's a no brainer, modulo the bikeshedding on 
> paths.
> 
> Paolo
> 
> 

Ok, the paths: I kinda liked the symmetry between:

$(top_srcdir)/accel/kvm
$(top_srcdir)/target/i386/accel/kvm

but yeah, minor think that can be dropped if necessary.

Ciao,

CLaudio




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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 10:04       ` Daniel P. Berrangé
@ 2020-11-10 10:13         ` Claudio Fontana
  2020-11-10 10:41         ` Paolo Bonzini
  1 sibling, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-10 10:13 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Eduardo Habkost,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On 11/10/20 11:04 AM, Daniel P. Berrangé wrote:
> On Tue, Nov 10, 2020 at 10:40:04AM +0100, Claudio Fontana wrote:
>> On 11/9/20 7:03 PM, Daniel P. Berrangé wrote:
>>> On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
>>>> 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-type.c   KVM x86 cpu type
>>>> hvf-cpu-type.c   HVF x86 cpu type
>>>> tcg-cpu-type.c   TCG x86 cpu type
>>>>
>>>> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
>>>> so that accel-specific types can be used as parent types for all
>>>> cpu models. Use the generic TYPE_X86_CPU only if no
>>>> accel-specific specialization is enabled.
>>>
>>> Can you give more info on why this is needed and/or desirable ?
>>
>> Hello Daniel, there is a pointer to the overall higher level motivation in the cover letter.
>>
>> But I am not pushing for this specific mechanism to be used, as mentioned in the cover letter.
>>
>> If we need another mechanism to achieve that (not delaying the x86 model registration and make them inherit from the specialized class), but something else,
>> I would be happy to get additional ideas.
>>
>>>
>>> Dynamically changing the class hierarchy of CPUs at runtime feels
>>> like a rather suspicious approach to me
>>
>> TYPE_X86_CPU is base type is registered as usual.
>> New accel-specialized types are defined (TYPE_TCG_CPU, TYPE_KVM_CPU, TYPE_HVF_CPU), also using normal type registration.
>>
>> The missing step is how to adapt all the cpu models to use the functionality.
> 
> If I understand the problem correctly, we have two distinct axis of
> configurability
> 
>  - the CPU model definitions (Nehalem, Broadwell, Skylake, host, max)
>  - the accelerator CPU implementations (tcg, kvm, hvf).
> 
> At runtime any pair of objects from these two axis can be combined.
> 
> We're trying to avoid defining classes for the combinatorial expansion
> of these axis.
> 
> This patch series encodes these two axis in a single class hierarchy,
> with the CPU implementations being a parent of the CPU model definitions.
> It avoids the combinatorial expansion, by taking the approach of dynamically
> defining the parent/child relation between CPU impl and CPU defintion at
> runtime  baed on the choosen accelerator impl.
> 
> The fully static way to deal with this problem is to accept that distinct
> axis should be represented as distinct class hierarchies.
> 
> ie, we should have one class hierarchy for CPU model definitions, and
> one class hierarchy  for accelerator CPU implementations.
> 
> So at runtime we then get two object instances - a CPU implementation
> and a CPU definition. The CPU implementation object should have a
> property which is a link to the desired CPU definition.
> 
> 
>> The accelerator that is finally chosen to be used is only known at a specific point in the qemu initialization.
>> This point of time I defined as MODULE_INIT_ACCEL_CPU.
>>
>> That is the time when we know how the CPU should actually really behave (how it should be realized, etc).
>>
>> In this series I realized this by registering the cpu models only at MODULE_INIT_ACCEL_CPU time, and not earlier.
>> But maybe there is a better idea on how to do it, and I am all ears.
>>
>> .
>>>
>>> It is contrary to work we've been doing recently to try to make all
>>> classes be fully statically defined by getting rid of dynamic properties,
>>> such that introspection of classes does not depend on other CLI flags
>>> you might have passed.
>>
>> Understood, this goes against other requirements.
>>
>> The dynamism introduced here is to register the cpu models at MODULE_INIT_ACCEL_CPU time instead of MODULE_INIT_QOM time.
>> As a result, for any chosen accelerator, the type tree and class tree is identical.
> 
> For introspection the goal is that the type tree and class tree is
> identical for a *binary*, not an accelerator within a binary.
> 
> 
> Regards,
> Daniel
> 

Thanks Daniel for your comments, I am going to think these through and see if I can build a model like you suggest
(with the cpu implementation axis separate from the cpu model definitions axis),

as a possible other way forward.

Ciao,

Claudio




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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 10:04       ` Daniel P. Berrangé
  2020-11-10 10:13         ` Claudio Fontana
@ 2020-11-10 10:41         ` Paolo Bonzini
  2020-11-10 15:23           ` Eduardo Habkost
  1 sibling, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-10 10:41 UTC (permalink / raw)
  To: Daniel P. Berrangé, Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Eduardo Habkost,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On 10/11/20 11:04, Daniel P. Berrangé wrote:
> 
> ie, we should have one class hierarchy for CPU model definitions, and
> one class hierarchy  for accelerator CPU implementations.
> 
> So at runtime we then get two object instances - a CPU implementation
> and a CPU definition. The CPU implementation object should have a
> property which is a link to the desired CPU definition.

It doesn't even have to be two object instances.  The implementation can 
be nothing more than a set of function pointers.

Paolo



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

* Re: [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c
  2020-11-10 10:05     ` Claudio Fontana
@ 2020-11-10 10:42       ` Paolo Bonzini
  0 siblings, 0 replies; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-10 10:42 UTC (permalink / raw)
  To: Claudio Fontana, Thomas Huth, Richard Henderson,
	Stefano Stabellini, Wenchao Wang, Roman Bolshakov,
	Sunil Muthuswamy, Philippe Mathieu-Daudé
  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, Colin Xu

On 10/11/20 11:05, Claudio Fontana wrote:
>> Up to this patch I think it's a no brainer, modulo the bikeshedding on
>> paths.
>>
>> Paolo
>>
>>
> Ok, the paths: I kinda liked the symmetry between:
> 
> $(top_srcdir)/accel/kvm
> $(top_srcdir)/target/i386/accel/kvm
> 
> but yeah, minor think that can be dropped if necessary.

You can instead mirror hw/i386/kvm/. :)

Paolo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 10:41         ` Paolo Bonzini
@ 2020-11-10 15:23           ` Eduardo Habkost
  2020-11-10 16:05             ` Paolo Bonzini
                               ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Eduardo Habkost @ 2020-11-10 15:23 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, haxm-team,
	Claudio Fontana, Anthony Perard, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
> On 10/11/20 11:04, Daniel P. Berrangé wrote:
> > 
> > ie, we should have one class hierarchy for CPU model definitions, and
> > one class hierarchy  for accelerator CPU implementations.
> > 
> > So at runtime we then get two object instances - a CPU implementation
> > and a CPU definition. The CPU implementation object should have a
> > property which is a link to the desired CPU definition.
> 
> It doesn't even have to be two object instances.  The implementation can be
> nothing more than a set of function pointers.

A set of function pointers is exactly what a QOM interface is.
Could the methods be provided by a TYPE_X86_ACCEL interface type,
implemented by the accel object?

-- 
Eduardo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 15:23           ` Eduardo Habkost
@ 2020-11-10 16:05             ` Paolo Bonzini
  2020-11-10 17:55               ` Eduardo Habkost
  2020-11-10 17:38             ` Claudio Fontana
  2020-11-16 17:53             ` Claudio Fontana
  2 siblings, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-10 16:05 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, haxm-team,
	Claudio Fontana, Anthony Perard, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On 10/11/20 16:23, Eduardo Habkost wrote:
> On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
>> On 10/11/20 11:04, Daniel P. Berrangé wrote:
>>>
>>> ie, we should have one class hierarchy for CPU model definitions, and
>>> one class hierarchy  for accelerator CPU implementations.
>>>
>>> So at runtime we then get two object instances - a CPU implementation
>>> and a CPU definition. The CPU implementation object should have a
>>> property which is a link to the desired CPU definition.
>>
>> It doesn't even have to be two object instances.  The implementation can be
>> nothing more than a set of function pointers.
> 
> A set of function pointers is exactly what a QOM interface is.
> Could the methods be provided by a TYPE_X86_ACCEL interface type,
> implemented by the accel object?

I think we should not try yo implement interfaces conditionally (i.e. 
have TYPE_X86_ACCEL implemented only on qemu-system-{i386,x86_64} and 
not qemu-system-arm), even if technically the accel/ objects are 
per-target (specific_ss) rather than common.

Paolo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 15:23           ` Eduardo Habkost
  2020-11-10 16:05             ` Paolo Bonzini
@ 2020-11-10 17:38             ` Claudio Fontana
  2020-11-10 18:14               ` Eduardo Habkost
  2020-11-16 17:53             ` Claudio Fontana
  2 siblings, 1 reply; 33+ messages in thread
From: Claudio Fontana @ 2020-11-10 17:38 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Colin Xu, Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Cameron Esfahani,
	haxm-team, Wenchao Wang, Anthony Perard, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson

On 11/10/20 4:23 PM, Eduardo Habkost wrote:
> On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
>> On 10/11/20 11:04, Daniel P. Berrangé wrote:
>>>
>>> ie, we should have one class hierarchy for CPU model definitions, and
>>> one class hierarchy  for accelerator CPU implementations.
>>>
>>> So at runtime we then get two object instances - a CPU implementation
>>> and a CPU definition. The CPU implementation object should have a
>>> property which is a link to the desired CPU definition.
>>
>> It doesn't even have to be two object instances.  The implementation can be
>> nothing more than a set of function pointers.
> 
> A set of function pointers is exactly what a QOM interface is.
> Could the methods be provided by a TYPE_X86_ACCEL interface type,
> implemented by the accel object?
> 

Looking at the 2 axes mentioned by Daniel before, on the "accelerator cpu axis", we have TYPE_TCG_CPU, TYPE_KVM_CPU, TYPE_HVF_CPU,
which look like simple subclasses of TYPE_X86_CPU to me, with basically all the divergent functionality being added by composition.
TYPE_HVF_CPU seems to do everything that TYPE_X86_CPU does on construction (and device realization), and then some.

On the "cpu models" axis we have all the current subclasses of TYPE_X86_CPU, which include "links" to X86CPUModel objects in the form
of class_data:

static void x86_register_cpu_model_type(const char *name, X86CPUModel *model,
                                        const char *parent_type)
{
    g_autofree char *typename = x86_cpu_type_name(name);
    TypeInfo ti = {
        .name = typename,
        .parent = parent_type,
        .class_init = x86_cpu_cpudef_class_init,
        .class_data = model,
    };

    type_register(&ti);
}

so this would be close to the "link" property that Daniel you were speaking about before?
Should X86CPUmodel be the prime citizen of the "cpu models" axis, without constructing a separate TYPE_X86_CPU subclass for each cpu model?

A separate topic we did not address in comments before, where I'd like opinions, is how should we treat cpu types "base" and "max" and "host"?

Just to avoid forgetting about them, currently TYPE_X86_CPU is the parent type of "base" and of "max",
and "max" is the parent type of "host".

"host" is only allowed when using accelerator kvm or hvf. Attempts to create such a cpu without a kvm or hvf accelerator enabled will error out.
"max" behaves differently when using hvf or kvm.

Thanks,

Claudio


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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 16:05             ` Paolo Bonzini
@ 2020-11-10 17:55               ` Eduardo Habkost
  2020-11-10 20:39                 ` Paolo Bonzini
  0 siblings, 1 reply; 33+ messages in thread
From: Eduardo Habkost @ 2020-11-10 17:55 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, haxm-team,
	Claudio Fontana, Anthony Perard, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On Tue, Nov 10, 2020 at 05:05:27PM +0100, Paolo Bonzini wrote:
> On 10/11/20 16:23, Eduardo Habkost wrote:
> > On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
> > > On 10/11/20 11:04, Daniel P. Berrangé wrote:
> > > > 
> > > > ie, we should have one class hierarchy for CPU model definitions, and
> > > > one class hierarchy  for accelerator CPU implementations.
> > > > 
> > > > So at runtime we then get two object instances - a CPU implementation
> > > > and a CPU definition. The CPU implementation object should have a
> > > > property which is a link to the desired CPU definition.
> > > 
> > > It doesn't even have to be two object instances.  The implementation can be
> > > nothing more than a set of function pointers.
> > 
> > A set of function pointers is exactly what a QOM interface is.
> > Could the methods be provided by a TYPE_X86_ACCEL interface type,
> > implemented by the accel object?
> 
> I think we should not try yo implement interfaces conditionally (i.e. have
> TYPE_X86_ACCEL implemented only on qemu-system-{i386,x86_64} and not
> qemu-system-arm), even if technically the accel/ objects are per-target
> (specific_ss) rather than common.

If the accel objects are already per target, it seems appropriate
to have a QOM type hierarchy that reflects that.

`qemu-system-x86_64 -accel kvm` would create a kvm-x86_64-accel
object, but `qemu-system-arm -accel kvm` would create a
kvm-arm-accel.

*-x86_64-accel and *-i386-accel would all implement
INTERFACE_X86_ACCEL.

-- 
Eduardo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 17:38             ` Claudio Fontana
@ 2020-11-10 18:14               ` Eduardo Habkost
  2020-11-11 12:59                 ` Claudio Fontana
  0 siblings, 1 reply; 33+ messages in thread
From: Eduardo Habkost @ 2020-11-10 18:14 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Colin Xu, Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Cameron Esfahani,
	haxm-team, Wenchao Wang, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson

On Tue, Nov 10, 2020 at 06:38:49PM +0100, Claudio Fontana wrote:
> On 11/10/20 4:23 PM, Eduardo Habkost wrote:
> > On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
> >> On 10/11/20 11:04, Daniel P. Berrangé wrote:
> >>>
> >>> ie, we should have one class hierarchy for CPU model definitions, and
> >>> one class hierarchy  for accelerator CPU implementations.
> >>>
> >>> So at runtime we then get two object instances - a CPU implementation
> >>> and a CPU definition. The CPU implementation object should have a
> >>> property which is a link to the desired CPU definition.
> >>
> >> It doesn't even have to be two object instances.  The implementation can be
> >> nothing more than a set of function pointers.
> > 
> > A set of function pointers is exactly what a QOM interface is.
> > Could the methods be provided by a TYPE_X86_ACCEL interface type,
> > implemented by the accel object?
> > 
> 
> Looking at the 2 axes mentioned by Daniel before, on the "accelerator cpu axis", we have TYPE_TCG_CPU, TYPE_KVM_CPU, TYPE_HVF_CPU,
> which look like simple subclasses of TYPE_X86_CPU to me, with basically all the divergent functionality being added by composition.
> TYPE_HVF_CPU seems to do everything that TYPE_X86_CPU does on construction (and device realization), and then some.

What I don't get here is: why do we need a new "accelerator CPU
axis" if we already have an accelerator QOM type hierarchy?
accelerator-specific behavior can be delegated to the (existing)
accelerator object.

> 
> On the "cpu models" axis we have all the current subclasses of TYPE_X86_CPU, which include "links" to X86CPUModel objects in the form
> of class_data:
> 
> static void x86_register_cpu_model_type(const char *name, X86CPUModel *model,
>                                         const char *parent_type)
> {
>     g_autofree char *typename = x86_cpu_type_name(name);
>     TypeInfo ti = {
>         .name = typename,
>         .parent = parent_type,
>         .class_init = x86_cpu_cpudef_class_init,
>         .class_data = model,
>     };
> 
>     type_register(&ti);
> }
> 
> so this would be close to the "link" property that Daniel you were speaking about before?
> Should X86CPUmodel be the prime citizen of the "cpu models"
> axis, without constructing a separate TYPE_X86_CPU subclass for
> each cpu model?

I don't think this would be fundamentally wrong, but the
assumption that each CPU model is implemented as a separate
subclass of TYPE_CPU is encoded everywhere in the code and in
management software.

> 
> A separate topic we did not address in comments before, where
> I'd like opinions, is how should we treat cpu types "base" and
> "max" and "host"?
> 
> Just to avoid forgetting about them, currently TYPE_X86_CPU is
> the parent type of "base" and of "max", and "max" is the parent
> type of "host".
> 
> "host" is only allowed when using accelerator kvm or hvf.
> Attempts to create such a cpu without a kvm or hvf accelerator
> enabled will error out.
> "max" behaves differently when using hvf or kvm.

"base" exists only to allow us to implement
`query-cpu-model-expansion type=static` (because it requires a
"static" CPU model[1]).  It is not supposed to be used directly.

"host" is supposed to be used directly by the user, work out of
the box, and is a convenient way to get an optimal configuration
for the current host.  It is supposed to have reasonable defaults
that let you boot a guest, and enable as most features as
possible.  We don't offer it for TCG, because TCG emulation
features are not dependent on host capabilities.

Now, "max" is tricky to define, because its semantics are
overloaded:

For KVM, "max" is used for querying which features are supported
by the host (even if the feature is not enabled by default by
"host").

However, "max" is _also_ usable directly by users with TCG, if
they want all features supported by TCG enabled.  Its use case
for TCG is more similar to the use case for "host".

Probably mixing two use cases in the same "max" CPU model was a
mistake, and we should have added a separate CPU model for each
use case.

Because of the above, having separate accel-specific names for
each of those models sounds like a welcome change.

---
[1] The definition of "static CPU model" is in the documentation
for query-cpu-model-expansion.

-- 
Eduardo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 17:55               ` Eduardo Habkost
@ 2020-11-10 20:39                 ` Paolo Bonzini
  2020-11-10 20:45                   ` Eduardo Habkost
  0 siblings, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2020-11-10 20:39 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, haxm-team,
	Claudio Fontana, Anthony Perard, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On 10/11/20 18:55, Eduardo Habkost wrote:
>> I think we should not try yo implement interfaces conditionally (i.e. have
>> TYPE_X86_ACCEL implemented only on qemu-system-{i386,x86_64} and not
>> qemu-system-arm), even if technically the accel/ objects are per-target
>> (specific_ss) rather than common.
> If the accel objects are already per target, it seems appropriate
> to have a QOM type hierarchy that reflects that.
> 
> `qemu-system-x86_64 -accel kvm` would create a kvm-x86_64-accel
> object, but `qemu-system-arm -accel kvm` would create a
> kvm-arm-accel.

... and fall back to kvm-accel?  So accel_find would be the only place 
to change.

Paolo

> *-x86_64-accel and *-i386-accel would all implement
> INTERFACE_X86_ACCEL.



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 20:39                 ` Paolo Bonzini
@ 2020-11-10 20:45                   ` Eduardo Habkost
  0 siblings, 0 replies; 33+ messages in thread
From: Eduardo Habkost @ 2020-11-10 20:45 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Laurent Vivier, Wenchao Wang, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, haxm-team,
	Claudio Fontana, Anthony Perard, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Richard Henderson, Colin Xu

On Tue, Nov 10, 2020 at 09:39:37PM +0100, Paolo Bonzini wrote:
> On 10/11/20 18:55, Eduardo Habkost wrote:
> > > I think we should not try yo implement interfaces conditionally (i.e. have
> > > TYPE_X86_ACCEL implemented only on qemu-system-{i386,x86_64} and not
> > > qemu-system-arm), even if technically the accel/ objects are per-target
> > > (specific_ss) rather than common.
> > If the accel objects are already per target, it seems appropriate
> > to have a QOM type hierarchy that reflects that.
> > 
> > `qemu-system-x86_64 -accel kvm` would create a kvm-x86_64-accel
> > object, but `qemu-system-arm -accel kvm` would create a
> > kvm-arm-accel.
> 
> ... and fall back to kvm-accel?  So accel_find would be the only place to
> change.

Sounds good.  This way we don't need to convert all accelerators
or all targets at the same time.

-- 
Eduardo



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 18:14               ` Eduardo Habkost
@ 2020-11-11 12:59                 ` Claudio Fontana
  0 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-11 12:59 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Paul Durrant, Jason Wang, Marcelo Tosatti, Richard Henderson,
	qemu-devel, Peter Xu, Dario Faggioli, Roman Bolshakov,
	Cameron Esfahani, haxm-team, Colin Xu, Anthony Perard,
	Paolo Bonzini, Sunil Muthuswamy, Bruce Rogers,
	Philippe Mathieu-Daudé,
	Wenchao Wang

On 11/10/20 7:14 PM, Eduardo Habkost wrote:
> On Tue, Nov 10, 2020 at 06:38:49PM +0100, Claudio Fontana wrote:
>> On 11/10/20 4:23 PM, Eduardo Habkost wrote:
>>> On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
>>>> On 10/11/20 11:04, Daniel P. Berrangé wrote:
>>>>>
>>>>> ie, we should have one class hierarchy for CPU model definitions, and
>>>>> one class hierarchy  for accelerator CPU implementations.
>>>>>
>>>>> So at runtime we then get two object instances - a CPU implementation
>>>>> and a CPU definition. The CPU implementation object should have a
>>>>> property which is a link to the desired CPU definition.
>>>>
>>>> It doesn't even have to be two object instances.  The implementation can be
>>>> nothing more than a set of function pointers.
>>>
>>> A set of function pointers is exactly what a QOM interface is.
>>> Could the methods be provided by a TYPE_X86_ACCEL interface type,
>>> implemented by the accel object?
>>>
>>
>> Looking at the 2 axes mentioned by Daniel before, on the "accelerator cpu axis", we have TYPE_TCG_CPU, TYPE_KVM_CPU, TYPE_HVF_CPU,
>> which look like simple subclasses of TYPE_X86_CPU to me, with basically all the divergent functionality being added by composition.
>> TYPE_HVF_CPU seems to do everything that TYPE_X86_CPU does on construction (and device realization), and then some.
> 
> What I don't get here is: why do we need a new "accelerator CPU
> axis" if we already have an accelerator QOM type hierarchy?
> accelerator-specific behavior can be delegated to the (existing)
> accelerator object.


Hi Eduardo,

it might very well be that we can extend the QOM hierarchy to achieve this,
this is probably the focus of the other thread with Paolo.

I have some reservations with this approach, which maybe I should mention there (briefly: current accel implementation, its lack of user mode coverage, and the imperfect mapping between the accel cpu behavior we need and the actual accel class (in particular for whpx, hax, qtest).

It might be that these are actually only TODOs, and not blockers.

> 
>>
>> On the "cpu models" axis we have all the current subclasses of TYPE_X86_CPU, which include "links" to X86CPUModel objects in the form
>> of class_data:
>>
>> static void x86_register_cpu_model_type(const char *name, X86CPUModel *model,
>>                                         const char *parent_type)
>> {
>>     g_autofree char *typename = x86_cpu_type_name(name);
>>     TypeInfo ti = {
>>         .name = typename,
>>         .parent = parent_type,
>>         .class_init = x86_cpu_cpudef_class_init,
>>         .class_data = model,
>>     };
>>
>>     type_register(&ti);
>> }
>>
>> so this would be close to the "link" property that Daniel you were speaking about before?
>> Should X86CPUmodel be the prime citizen of the "cpu models"
>> axis, without constructing a separate TYPE_X86_CPU subclass for
>> each cpu model?
> 
> I don't think this would be fundamentally wrong, but the
> assumption that each CPU model is implemented as a separate
> subclass of TYPE_CPU is encoded everywhere in the code and in
> management software.


Fair enough, so that's a point towards keeping the existing "cpu models as subclasses of X86 cpu".

> 
>>
>> A separate topic we did not address in comments before, where
>> I'd like opinions, is how should we treat cpu types "base" and
>> "max" and "host"?
>>
>> Just to avoid forgetting about them, currently TYPE_X86_CPU is
>> the parent type of "base" and of "max", and "max" is the parent
>> type of "host".
>>
>> "host" is only allowed when using accelerator kvm or hvf.
>> Attempts to create such a cpu without a kvm or hvf accelerator
>> enabled will error out.
>> "max" behaves differently when using hvf or kvm.
> 
> "base" exists only to allow us to implement
> `query-cpu-model-expansion type=static` (because it requires a
> "static" CPU model[1]).  It is not supposed to be used directly.
> 
> "host" is supposed to be used directly by the user, work out of
> the box, and is a convenient way to get an optimal configuration
> for the current host.  It is supposed to have reasonable defaults
> that let you boot a guest, and enable as most features as
> possible.  We don't offer it for TCG, because TCG emulation
> features are not dependent on host capabilities.
> 
> Now, "max" is tricky to define, because its semantics are
> overloaded:
> 
> For KVM, "max" is used for querying which features are supported
> by the host (even if the feature is not enabled by default by
> "host").
> 
> However, "max" is _also_ usable directly by users with TCG, if
> they want all features supported by TCG enabled.  Its use case
> for TCG is more similar to the use case for "host".
> 
> Probably mixing two use cases in the same "max" CPU model was a
> mistake, and we should have added a separate CPU model for each
> use case.
> 
> Because of the above, having separate accel-specific names for
> each of those models sounds like a welcome change.

can compatibility issues be addressed effectively with this option?
If so, would it make sense to go even further and expand the whole type tree to have accel-specific models?

Just trying to explore the whole range of possibilities here.

Thanks,

Claudio


> 
> ---
> [1] The definition of "static CPU model" is in the documentation
> for query-cpu-model-expansion.
> 



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

* Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
  2020-11-10 15:23           ` Eduardo Habkost
  2020-11-10 16:05             ` Paolo Bonzini
  2020-11-10 17:38             ` Claudio Fontana
@ 2020-11-16 17:53             ` Claudio Fontana
  2 siblings, 0 replies; 33+ messages in thread
From: Claudio Fontana @ 2020-11-16 17:53 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini,
	Daniel P. Berrangé,
	Colin Xu, Paul Durrant, Jason Wang, Marcelo Tosatti, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Cameron Esfahani,
	haxm-team, Wenchao Wang, Anthony Perard, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson

On 11/10/20 4:23 PM, Eduardo Habkost wrote:
> On Tue, Nov 10, 2020 at 11:41:46AM +0100, Paolo Bonzini wrote:
>> On 10/11/20 11:04, Daniel P. Berrangé wrote:
>>>
>>> ie, we should have one class hierarchy for CPU model definitions, and
>>> one class hierarchy  for accelerator CPU implementations.
>>>
>>> So at runtime we then get two object instances - a CPU implementation
>>> and a CPU definition. The CPU implementation object should have a
>>> property which is a link to the desired CPU definition.
>>
>> It doesn't even have to be two object instances.  The implementation can be
>> nothing more than a set of function pointers.
> 
> A set of function pointers is exactly what a QOM interface is.
> Could the methods be provided by a TYPE_X86_ACCEL interface type,
> implemented by the accel object?
> 

Hi Eduardo, Paolo,

conceptually this is also an attractive option, but there are a few issues I can see with this approach,

the first and most evident of which is that accel classes are used only for softmmu,
while we need the tcg cpu (or TYPE_X86_ACCEL interface to be used by the cpu) for user mode too.

I'll start working on some new prototype, trying to incorporate some ideas exchanged here, see what comes out.

Thanks,

Ciao,

CLaudio


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

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

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-09 17:27 [RFC v1 00/10] i386 cleanup Claudio Fontana
2020-11-09 17:27 ` [RFC v1 01/10] i386: move kvm accel files into accel/kvm/ Claudio Fontana
2020-11-09 17:27 ` [RFC v1 02/10] i386: move whpx accel files to accel/whpx/ Claudio Fontana
2020-11-09 17:27 ` [RFC v1 03/10] i386: move hax accel files to accel/hax/ Claudio Fontana
2020-11-09 17:27 ` [RFC v1 04/10] i386: move hvf accel files into accel/hvf/ Claudio Fontana
2020-11-09 17:27 ` [RFC v1 05/10] i386: move TCG accel files into accel/tcg/ Claudio Fontana
2020-11-09 17:27 ` [RFC v1 06/10] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
2020-11-09 17:27 ` [RFC v1 07/10] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
2020-11-09 17:39   ` Paolo Bonzini
2020-11-10 10:05     ` Claudio Fontana
2020-11-10 10:42       ` Paolo Bonzini
2020-11-09 17:27 ` [RFC v1 08/10] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
2020-11-09 17:27 ` [RFC v1 09/10] i386: split cpu.c and defer x86 models registration Claudio Fontana
2020-11-09 17:34   ` Paolo Bonzini
2020-11-09 17:37   ` Paolo Bonzini
2020-11-09 18:03   ` Daniel P. Berrangé
2020-11-10  9:40     ` Claudio Fontana
2020-11-10 10:04       ` Daniel P. Berrangé
2020-11-10 10:13         ` Claudio Fontana
2020-11-10 10:41         ` Paolo Bonzini
2020-11-10 15:23           ` Eduardo Habkost
2020-11-10 16:05             ` Paolo Bonzini
2020-11-10 17:55               ` Eduardo Habkost
2020-11-10 20:39                 ` Paolo Bonzini
2020-11-10 20:45                   ` Eduardo Habkost
2020-11-10 17:38             ` Claudio Fontana
2020-11-10 18:14               ` Eduardo Habkost
2020-11-11 12:59                 ` Claudio Fontana
2020-11-16 17:53             ` Claudio Fontana
2020-11-09 19:04   ` Eduardo Habkost
2020-11-10  9:49     ` Claudio Fontana
2020-11-09 17:27 ` [RFC v1 10/10] module: add priority to module_init Claudio Fontana
2020-11-09 17:45 ` [RFC v1 00/10] i386 cleanup no-reply

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.