All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v3 0/9] i386 cleanup
@ 2020-11-18 10:29 Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 1/9] i386: move kvm accel files into kvm/ Claudio Fontana
                   ` (9 more replies)
  0 siblings, 10 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

Hi all, in this cleanup series we are back at RFC,
and back at providing the whole series together.

The last patch in particular contains a different way to provide
the accelerator-specific i386 CPU functionality,
compared with RFCv1.

In this series I start by moving all i386-specific accelerators
into subdirs of target/i386/ away from the main target directory.

Btw do we have any minimal testing coverage for HAX? Also Xen?

After the code move 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.

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 temporary
tcg-cpu module.

After this I considered and implemented a few options.

Like in RFCv1, I introduced a new MODULE_INIT phase,

MODULE_INIT_ACCEL_CPU

that will trigger the registration of the cpu accel-specific
functionality.

Differently than in RFCv1, the class hierarchy of TYPE_X86_CPUs
has been left untouched, and the registration of cpu models
has again been left untouched,

instead describing the specialized functionality in a struct.

The existing "accel" class hierarchy, which is basically used
to contain machine accelerator-specific initializations,
has also been left untouched, as it cannot be used in user mode.

Motivation and higher level steps:

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

Looking forward to your comments on this proposal,

Ciao,

Claudio

Claudio Fontana (9):
  i386: move kvm accel files into kvm/
  i386: move whpx accel files into whpx/
  i386: move hax accel files into hax/
  i386: hvf: remove stale MAINTAINERS entry for old hvf stubs
  i386: move TCG accel files into tcg/
  i386: move cpu dump out of helper.c into cpu-dump.c
  i386: move TCG cpu class initialization out of helper.c
  module: introduce MODULE_INIT_ACCEL_CPU
  i386: split cpu accelerators from cpu.c

 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                       |   1 +
 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                 |   2 +
 linux-user/main.c                     |   1 +
 meson.build                           |   1 +
 softmmu/vl.c                          |   6 +
 target/i386/cpu-dump.c                | 538 +++++++++++++++++++++++++
 target/i386/cpu-qom.h                 |  23 ++
 target/i386/cpu.c                     | 420 +++-----------------
 target/i386/cpu.h                     | 120 +-----
 target/i386/{ => hax}/hax-all.c       |  12 +-
 target/i386/{ => hax}/hax-cpus.c      |   0
 target/i386/{ => hax}/hax-cpus.h      |   0
 target/i386/{ => hax}/hax-i386.h      |   6 +-
 target/i386/{ => hax}/hax-interface.h |   0
 target/i386/{ => hax}/hax-mem.c       |   0
 target/i386/{ => hax}/hax-posix.c     |   0
 target/i386/{ => hax}/hax-posix.h     |   0
 target/i386/{ => hax}/hax-windows.c   |   0
 target/i386/{ => hax}/hax-windows.h   |   0
 target/i386/hax/meson.build           |   7 +
 target/i386/helper-tcg.h              | 112 ++++++
 target/i386/helper.c                  | 539 +-------------------------
 target/i386/host-cpu.c                | 196 ++++++++++
 target/i386/host-cpu.h                |  20 +
 target/i386/hvf/cpu.c                 |  64 +++
 target/i386/hvf/hvf.c                 |  10 +-
 target/i386/hvf/meson.build           |   1 +
 target/i386/kvm/cpu.c                 | 145 +++++++
 target/i386/{ => kvm}/hyperv-proto.h  |   0
 target/i386/{ => kvm}/hyperv-stub.c   |   0
 target/i386/{ => kvm}/hyperv.c        |   0
 target/i386/{ => kvm}/hyperv.h        |   0
 target/i386/kvm/kvm-cpu.h             |  41 ++
 target/i386/{ => kvm}/kvm-stub.c      |   0
 target/i386/{ => kvm}/kvm.c           |   3 +-
 target/i386/{ => kvm}/kvm_i386.h      |   0
 target/i386/kvm/meson.build           |   8 +
 target/i386/kvm/trace-events          |   7 +
 target/i386/kvm/trace.h               |   1 +
 target/i386/machine.c                 |   4 +-
 target/i386/meson.build               |  39 +-
 target/i386/{ => tcg}/bpt_helper.c    |   1 +
 target/i386/{ => tcg}/cc_helper.c     |   1 +
 target/i386/tcg/cpu.c                 | 168 ++++++++
 target/i386/{ => tcg}/excp_helper.c   |   1 +
 target/i386/{ => tcg}/fpu_helper.c    |  33 +-
 target/i386/{ => tcg}/int_helper.c    |   1 +
 target/i386/{ => tcg}/mem_helper.c    |   1 +
 target/i386/tcg/meson.build           |  14 +
 target/i386/{ => tcg}/misc_helper.c   |   1 +
 target/i386/{ => tcg}/mpx_helper.c    |   1 +
 target/i386/{ => tcg}/seg_helper.c    |   1 +
 target/i386/{ => tcg}/smm_helper.c    |   2 +
 target/i386/{ => tcg}/svm_helper.c    |   1 +
 target/i386/{ => tcg}/tcg-stub.c      |   0
 target/i386/{ => tcg}/translate.c     |   1 +
 target/i386/trace-events              |   6 -
 target/i386/whpx/meson.build          |   4 +
 target/i386/{ => whpx}/whp-dispatch.h |   0
 target/i386/{ => whpx}/whpx-all.c     |  11 +-
 target/i386/{ => whpx}/whpx-cpus.c    |   0
 target/i386/{ => whpx}/whpx-cpus.h    |   0
 75 files changed, 1555 insertions(+), 1091 deletions(-)
 create mode 100644 target/i386/cpu-dump.c
 rename target/i386/{ => hax}/hax-all.c (99%)
 rename target/i386/{ => hax}/hax-cpus.c (100%)
 rename target/i386/{ => hax}/hax-cpus.h (100%)
 rename target/i386/{ => hax}/hax-i386.h (95%)
 rename target/i386/{ => hax}/hax-interface.h (100%)
 rename target/i386/{ => hax}/hax-mem.c (100%)
 rename target/i386/{ => hax}/hax-posix.c (100%)
 rename target/i386/{ => hax}/hax-posix.h (100%)
 rename target/i386/{ => hax}/hax-windows.c (100%)
 rename target/i386/{ => hax}/hax-windows.h (100%)
 create mode 100644 target/i386/hax/meson.build
 create mode 100644 target/i386/helper-tcg.h
 create mode 100644 target/i386/host-cpu.c
 create mode 100644 target/i386/host-cpu.h
 create mode 100644 target/i386/hvf/cpu.c
 create mode 100644 target/i386/kvm/cpu.c
 rename target/i386/{ => kvm}/hyperv-proto.h (100%)
 rename target/i386/{ => kvm}/hyperv-stub.c (100%)
 rename target/i386/{ => kvm}/hyperv.c (100%)
 rename target/i386/{ => kvm}/hyperv.h (100%)
 create mode 100644 target/i386/kvm/kvm-cpu.h
 rename target/i386/{ => kvm}/kvm-stub.c (100%)
 rename target/i386/{ => kvm}/kvm.c (99%)
 rename target/i386/{ => kvm}/kvm_i386.h (100%)
 create mode 100644 target/i386/kvm/meson.build
 create mode 100644 target/i386/kvm/trace-events
 create mode 100644 target/i386/kvm/trace.h
 rename target/i386/{ => tcg}/bpt_helper.c (99%)
 rename target/i386/{ => tcg}/cc_helper.c (99%)
 create mode 100644 target/i386/tcg/cpu.c
 rename target/i386/{ => tcg}/excp_helper.c (99%)
 rename target/i386/{ => tcg}/fpu_helper.c (99%)
 rename target/i386/{ => tcg}/int_helper.c (99%)
 rename target/i386/{ => tcg}/mem_helper.c (99%)
 create mode 100644 target/i386/tcg/meson.build
 rename target/i386/{ => tcg}/misc_helper.c (99%)
 rename target/i386/{ => tcg}/mpx_helper.c (99%)
 rename target/i386/{ => tcg}/seg_helper.c (99%)
 rename target/i386/{ => tcg}/smm_helper.c (99%)
 rename target/i386/{ => tcg}/svm_helper.c (99%)
 rename target/i386/{ => tcg}/tcg-stub.c (100%)
 rename target/i386/{ => tcg}/translate.c (99%)
 create mode 100644 target/i386/whpx/meson.build
 rename target/i386/{ => whpx}/whp-dispatch.h (100%)
 rename target/i386/{ => whpx}/whpx-all.c (99%)
 rename target/i386/{ => whpx}/whpx-cpus.c (100%)
 rename target/i386/{ => whpx}/whpx-cpus.h (100%)

-- 
2.26.2



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

* [RFC v3 1/9] i386: move kvm accel files into kvm/
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 2/9] i386: move whpx accel files into whpx/ Claudio Fontana
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 2/9] i386: move whpx accel files into whpx/
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 1/9] i386: move kvm accel files into kvm/ Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 3/9] i386: move hax accel files into hax/ Claudio Fontana
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 3/9] i386: move hax accel files into hax/
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 1/9] i386: move kvm accel files into kvm/ Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 2/9] i386: move whpx accel files into whpx/ Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 4/9] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 4/9] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (2 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 3/9] i386: move hax accel files into hax/ Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 16:09   ` Roman Bolshakov
  2020-11-18 10:29 ` [RFC v3 5/9] i386: move TCG accel files into tcg/ Claudio Fontana
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 5/9] i386: move TCG accel files into tcg/
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (3 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 4/9] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 6/9] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 6/9] i386: move cpu dump out of helper.c into cpu-dump.c
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (4 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 5/9] i386: move TCG accel files into tcg/ Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 7/9] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 7/9] i386: move TCG cpu class initialization out of helper.c
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (5 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 6/9] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 10:29 ` [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

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

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



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

* [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (6 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 7/9] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 12:38   ` Claudio Fontana
  2020-11-18 12:48   ` Eduardo Habkost
  2020-11-18 10:29 ` [RFC v3 9/9] i386: split cpu accelerators from cpu.c Claudio Fontana
  2020-11-18 11:00 ` [RFC v3 0/9] i386 cleanup no-reply
  9 siblings, 2 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

apply this to the registration of the cpus accel interfaces,

but this will be also in preparation for later use of this
new module init step to also 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/hax/hax-all.c   | 12 +++++++++---
 target/i386/hvf/hvf.c       | 10 +++++++++-
 target/i386/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 e6e0ad5a92..df4bed056a 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4173,6 +4173,12 @@ void qemu_init(int argc, char **argv, char **envp)
      */
     configure_accelerators(argv[0]);
 
+    /*
+     * accelerator has been chosen and initialized, now it is time to
+     * register the cpu accel interface.
+     */
+    module_call_init(MODULE_INIT_ACCEL_CPU);
+
     /*
      * Beware, QOM objects created before this point miss global and
      * compat properties.
diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
index fecfe8cd6e..3bada019f5 100644
--- a/target/i386/hax/hax-all.c
+++ b/target/i386/hax/hax-all.c
@@ -364,9 +364,6 @@ static int hax_accel_init(MachineState *ms)
                 !ret ? "working" : "not working",
                 !ret ? "fast virt" : "emulation");
     }
-    if (ret == 0) {
-        cpus_register_accel(&hax_cpus);
-    }
     return ret;
 }
 
@@ -1141,3 +1138,12 @@ static void hax_type_init(void)
 }
 
 type_init(hax_type_init);
+
+static void hax_accel_cpu_init(void)
+{
+    if (hax_enabled()) {
+        cpus_register_accel(&hax_cpus);
+    }
+}
+
+accel_cpu_init(hax_accel_cpu_init);
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ed9356565c..249b77797f 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -887,7 +887,6 @@ static int hvf_accel_init(MachineState *ms)
   
     hvf_state = s;
     memory_listener_register(&hvf_memory_listener, &address_space_memory);
-    cpus_register_accel(&hvf_cpus);
     return 0;
 }
 
@@ -911,3 +910,12 @@ static void hvf_type_init(void)
 }
 
 type_init(hvf_type_init);
+
+static void hvf_accel_cpu_init(void)
+{
+    if (hvf_enabled()) {
+        cpus_register_accel(&hvf_cpus);
+    }
+}
+
+accel_cpu_init(hvf_accel_cpu_init);
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index f4f3e33eac..2e715e2bc6 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1642,8 +1642,6 @@ static int whpx_accel_init(MachineState *ms)
 
     whpx_memory_init();
 
-    cpus_register_accel(&whpx_cpus);
-
     printf("Windows Hypervisor Platform accelerator is operational\n");
     return 0;
 
@@ -1713,3 +1711,12 @@ error:
 }
 
 type_init(whpx_type_init);
+
+static void whpx_accel_cpu_init(void)
+{
+    if (whpx_enabled()) {
+        cpus_register_accel(&whpx_cpus);
+    }
+}
+
+accel_cpu_init(whpx_accel_cpu_init);
-- 
2.26.2



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

* [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (7 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
@ 2020-11-18 10:29 ` Claudio Fontana
  2020-11-18 18:28   ` Eduardo Habkost
  2020-11-18 11:00 ` [RFC v3 0/9] i386 cleanup no-reply
  9 siblings, 1 reply; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 10:29 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, Olaf Hering, Colin Xu

split cpu.c into:

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

The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
time, when the accelerator is known.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
---
 MAINTAINERS                 |   2 +-
 bsd-user/main.c             |   1 +
 hw/i386/pc_piix.c           |   1 +
 linux-user/main.c           |   1 +
 target/i386/cpu-qom.h       |  23 +++
 target/i386/cpu.c           | 395 +++++-------------------------------
 target/i386/cpu.h           |  20 +-
 target/i386/host-cpu.c      | 196 ++++++++++++++++++
 target/i386/host-cpu.h      |  20 ++
 target/i386/hvf/cpu.c       |  64 ++++++
 target/i386/hvf/meson.build |   1 +
 target/i386/kvm/cpu.c       | 145 +++++++++++++
 target/i386/kvm/kvm-cpu.h   |  41 ++++
 target/i386/kvm/kvm.c       |   3 +-
 target/i386/kvm/meson.build |   7 +-
 target/i386/meson.build     |   8 +-
 target/i386/tcg-cpu.c       |  71 -------
 target/i386/tcg-cpu.h       |  15 --
 target/i386/tcg/cpu.c       | 168 +++++++++++++++
 target/i386/tcg/meson.build |   3 +-
 20 files changed, 736 insertions(+), 449 deletions(-)
 create mode 100644 target/i386/host-cpu.c
 create mode 100644 target/i386/host-cpu.h
 create mode 100644 target/i386/hvf/cpu.c
 create mode 100644 target/i386/kvm/cpu.c
 create mode 100644 target/i386/kvm/kvm-cpu.h
 delete mode 100644 target/i386/tcg-cpu.c
 delete mode 100644 target/i386/tcg-cpu.h
 create mode 100644 target/i386/tcg/cpu.c

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



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

* Re: [RFC v3 0/9] i386 cleanup
  2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
                   ` (8 preceding siblings ...)
  2020-11-18 10:29 ` [RFC v3 9/9] i386: split cpu accelerators from cpu.c Claudio Fontana
@ 2020-11-18 11:00 ` no-reply
  9 siblings, 0 replies; 41+ messages in thread
From: no-reply @ 2020-11-18 11:00 UTC (permalink / raw)
  To: cfontana
  Cc: paul, jasowang, qemu-devel, peterx, haxm-team, colin.xu, ohering,
	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/20201118102936.25569-1-cfontana@suse.de/



Hi,

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

Type: series
Message-id: 20201118102936.25569-1-cfontana@suse.de
Subject: [RFC v3 0/9] i386 cleanup

=== 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
 * [new tag]         patchew/20201118102936.25569-1-cfontana@suse.de -> patchew/20201118102936.25569-1-cfontana@suse.de
 * [new tag]         patchew/20201118104202.1301363-1-cohuck@redhat.com -> patchew/20201118104202.1301363-1-cohuck@redhat.com
Switched to a new branch 'test'
f6ca212 i386: split cpu accelerators from cpu.c
cc955b2 module: introduce MODULE_INIT_ACCEL_CPU
2d7e19f i386: move TCG cpu class initialization out of helper.c
147af3d i386: move cpu dump out of helper.c into cpu-dump.c
87b7d59 i386: move TCG accel files into tcg/
cc16a3c i386: hvf: remove stale MAINTAINERS entry for old hvf stubs
7ac7172 i386: move hax accel files into hax/
7bf9e93 i386: move whpx accel files into whpx/
a77578d i386: move kvm accel files into kvm/

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

total: 0 errors, 1 warnings, 150 lines checked

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

total: 0 errors, 1 warnings, 32 lines checked

Patch 2/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/9 Checking commit 7ac71728106a (i386: move hax accel files into 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/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/9 Checking commit cc16a3c13543 (i386: hvf: remove stale MAINTAINERS entry for old hvf stubs)
5/9 Checking commit 87b7d59c263a (i386: move TCG accel files into tcg/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#44: 
rename from target/i386/bpt_helper.c

total: 0 errors, 1 warnings, 39 lines checked

Patch 5/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/9 Checking commit 147af3d785ba (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/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

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

total: 0 errors, 1 warnings, 610 lines checked

Patch 7/9 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/9 Checking commit cc955b2b3858 (module: introduce MODULE_INIT_ACCEL_CPU)
9/9 Checking commit f6ca212625cb (i386: split cpu accelerators from cpu.c)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#727: 
new file mode 100644

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

total: 0 errors, 2 warnings, 1331 lines checked

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

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20201118102936.25569-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] 41+ messages in thread

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-18 10:29 ` [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
@ 2020-11-18 12:38   ` Claudio Fontana
  2020-11-18 12:48   ` Eduardo Habkost
  1 sibling, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-18 12:38 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, Colin Xu, Anthony Perard,
	Bruce Rogers, Olaf Hering

On 11/18/20 11:29 AM, Claudio Fontana wrote:
> apply this to the registration of the cpus accel interfaces,
> 
> but this will be also in preparation for later use of this
> new module init step to also defer the registration of the cpu models,



this is not true anymore, so my commit message here needs fixing.



> 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/hax/hax-all.c   | 12 +++++++++---
>  target/i386/hvf/hvf.c       | 10 +++++++++-
>  target/i386/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 e6e0ad5a92..df4bed056a 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -4173,6 +4173,12 @@ void qemu_init(int argc, char **argv, char **envp)
>       */
>      configure_accelerators(argv[0]);
>  
> +    /*
> +     * accelerator has been chosen and initialized, now it is time to
> +     * register the cpu accel interface.
> +     */
> +    module_call_init(MODULE_INIT_ACCEL_CPU);
> +
>      /*
>       * Beware, QOM objects created before this point miss global and
>       * compat properties.
> diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
> index fecfe8cd6e..3bada019f5 100644
> --- a/target/i386/hax/hax-all.c
> +++ b/target/i386/hax/hax-all.c
> @@ -364,9 +364,6 @@ static int hax_accel_init(MachineState *ms)
>                  !ret ? "working" : "not working",
>                  !ret ? "fast virt" : "emulation");
>      }
> -    if (ret == 0) {
> -        cpus_register_accel(&hax_cpus);
> -    }
>      return ret;
>  }
>  
> @@ -1141,3 +1138,12 @@ static void hax_type_init(void)
>  }
>  
>  type_init(hax_type_init);
> +
> +static void hax_accel_cpu_init(void)
> +{
> +    if (hax_enabled()) {
> +        cpus_register_accel(&hax_cpus);
> +    }
> +}
> +
> +accel_cpu_init(hax_accel_cpu_init);
> diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
> index ed9356565c..249b77797f 100644
> --- a/target/i386/hvf/hvf.c
> +++ b/target/i386/hvf/hvf.c
> @@ -887,7 +887,6 @@ static int hvf_accel_init(MachineState *ms)
>    
>      hvf_state = s;
>      memory_listener_register(&hvf_memory_listener, &address_space_memory);
> -    cpus_register_accel(&hvf_cpus);
>      return 0;
>  }
>  
> @@ -911,3 +910,12 @@ static void hvf_type_init(void)
>  }
>  
>  type_init(hvf_type_init);
> +
> +static void hvf_accel_cpu_init(void)
> +{
> +    if (hvf_enabled()) {
> +        cpus_register_accel(&hvf_cpus);
> +    }
> +}
> +
> +accel_cpu_init(hvf_accel_cpu_init);
> diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
> index f4f3e33eac..2e715e2bc6 100644
> --- a/target/i386/whpx/whpx-all.c
> +++ b/target/i386/whpx/whpx-all.c
> @@ -1642,8 +1642,6 @@ static int whpx_accel_init(MachineState *ms)
>  
>      whpx_memory_init();
>  
> -    cpus_register_accel(&whpx_cpus);
> -
>      printf("Windows Hypervisor Platform accelerator is operational\n");
>      return 0;
>  
> @@ -1713,3 +1711,12 @@ error:
>  }
>  
>  type_init(whpx_type_init);
> +
> +static void whpx_accel_cpu_init(void)
> +{
> +    if (whpx_enabled()) {
> +        cpus_register_accel(&whpx_cpus);
> +    }
> +}
> +
> +accel_cpu_init(whpx_accel_cpu_init);
> 



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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-18 10:29 ` [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
  2020-11-18 12:38   ` Claudio Fontana
@ 2020-11-18 12:48   ` Eduardo Habkost
  2020-11-18 13:48     ` Claudio Fontana
  1 sibling, 1 reply; 41+ messages in thread
From: Eduardo Habkost @ 2020-11-18 12:48 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Olaf Hering, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, Colin Xu,
	Wenchao Wang, Anthony Perard, Paolo Bonzini, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	haxm-team, Richard Henderson

On Wed, Nov 18, 2020 at 11:29:35AM +0100, Claudio Fontana wrote:
> apply this to the registration of the cpus accel interfaces,
> 
> but this will be also in preparation for later use of this
> new module init step to also 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>
> ---
[...]
> +    /*
> +     * accelerator has been chosen and initialized, now it is time to
> +     * register the cpu accel interface.
> +     */
> +    module_call_init(MODULE_INIT_ACCEL_CPU);

I don't get why we would use a new module initialization level
for this.  If the accelerator object was already created, we can
just ask the existing accel object to do whatever initialization
step is necessary.

e.g. we can add a AccelClass.cpu_accel_ops field, and call:

   cpus_register_accel(current_machine->accelerator->cpu_accel_ops);

-- 
Eduardo



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

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

On 11/18/20 1:48 PM, Eduardo Habkost wrote:
> On Wed, Nov 18, 2020 at 11:29:35AM +0100, Claudio Fontana wrote:
>> apply this to the registration of the cpus accel interfaces,
>>
>> but this will be also in preparation for later use of this
>> new module init step to also 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>
>> ---
> [...]
>> +    /*
>> +     * accelerator has been chosen and initialized, now it is time to
>> +     * register the cpu accel interface.
>> +     */
>> +    module_call_init(MODULE_INIT_ACCEL_CPU);
> 
> I don't get why we would use a new module initialization level

To have a clear point in time after which all accelerator interface initialization is done.
It avoids to have to hunt down the registration points spread around the code base.
I'd turn it around, why not?

> for this.  If the accelerator object was already created, we can
> just ask the existing accel object to do whatever initialization
> step is necessary.
> 
> e.g. we can add a AccelClass.cpu_accel_ops field, and call:
> 
>    cpus_register_accel(current_machine->accelerator->cpu_accel_ops);
> 

_When_ this is done is the question, in my view, where the call to the registration is placed.

After adding additonal operations that have to be done at "accelerator-chosen" time, it becomes more and more difficult to trace them around the codebase.

Thanks,

Claudio






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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-18 13:48     ` Claudio Fontana
@ 2020-11-18 14:05       ` Paolo Bonzini
  2020-11-18 14:36         ` Eduardo Habkost
  0 siblings, 1 reply; 41+ messages in thread
From: Paolo Bonzini @ 2020-11-18 14:05 UTC (permalink / raw)
  To: Claudio Fontana, Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Olaf Hering, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, Colin Xu,
	Wenchao Wang, Anthony Perard, haxm-team, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	Richard Henderson

On 18/11/20 14:48, Claudio Fontana wrote:
> On 11/18/20 1:48 PM, Eduardo Habkost wrote:
>> On Wed, Nov 18, 2020 at 11:29:35AM +0100, Claudio Fontana wrote:
>>> apply this to the registration of the cpus accel interfaces,
>>>
>>> but this will be also in preparation for later use of this
>>> new module init step to also 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>
>>> ---
>> [...]
>>> +    /*
>>> +     * accelerator has been chosen and initialized, now it is time to
>>> +     * register the cpu accel interface.
>>> +     */
>>> +    module_call_init(MODULE_INIT_ACCEL_CPU);
>>
>> I don't get why we would use a new module initialization level
> 
> To have a clear point in time after which all accelerator interface initialization is done.
> It avoids to have to hunt down the registration points spread around the code base.
> I'd turn it around, why not?

I see two disadvantages:

1) you have to hunt down accel_cpu_inits instead of looking at 
accelerator classes. :)

2) all callbacks have an "if (*_enabled())" around the actual meat. 
Another related issue is that usually the module_call_init are 
unconditional.

I think the idea of using module_call_init is good however.  What about:

static void kvm_cpu_accel_init(void)
{
     x86_cpu_accel_init(&kvm_cpu_accel);
}

static void kvm_cpu_accel_register(void)
{
     accel_register_call(TYPE_KVM, kvm_cpu_accel_init);
}
accel_cpu_init(kvm_cpu_accel_register);

...

void
accel_register_call(const char *qom_type, void (*fn)(void))
{
     AccelClass *acc = ACCEL_CLASS(object_class_by_name(qom_type));

     acc->setup_calls = g_slist_append(acc->setup_calls, (void *)fn);
}

void
accel_do_call(void *data, void *unused)
{
     void (*fn)(void) = data;

     data();
}

int accel_init_machine(AccelState *accel, MachineState *ms)
{
...
     if (ret < 0) {
         ms->accelerator = NULL;
         *(acc->allowed) = false;
         object_unref(OBJECT(accel));
     } else {
         object_set_accelerator_compat_props(acc->compat_props);
         g_slist_foreach(acc->setup_calls, accel_do_call, NULL);
     }
     return ret;
}

where the module_call_init would be right after MODULE_INIT_QOM

Paolo

>> for this.  If the accelerator object was already created, we can
>> just ask the existing accel object to do whatever initialization
>> step is necessary.
>>
>> e.g. we can add a AccelClass.cpu_accel_ops field, and call:
>>
>>     cpus_register_accel(current_machine->accelerator->cpu_accel_ops);
>>
> 
> _When_ this is done is the question, in my view, where the call to the registration is placed.
> 
> After adding additonal operations that have to be done at "accelerator-chosen" time, it becomes more and more difficult to trace them around the codebase.
> 
> Thanks,
> 
> Claudio
> 
> 
> 
> 



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

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

On Wed, Nov 18, 2020 at 03:05:42PM +0100, Paolo Bonzini wrote:
> On 18/11/20 14:48, Claudio Fontana wrote:
> > On 11/18/20 1:48 PM, Eduardo Habkost wrote:
> > > On Wed, Nov 18, 2020 at 11:29:35AM +0100, Claudio Fontana wrote:
> > > > apply this to the registration of the cpus accel interfaces,
> > > > 
> > > > but this will be also in preparation for later use of this
> > > > new module init step to also 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>
> > > > ---
> > > [...]
> > > > +    /*
> > > > +     * accelerator has been chosen and initialized, now it is time to
> > > > +     * register the cpu accel interface.
> > > > +     */
> > > > +    module_call_init(MODULE_INIT_ACCEL_CPU);
> > > 
> > > I don't get why we would use a new module initialization level
> > 
> > To have a clear point in time after which all accelerator interface initialization is done.
> > It avoids to have to hunt down the registration points spread around the code base.
> > I'd turn it around, why not?
> 
> I see two disadvantages:
> 
> 1) you have to hunt down accel_cpu_inits instead of looking at accelerator
> classes. :)
> 
> 2) all callbacks have an "if (*_enabled())" around the actual meat. Another
> related issue is that usually the module_call_init are unconditional.
> 
> I think the idea of using module_call_init is good however.  What about:
> 
> static void kvm_cpu_accel_init(void)
> {
>     x86_cpu_accel_init(&kvm_cpu_accel);

What do you expect x86_cpu_accel_init() to do?

> }
> 
> static void kvm_cpu_accel_register(void)
> {
>     accel_register_call(TYPE_KVM, kvm_cpu_accel_init);
> }
> accel_cpu_init(kvm_cpu_accel_register);
> 
> ...
> 
> void
> accel_register_call(const char *qom_type, void (*fn)(void))
> {
>     AccelClass *acc = ACCEL_CLASS(object_class_by_name(qom_type));
> 
>     acc->setup_calls = g_slist_append(acc->setup_calls, (void *)fn);
> }
> 
> void
> accel_do_call(void *data, void *unused)
> {
>     void (*fn)(void) = data;
> 
>     data();
> }
> 
> int accel_init_machine(AccelState *accel, MachineState *ms)
> {
> ...
>     if (ret < 0) {
>         ms->accelerator = NULL;
>         *(acc->allowed) = false;
>         object_unref(OBJECT(accel));
>     } else {
>         object_set_accelerator_compat_props(acc->compat_props);
>         g_slist_foreach(acc->setup_calls, accel_do_call, NULL);

Why all this extra complexity if you can simply do:

  ACCEL_GET_CLASS(acc)->finish_arch_specific_init();

?


>     }
>     return ret;
> }
> 
> where the module_call_init would be right after MODULE_INIT_QOM
> 
> Paolo
> 
> > > for this.  If the accelerator object was already created, we can
> > > just ask the existing accel object to do whatever initialization
> > > step is necessary.
> > > 
> > > e.g. we can add a AccelClass.cpu_accel_ops field, and call:
> > > 
> > >     cpus_register_accel(current_machine->accelerator->cpu_accel_ops);
> > > 
> > 
> > _When_ this is done is the question, in my view, where the call to the registration is placed.
> > 
> > After adding additonal operations that have to be done at
> > "accelerator-chosen" time, it becomes more and more difficult
> > to trace them around the codebase.

I don't understand why a separate module init level is necessary
here.

Making sure module_call_init() is called at the correct moment is
not easier or safer than just making sure accel_init_machine()
(or another init function you create) is called at the correct
moment.

-- 
Eduardo



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

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

On 18/11/20 15:36, Eduardo Habkost wrote:
> On Wed, Nov 18, 2020 at 03:05:42PM +0100, Paolo Bonzini wrote:
>> On 18/11/20 14:48, Claudio Fontana wrote:
>>> On 11/18/20 1:48 PM, Eduardo Habkost wrote:
>>>> I don't get why we would use a new module initialization level
>>>
>>> To have a clear point in time after which all accelerator interface initialization is done.
>>> It avoids to have to hunt down the registration points spread around the code base.
>>> I'd turn it around, why not?
>>
>> I see two disadvantages:
>>
>> 1) you have to hunt down accel_cpu_inits instead of looking at accelerator
>> classes. :)
>>
>> 2) all callbacks have an "if (*_enabled())" around the actual meat. Another
>> related issue is that usually the module_call_init are unconditional.
>>
>> I think the idea of using module_call_init is good however.  What about:
>>
>> static void kvm_cpu_accel_init(void)
>> {
>>      x86_cpu_accel_init(&kvm_cpu_accel);
> 
> What do you expect x86_cpu_accel_init() to do?

I don't know, the same that it was doing in Claudio's patches. :)

He had

	if (kvm_enabled()) {
	    x86_cpu_accel_init(&kvm_cpu_accel);
	}

and I'm calling only the function that is registered on the enabled 
accelerator.

> I don't understand why a separate module init level is necessary
> here.

Because you must call accel_register_call after the TYPE_KVM type has 
been registered, or object_class_by_name fails:

void
accel_register_call(const char *qom_type, void (*fn)(void))
{
     AccelClass *acc = ACCEL_CLASS(object_class_by_name(qom_type));

     acc->setup_calls = g_slist_append(acc->setup_calls, (void *)fn);
}

The alternative is to store the (type, function) tuple directly, with 
the type as a string.  Then you can just use type_init.

> Making sure module_call_init() is called at the correct moment is
> not easier or safer than just making sure accel_init_machine()
> (or another init function you create) is called at the correct
> moment.

Since there is a way to do it without a new level, that would of course 
be fine for me too.  Let me explain however why I think Claudio's design 
had module_call_init() misplaced and what the fundamental difference is. 
  The basic phases in qemu_init() are:

- initialize stuff
- parse command line
- create machine
- create accelerator
- initialize machine
- create devices
- start

with a mess of other object creation sprinkled between the various 
phases (but we don't care about those).

What I object to, is calling module_call_init() after the "initialize 
stuff" phase.  Claudio was using it to call the function directly, so it 
had to be exactly at "create accelerator".  This is different from all 
other module_call_init() calls, which are done very early.

With the implementation I sketched, accel_register_call must still be 
done after type_init, so there's still an ordering constraint, but all 
it's doing is registering a callback in the "initialize stuff" phase.

Thanks,

Paolo



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

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

On Wed, Nov 18, 2020 at 03:51:44PM +0100, Paolo Bonzini wrote:
> On 18/11/20 15:36, Eduardo Habkost wrote:
> > On Wed, Nov 18, 2020 at 03:05:42PM +0100, Paolo Bonzini wrote:
> > > On 18/11/20 14:48, Claudio Fontana wrote:
> > > > On 11/18/20 1:48 PM, Eduardo Habkost wrote:
> > > > > I don't get why we would use a new module initialization level
> > > > 
> > > > To have a clear point in time after which all accelerator interface initialization is done.
> > > > It avoids to have to hunt down the registration points spread around the code base.
> > > > I'd turn it around, why not?
> > > 
> > > I see two disadvantages:
> > > 
> > > 1) you have to hunt down accel_cpu_inits instead of looking at accelerator
> > > classes. :)
> > > 
> > > 2) all callbacks have an "if (*_enabled())" around the actual meat. Another
> > > related issue is that usually the module_call_init are unconditional.
> > > 
> > > I think the idea of using module_call_init is good however.  What about:
> > > 
> > > static void kvm_cpu_accel_init(void)
> > > {
> > >      x86_cpu_accel_init(&kvm_cpu_accel);
> > 
> > What do you expect x86_cpu_accel_init() to do?
> 
> I don't know, the same that it was doing in Claudio's patches. :)
> 
> He had
> 
> 	if (kvm_enabled()) {
> 	    x86_cpu_accel_init(&kvm_cpu_accel);
> 	}
> 
> and I'm calling only the function that is registered on the enabled
> accelerator.
> 
> > I don't understand why a separate module init level is necessary
> > here.
> 
> Because you must call accel_register_call after the TYPE_KVM type has been
> registered, or object_class_by_name fails:
> 
> void
> accel_register_call(const char *qom_type, void (*fn)(void))
> {
>     AccelClass *acc = ACCEL_CLASS(object_class_by_name(qom_type));
> 
>     acc->setup_calls = g_slist_append(acc->setup_calls, (void *)fn);
> }
> 
> The alternative is to store the (type, function) tuple directly, with the
> type as a string.  Then you can just use type_init.

Right.  Let's build on top of that:

Another alternative would be to store a (type, X86CPUAccel) tuple
directly, with the type as string.  This would save the extra
indirection of the x86_cpu_accel_init() call.

It turns out we already have a mechanism to register and store
(type, StructContainingFunctionPointers) tuples at initialization
time: QOM.

X86CPUAccel can become X86CPUAccelClass, and be registered as a
QOM type.  It could be a subtype of TYPE_ACCEL or not, it
shouldn't matter.

I remember this was suggested in a previous thread, but I don't
remember if there were any objections.

> 
> > Making sure module_call_init() is called at the correct moment is
> > not easier or safer than just making sure accel_init_machine()
> > (or another init function you create) is called at the correct
> > moment.
> 
> Since there is a way to do it without a new level, that would of course be
> fine for me too.  Let me explain however why I think Claudio's design had
> module_call_init() misplaced and what the fundamental difference is.  The
> basic phases in qemu_init() are:
> 
> - initialize stuff
> - parse command line
> - create machine
> - create accelerator
> - initialize machine
> - create devices
> - start
> 
> with a mess of other object creation sprinkled between the various phases
> (but we don't care about those).
> 
> What I object to, is calling module_call_init() after the "initialize stuff"
> phase.  Claudio was using it to call the function directly, so it had to be
> exactly at "create accelerator".  This is different from all other
> module_call_init() calls, which are done very early.

I agree.

> 
> With the implementation I sketched, accel_register_call must still be done
> after type_init, so there's still an ordering constraint, but all it's doing
> is registering a callback in the "initialize stuff" phase.

Makes sense, if we really want to introduce a new accel_register_call()
abstraction.  I don't think we need it, though.

-- 
Eduardo



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

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

[-- Attachment #1: Type: text/plain, Size: 2773 bytes --]

Il mer 18 nov 2020, 16:26 Eduardo Habkost <ehabkost@redhat.com> ha scritto:

>
> > The alternative is to store the (type, function) tuple directly, with the
> > type as a string.  Then you can just use type_init.
>
> Right.  Let's build on top of that:
>
> Another alternative would be to store a (type, X86CPUAccel) tuple
> directly, with the type as string.  This would save the extra
> indirection of the x86_cpu_accel_init() call.
>
> It turns out we already have a mechanism to register and store
> (type, StructContainingFunctionPointers) tuples at initialization
> time: QOM.
>
> X86CPUAccel can become X86CPUAccelClass, and be registered as a
> QOM type.  It could be a subtype of TYPE_ACCEL or not, it
> shouldn't matter.
>

It would be a weird type that isn't instantiated, and/or that does nothing
but monkey patching other classes. I don't think it's a good fit.

Yet another possibility is to use GHashTable. It is limited to one value
per key, but it's enough if everything is kept local to {hw,target}/i386.
If needed a new function pointer can be added to MachineClass, implemented
in X86MachineState (where the GHashTable would also be) and called in
accel.c.

Paolo

Paolo


> I remember this was suggested in a previous thread, but I don't
> remember if there were any objections.
>
> >
> > > Making sure module_call_init() is called at the correct moment is
> > > not easier or safer than just making sure accel_init_machine()
> > > (or another init function you create) is called at the correct
> > > moment.
> >
> > Since there is a way to do it without a new level, that would of course
> be
> > fine for me too.  Let me explain however why I think Claudio's design had
> > module_call_init() misplaced and what the fundamental difference is.  The
> > basic phases in qemu_init() are:
> >
> > - initialize stuff
> > - parse command line
> > - create machine
> > - create accelerator
> > - initialize machine
> > - create devices
> > - start
> >
> > with a mess of other object creation sprinkled between the various phases
> > (but we don't care about those).
> >
> > What I object to, is calling module_call_init() after the "initialize
> stuff"
> > phase.  Claudio was using it to call the function directly, so it had to
> be
> > exactly at "create accelerator".  This is different from all other
> > module_call_init() calls, which are done very early.
>
> I agree.
>
> >
> > With the implementation I sketched, accel_register_call must still be
> done
> > after type_init, so there's still an ordering constraint, but all it's
> doing
> > is registering a callback in the "initialize stuff" phase.
>
> Makes sense, if we really want to introduce a new accel_register_call()
> abstraction.  I don't think we need it, though.
>
> --
> Eduardo
>
>

[-- Attachment #2: Type: text/html, Size: 3804 bytes --]

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

* Re: [RFC v3 4/9] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs
  2020-11-18 10:29 ` [RFC v3 4/9] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
@ 2020-11-18 16:09   ` Roman Bolshakov
  0 siblings, 0 replies; 41+ messages in thread
From: Roman Bolshakov @ 2020-11-18 16:09 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Eduardo Habkost,
	Paul Durrant, Olaf Hering, Jason Wang, Marcelo Tosatti,
	qemu-devel, Peter Xu, Dario Faggioli, Cameron Esfahani, Colin Xu,
	Wenchao Wang, Anthony Perard, Paolo Bonzini, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	haxm-team, Richard Henderson

On Wed, Nov 18, 2020 at 11:29:31AM +0100, Claudio Fontana wrote:
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
>  MAINTAINERS | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 463317784c..e892dd2220 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -443,7 +443,6 @@ M: Cameron Esfahani <dirty@apple.com>
>  M: Roman Bolshakov <r.bolshakov@yadro.com>
>  W: https://wiki.qemu.org/Features/HVF
>  S: Maintained
> -F: accel/stubs/hvf-stub.c
>  F: target/i386/hvf/
>  F: include/sysemu/hvf.h
>  
> -- 
> 2.26.2
> 

Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>

Thanks,
Roman


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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-18 15:43               ` Paolo Bonzini
@ 2020-11-18 16:11                 ` Eduardo Habkost
  2020-11-18 16:22                   ` Paolo Bonzini
  0 siblings, 1 reply; 41+ messages in thread
From: Eduardo Habkost @ 2020-11-18 16:11 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Laurent Vivier, Bruce Rogers, Thomas Huth, Stefano Stabellini,
	Paul Durrant, Olaf Hering, Jason Wang, Marcelo Tosatti,
	qemu-devel, Peter Xu, Dario Faggioli, Roman Bolshakov,
	Cameron Esfahani, Colin Xu, Wenchao Wang, Anthony Perard,
	haxm-team, Sunil Muthuswamy, Richard Henderson,
	Philippe Mathieu-Daudé,
	Claudio Fontana

On Wed, Nov 18, 2020 at 04:43:19PM +0100, Paolo Bonzini wrote:
> Il mer 18 nov 2020, 16:26 Eduardo Habkost <ehabkost@redhat.com> ha scritto:
> 
> >
> > > The alternative is to store the (type, function) tuple directly, with the
> > > type as a string.  Then you can just use type_init.
> >
> > Right.  Let's build on top of that:
> >
> > Another alternative would be to store a (type, X86CPUAccel) tuple
> > directly, with the type as string.  This would save the extra
> > indirection of the x86_cpu_accel_init() call.
> >
> > It turns out we already have a mechanism to register and store
> > (type, StructContainingFunctionPointers) tuples at initialization
> > time: QOM.
> >
> > X86CPUAccel can become X86CPUAccelClass, and be registered as a
> > QOM type.  It could be a subtype of TYPE_ACCEL or not, it
> > shouldn't matter.
> >
> 
> It would be a weird type that isn't instantiated, and/or that does nothing
> but monkey patching other classes. I don't think it's a good fit.

The whole point of this would be to avoid monkey patching other
classes.

Why wouldn't we instantiate it?  There's a huge number of static
variables in target/i386/kvm.c that could be moved to that
object.  Sounds like a perfect fit for me.

I won't try to stop you if you really want to invent a brand new
(name => CollectionOfFunctionPointers) registry, but it seems
unnecessary.

> 
> Yet another possibility is to use GHashTable. It is limited to one value
> per key, but it's enough if everything is kept local to {hw,target}/i386.
> If needed a new function pointer can be added to MachineClass, implemented
> in X86MachineState (where the GHashTable would also be) and called in
> accel.c.
> 
> Paolo
> 
> Paolo
> 
> 
> > I remember this was suggested in a previous thread, but I don't
> > remember if there were any objections.
> >
> > >
> > > > Making sure module_call_init() is called at the correct moment is
> > > > not easier or safer than just making sure accel_init_machine()
> > > > (or another init function you create) is called at the correct
> > > > moment.
> > >
> > > Since there is a way to do it without a new level, that would of course
> > be
> > > fine for me too.  Let me explain however why I think Claudio's design had
> > > module_call_init() misplaced and what the fundamental difference is.  The
> > > basic phases in qemu_init() are:
> > >
> > > - initialize stuff
> > > - parse command line
> > > - create machine
> > > - create accelerator
> > > - initialize machine
> > > - create devices
> > > - start
> > >
> > > with a mess of other object creation sprinkled between the various phases
> > > (but we don't care about those).
> > >
> > > What I object to, is calling module_call_init() after the "initialize
> > stuff"
> > > phase.  Claudio was using it to call the function directly, so it had to
> > be
> > > exactly at "create accelerator".  This is different from all other
> > > module_call_init() calls, which are done very early.
> >
> > I agree.
> >
> > >
> > > With the implementation I sketched, accel_register_call must still be
> > done
> > > after type_init, so there's still an ordering constraint, but all it's
> > doing
> > > is registering a callback in the "initialize stuff" phase.
> >
> > Makes sense, if we really want to introduce a new accel_register_call()
> > abstraction.  I don't think we need it, though.
> >
> > --
> > Eduardo
> >
> >

-- 
Eduardo



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

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

[-- Attachment #1: Type: text/plain, Size: 4349 bytes --]

Il mer 18 nov 2020, 17:11 Eduardo Habkost <ehabkost@redhat.com> ha scritto:

> On Wed, Nov 18, 2020 at 04:43:19PM +0100, Paolo Bonzini wrote:
> > Il mer 18 nov 2020, 16:26 Eduardo Habkost <ehabkost@redhat.com> ha
> scritto:
> >
> > >
> > > > The alternative is to store the (type, function) tuple directly,
> with the
> > > > type as a string.  Then you can just use type_init.
> > >
> > > Right.  Let's build on top of that:
> > >
> > > Another alternative would be to store a (type, X86CPUAccel) tuple
> > > directly, with the type as string.  This would save the extra
> > > indirection of the x86_cpu_accel_init() call.
> > >
> > > It turns out we already have a mechanism to register and store
> > > (type, StructContainingFunctionPointers) tuples at initialization
> > > time: QOM.
> > >
> > > X86CPUAccel can become X86CPUAccelClass, and be registered as a
> > > QOM type.  It could be a subtype of TYPE_ACCEL or not, it
> > > shouldn't matter.
> > >
> >
> > It would be a weird type that isn't instantiated, and/or that does
> nothing
> > but monkey patching other classes. I don't think it's a good fit.
>
> The whole point of this would be to avoid monkey patching other
> classes.
>

Adding a layer of indirect calls is not very different from monkey patching
though.

You also have to consider that accel currently does not exist in usermode
emulators, so that's an issue too. I would rather get a simple change in
quickly, instead of designing the perfect class hierarchy.

Perhaps another idea would be to allow adding interfaces to classes
*separately from the registration of the types*. Then we can use it to add
SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
add the accel object to usermode emulators.

Why wouldn't we instantiate it?  There's a huge number of static
> variables in target/i386/kvm.c that could be moved to that
> object.  Sounds like a perfect fit for me.
>

Most of those are properties of the running kernel so there's no need to
move them inside an object.

Paolo

I won't try to stop you if you really want to invent a brand new
> (name => CollectionOfFunctionPointers) registry, but it seems
> unnecessary.
>
> >
> > Yet another possibility is to use GHashTable. It is limited to one value
> > per key, but it's enough if everything is kept local to {hw,target}/i386.
> > If needed a new function pointer can be added to MachineClass,
> implemented
> > in X86MachineState (where the GHashTable would also be) and called in
> > accel.c.
> >
> > Paolo
> >
> > Paolo
> >
> >
> > > I remember this was suggested in a previous thread, but I don't
> > > remember if there were any objections.
> > >
> > > >
> > > > > Making sure module_call_init() is called at the correct moment is
> > > > > not easier or safer than just making sure accel_init_machine()
> > > > > (or another init function you create) is called at the correct
> > > > > moment.
> > > >
> > > > Since there is a way to do it without a new level, that would of
> course
> > > be
> > > > fine for me too.  Let me explain however why I think Claudio's
> design had
> > > > module_call_init() misplaced and what the fundamental difference
> is.  The
> > > > basic phases in qemu_init() are:
> > > >
> > > > - initialize stuff
> > > > - parse command line
> > > > - create machine
> > > > - create accelerator
> > > > - initialize machine
> > > > - create devices
> > > > - start
> > > >
> > > > with a mess of other object creation sprinkled between the various
> phases
> > > > (but we don't care about those).
> > > >
> > > > What I object to, is calling module_call_init() after the "initialize
> > > stuff"
> > > > phase.  Claudio was using it to call the function directly, so it
> had to
> > > be
> > > > exactly at "create accelerator".  This is different from all other
> > > > module_call_init() calls, which are done very early.
> > >
> > > I agree.
> > >
> > > >
> > > > With the implementation I sketched, accel_register_call must still be
> > > done
> > > > after type_init, so there's still an ordering constraint, but all
> it's
> > > doing
> > > > is registering a callback in the "initialize stuff" phase.
> > >
> > > Makes sense, if we really want to introduce a new accel_register_call()
> > > abstraction.  I don't think we need it, though.
> > >
> > > --
> > > Eduardo
> > >
> > >
>
> --
> Eduardo
>
>

[-- Attachment #2: Type: text/html, Size: 6279 bytes --]

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

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

On Wed, Nov 18, 2020 at 05:22:46PM +0100, Paolo Bonzini wrote:
> Il mer 18 nov 2020, 17:11 Eduardo Habkost <ehabkost@redhat.com> ha scritto:
> 
> > On Wed, Nov 18, 2020 at 04:43:19PM +0100, Paolo Bonzini wrote:
> > > Il mer 18 nov 2020, 16:26 Eduardo Habkost <ehabkost@redhat.com> ha
> > scritto:
> > >
> > > >
> > > > > The alternative is to store the (type, function) tuple directly,
> > with the
> > > > > type as a string.  Then you can just use type_init.
> > > >
> > > > Right.  Let's build on top of that:
> > > >
> > > > Another alternative would be to store a (type, X86CPUAccel) tuple
> > > > directly, with the type as string.  This would save the extra
> > > > indirection of the x86_cpu_accel_init() call.
> > > >
> > > > It turns out we already have a mechanism to register and store
> > > > (type, StructContainingFunctionPointers) tuples at initialization
> > > > time: QOM.
> > > >
> > > > X86CPUAccel can become X86CPUAccelClass, and be registered as a
> > > > QOM type.  It could be a subtype of TYPE_ACCEL or not, it
> > > > shouldn't matter.
> > > >
> > >
> > > It would be a weird type that isn't instantiated, and/or that does
> > nothing
> > > but monkey patching other classes. I don't think it's a good fit.
> >
> > The whole point of this would be to avoid monkey patching other
> > classes.
> >
> 
> Adding a layer of indirect calls is not very different from monkey patching
> though.

I'm a little bothered by monkey patching, but I'm more
bothered by having to:

(1) register (module_init()) a function (kvm_cpu_accel_register()) that
  (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
    (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
      (4) will be saved in multiple QOM classes, so that
        (5) we will call the right X86CPUClass.accel method at the right moment
            (common_class_init(), instance_init(), realizefn()),
where:
  step 4 must be done before any CPU object is created
    (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
     will be silently ignored), and
  step 3 must be done after all QOM types were registered.



> 
> You also have to consider that accel currently does not exist in usermode
> emulators, so that's an issue too. I would rather get a simple change in
> quickly, instead of designing the perfect class hierarchy.

It doesn't have to be perfect.  I agree that simple is better.

To me, registering a QOM type and looking it up when necessary is
simpler than the above.  Even if it's a weird class having no
object instances.  It probably could be an interface type.

> 
> Perhaps another idea would be to allow adding interfaces to classes
> *separately from the registration of the types*. Then we can use it to add
> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
> add the accel object to usermode emulators.

I'm not sure I follow.  What do you mean by bare bones accel
class, and when exactly would you add the new interfaces to the
classes?

> 
> Why wouldn't we instantiate it?  There's a huge number of static
> > variables in target/i386/kvm.c that could be moved to that
> > object.  Sounds like a perfect fit for me.
> >
> 
> Most of those are properties of the running kernel so there's no need to
> move them inside an object.

There's no need, correct.  Some consistency would be nice,
though.  All kernel capabilities in kvm-all.c are saved in
KVMState.

> 
> Paolo
> 
> I won't try to stop you if you really want to invent a brand new
> > (name => CollectionOfFunctionPointers) registry, but it seems
> > unnecessary.
> >
> > >
> > > Yet another possibility is to use GHashTable. It is limited to one value
> > > per key, but it's enough if everything is kept local to {hw,target}/i386.
> > > If needed a new function pointer can be added to MachineClass,
> > implemented
> > > in X86MachineState (where the GHashTable would also be) and called in
> > > accel.c.
> > >
> > > Paolo
> > >
> > > Paolo
> > >
> > >
> > > > I remember this was suggested in a previous thread, but I don't
> > > > remember if there were any objections.
> > > >
> > > > >
> > > > > > Making sure module_call_init() is called at the correct moment is
> > > > > > not easier or safer than just making sure accel_init_machine()
> > > > > > (or another init function you create) is called at the correct
> > > > > > moment.
> > > > >
> > > > > Since there is a way to do it without a new level, that would of
> > course
> > > > be
> > > > > fine for me too.  Let me explain however why I think Claudio's
> > design had
> > > > > module_call_init() misplaced and what the fundamental difference
> > is.  The
> > > > > basic phases in qemu_init() are:
> > > > >
> > > > > - initialize stuff
> > > > > - parse command line
> > > > > - create machine
> > > > > - create accelerator
> > > > > - initialize machine
> > > > > - create devices
> > > > > - start
> > > > >
> > > > > with a mess of other object creation sprinkled between the various
> > phases
> > > > > (but we don't care about those).
> > > > >
> > > > > What I object to, is calling module_call_init() after the "initialize
> > > > stuff"
> > > > > phase.  Claudio was using it to call the function directly, so it
> > had to
> > > > be
> > > > > exactly at "create accelerator".  This is different from all other
> > > > > module_call_init() calls, which are done very early.
> > > >
> > > > I agree.
> > > >
> > > > >
> > > > > With the implementation I sketched, accel_register_call must still be
> > > > done
> > > > > after type_init, so there's still an ordering constraint, but all
> > it's
> > > > doing
> > > > > is registering a callback in the "initialize stuff" phase.
> > > >
> > > > Makes sense, if we really want to introduce a new accel_register_call()
> > > > abstraction.  I don't think we need it, though.
> > > >
> > > > --
> > > > Eduardo
> > > >
> > > >
> >
> > --
> > Eduardo
> >
> >

-- 
Eduardo



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

* Re: [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-18 10:29 ` [RFC v3 9/9] i386: split cpu accelerators from cpu.c Claudio Fontana
@ 2020-11-18 18:28   ` Eduardo Habkost
  2020-11-19  8:53     ` Claudio Fontana
  0 siblings, 1 reply; 41+ messages in thread
From: Eduardo Habkost @ 2020-11-18 18:28 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Olaf Hering, Jason Wang, Marcelo Tosatti, qemu-devel, Peter Xu,
	Dario Faggioli, Roman Bolshakov, Cameron Esfahani, Colin Xu,
	Wenchao Wang, Anthony Perard, Paolo Bonzini, Sunil Muthuswamy,
	Bruce Rogers, Philippe Mathieu-Daudé,
	haxm-team, Richard Henderson

On Wed, Nov 18, 2020 at 11:29:36AM +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.c        KVM x86 cpu type
> hvf/cpu.c        HVF x86 cpu type
> tcg/cpu.c        TCG x86 cpu type
> 
> The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
> time, when the accelerator is known.
> 
> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> ---
[...]
> +/**
> + * X86CPUAccel:
> + * @name: string name of the X86 CPU Accelerator
> + *
> + * @common_class_init: initializer for the common cpu

So this will be called for every single CPU class.

> + * @instance_init: cpu instance initialization
> + * @realizefn: realize function, called first in x86 cpu realize
> + *
> + * X86 CPU accelerator-specific CPU initializations
> + */
> +
> +struct X86CPUAccel {
> +    const char *name;
> +
> +    void (*common_class_init)(X86CPUClass *xcc);
> +    void (*instance_init)(X86CPU *cpu);
> +    void (*realizefn)(X86CPU *cpu, Error **errp);
>  };
>  
> +void x86_cpu_accel_init(const X86CPUAccel *accel);
[...]
> +static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
> +{
> +    X86CPUClass *xcc = X86_CPU_CLASS(klass);
> +    const X86CPUAccel **accel = opaque;
> +
> +    xcc->accel = *accel;
> +    xcc->accel->common_class_init(xcc);
> +}
> +
> +void x86_cpu_accel_init(const X86CPUAccel *accel)
> +{
> +    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
> +}

This matches the documented behavior.

[...]
> +void host_cpu_class_init(X86CPUClass *xcc)
> +{
> +    xcc->host_cpuid_required = true;
> +    xcc->ordering = 8;
> +    xcc->model_description =
> +        g_strdup_printf("%s processor with all supported host features ",
> +                        xcc->accel->name);
> +}
[...]
> +static void hvf_cpu_common_class_init(X86CPUClass *xcc)
> +{
> +    host_cpu_class_init(xcc);

Why are you calling host_cpu_class_init() for all CPU types?

> +}
[...]
> +static void kvm_cpu_common_class_init(X86CPUClass *xcc)
> +{
> +    host_cpu_class_init(xcc);
> +}

Same question as above.

-- 
Eduardo



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

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

On 18/11/20 18:30, Eduardo Habkost wrote:
>> Adding a layer of indirect calls is not very different from monkey patching
>> though.
> 
> I'm a little bothered by monkey patching, but I'm more
> bothered by having to:
> 
> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
>        (4) will be saved in multiple QOM classes, so that
>          (5) we will call the right X86CPUClass.accel method at the right moment
>              (common_class_init(), instance_init(), realizefn()),
> where:
>    step 4 must be done before any CPU object is created
>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
>       will be silently ignored), and
>    step 3 must be done after all QOM types were registered.
> 
>> You also have to consider that accel currently does not exist in usermode
>> emulators, so that's an issue too. I would rather get a simple change in
>> quickly, instead of designing the perfect class hierarchy.
> 
> It doesn't have to be perfect.  I agree that simple is better.
> 
> To me, registering a QOM type and looking it up when necessary is
> simpler than the above.  Even if it's a weird class having no
> object instances.  It probably could be an interface type.

Registering a QOM type still has quite some boilerplate.  Also 
registering a QOM type has a public side effect (shows up in 
qom-list-types).  In general I don't look at QOM unless I want its 
property mechanism, but maybe that's just me.

>> Perhaps another idea would be to allow adding interfaces to classes
>> *separately from the registration of the types*. Then we can use it to add
>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
>> add the accel object to usermode emulators.
> 
> I'm not sure I follow.  What do you mean by bare bones accel
> class, and when exactly would you add the new interfaces to the
> classes?

A bare bones accel class would not have init_machine and setup_post 
methods; those would be in a TYPE_SOFTMMU_ACCEL interface.  It would 
still have properties (such as tb-size for TCG) and would be able to 
register compat properties.

Where would I add it, I don't know.  It could be a simple public wrapper 
around type_initialize_interface() if we add a new MODULE_INIT_* phase 
after QOM.

Or without adding a new phase, it could be a class_type->array of 
(interface_type, init_fn) hash table.  type_initialize would look up the 
class_type by name, add the interfaces would to the class with 
type_initialize_interface, and then call the init_fn to fill in the vtable.

Paolo



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

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

On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
> On 18/11/20 18:30, Eduardo Habkost wrote:
> > > Adding a layer of indirect calls is not very different from monkey patching
> > > though.
> > 
> > I'm a little bothered by monkey patching, but I'm more
> > bothered by having to:
> > 
> > (1) register (module_init()) a function (kvm_cpu_accel_register()) that
> >    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
> >      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
> >        (4) will be saved in multiple QOM classes, so that
> >          (5) we will call the right X86CPUClass.accel method at the right moment
> >              (common_class_init(), instance_init(), realizefn()),
> > where:
> >    step 4 must be done before any CPU object is created
> >      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
> >       will be silently ignored), and
> >    step 3 must be done after all QOM types were registered.
> > 
> > > You also have to consider that accel currently does not exist in usermode
> > > emulators, so that's an issue too. I would rather get a simple change in
> > > quickly, instead of designing the perfect class hierarchy.
> > 
> > It doesn't have to be perfect.  I agree that simple is better.
> > 
> > To me, registering a QOM type and looking it up when necessary is
> > simpler than the above.  Even if it's a weird class having no
> > object instances.  It probably could be an interface type.
> 
> Registering a QOM type still has quite some boilerplate.  [...]

We're working on that.  :)

>                                                    [...]  Also registering a
> QOM type has a public side effect (shows up in qom-list-types).  In general
> I don't look at QOM unless I want its property mechanism, but maybe that's
> just me.

We have lots of internal-use-only types returned by
qom-list-types, I don't think it's a big deal.

> 
> > > Perhaps another idea would be to allow adding interfaces to classes
> > > *separately from the registration of the types*. Then we can use it to add
> > > SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
> > > add the accel object to usermode emulators.
> > 
> > I'm not sure I follow.  What do you mean by bare bones accel
> > class, and when exactly would you add the new interfaces to the
> > classes?
> 
> A bare bones accel class would not have init_machine and setup_post methods;
> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
> properties (such as tb-size for TCG) and would be able to register compat
> properties.

Oh, I think I see.  This could save us having a lot of parallel type
hierarchies.

> 
> Where would I add it, I don't know.  It could be a simple public wrapper
> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
> QOM.
> 
> Or without adding a new phase, it could be a class_type->array of
> (interface_type, init_fn) hash table.  type_initialize would look up the
> class_type by name, add the interfaces would to the class with
> type_initialize_interface, and then call the init_fn to fill in the vtable.

That sounds nice.  I don't think Claudio's cleanup should be
blocked until this new mechanism is ready, though.

We don't really need the type representing X86CPUAccel to be a
subtype of TYPE_ACCEL or an interface implemented by
current_machine->accelerator, in the first version.  We just need
a simple way for the CPU initialization code to find the correct
X86CPUAccel struct.

While we don't have the new mechanism, it can be just a:
  object_class_by_name("%s-x86-cpu-accel" % (accel->name))
call.

Below is a rough draft of what I mean.  There's still lots of
room for cleaning it up (especially getting rid of the
X86CPUClass.common_class_init and X86CPUClass.accel fields).

git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 485eda986a..944d403cbd 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -44,7 +44,6 @@ 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,
@@ -55,7 +54,6 @@ 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/include/sysemu/cpus.h b/include/sysemu/cpus.h
index 032169ccd3..14491297bb 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -25,6 +25,9 @@ typedef struct CpuAccelOps {
 /* register accel-specific cpus interface implementation */
 void cpus_register_accel(const CpuAccelOps *i);
 
+/* Call arch-specific accel initialization */
+void cpu_accel_arch_init(const char *accel_name);
+
 /* Create a dummy vcpu for CpuAccelOps->create_vcpu_thread */
 void dummy_start_vcpu_thread(CPUState *);
 
diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
index 79fcbd3b9b..eafd86dc22 100644
--- a/target/i386/cpu-qom.h
+++ b/target/i386/cpu-qom.h
@@ -34,7 +34,7 @@ OBJECT_DECLARE_TYPE(X86CPU, X86CPUClass,
                     X86_CPU)
 
 typedef struct X86CPUModel X86CPUModel;
-typedef struct X86CPUAccel X86CPUAccel;
+typedef struct X86CPUAccelInterface X86CPUAccelInterface;
 
 /**
  * X86CPUClass:
@@ -71,13 +71,11 @@ struct X86CPUClass {
     DeviceUnrealize parent_unrealize;
     DeviceReset parent_reset;
 
-    const X86CPUAccel *accel;
+    const X86CPUAccelInterface *accel;
 };
 
 /**
- * X86CPUAccel:
- * @name: string name of the X86 CPU Accelerator
- *
+ * X86CPUAccelInterface:
  * @common_class_init: initializer for the common cpu
  * @instance_init: cpu instance initialization
  * @realizefn: realize function, called first in x86 cpu realize
@@ -85,14 +83,16 @@ struct X86CPUClass {
  * X86 CPU accelerator-specific CPU initializations
  */
 
-struct X86CPUAccel {
-    const char *name;
-
+struct X86CPUAccelInterface {
+    ObjectClass parent_class;
     void (*common_class_init)(X86CPUClass *xcc);
     void (*instance_init)(X86CPU *cpu);
     void (*realizefn)(X86CPU *cpu, Error **errp);
 };
 
-void x86_cpu_accel_init(const X86CPUAccel *accel);
+#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
+OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);
+
+#define X86_CPU_ACCEL_NAME(acc) (acc "-x86-cpu-accel")
 
 #endif
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 9f88ae952a..6107c8ca24 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -909,7 +909,8 @@ int main(int argc, char **argv)
 
     /* init tcg before creating CPUs and to get qemu_host_page_size */
     tcg_exec_init(0);
-    module_call_init(MODULE_INIT_ACCEL_CPU);
+    cpu_accel_arch_init("tcg");
+
 
     cpu_type = parse_cpu_option(cpu_model);
     cpu = cpu_create(cpu_type);
diff --git a/linux-user/main.c b/linux-user/main.c
index a745901d86..c36564fd61 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -704,7 +704,7 @@ int main(int argc, char **argv, char **envp)
 
     /* init tcg before creating CPUs and to get qemu_host_page_size */
     tcg_exec_init(0);
-    module_call_init(MODULE_INIT_ACCEL_CPU);
+    cpu_accel_arch_init("tcg");
 
     cpu = cpu_create(cpu_type);
     env = cpu->env_ptr;
diff --git a/softmmu/vl.c b/softmmu/vl.c
index df4bed056a..b90d107475 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2744,6 +2744,7 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
         return 0;
     }
 
+    cpu_accel_arch_init(acc);
     return 1;
 }
 
@@ -4173,12 +4174,6 @@ 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/stubs/cpu_accel_arch_init.c b/stubs/cpu_accel_arch_init.c
new file mode 100644
index 0000000000..b80cbdd847
--- /dev/null
+++ b/stubs/cpu_accel_arch_init.c
@@ -0,0 +1,6 @@
+#include "qemu/osdep.h"
+#include "sysemu/cpus.h"
+
+void cpu_accel_arch_init(const char *accel_name)
+{
+}
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b53e958926..b91e0b44ca 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -7041,6 +7041,12 @@ static const TypeInfo x86_base_cpu_type_info = {
         .class_init = x86_cpu_base_class_init,
 };
 
+static const TypeInfo x86_cpu_accel_type_info = {
+    .name = TYPE_X86_CPU_ACCEL,
+    .parent = TYPE_INTERFACE,
+    .class_size = sizeof(X86CPUAccelInterface),
+};
+
 static void x86_cpu_register_types(void)
 {
     int i;
@@ -7051,6 +7057,7 @@ static void x86_cpu_register_types(void)
     }
     type_register_static(&max_x86_cpu_type_info);
     type_register_static(&x86_base_cpu_type_info);
+    type_register_static(&x86_cpu_accel_type_info);
 }
 
 type_init(x86_cpu_register_types)
@@ -7058,13 +7065,22 @@ type_init(x86_cpu_register_types)
 static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(klass);
-    const X86CPUAccel **accel = opaque;
+    const X86CPUAccelInterface **accel = opaque;
 
     xcc->accel = *accel;
     xcc->accel->common_class_init(xcc);
 }
 
-void x86_cpu_accel_init(const X86CPUAccel *accel)
+static void x86_cpu_accel_init(const X86CPUAccelInterface *accel)
 {
     object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
 }
+
+void cpu_accel_arch_init(const char *accel_name)
+{
+    g_autofree char *cpu_accel_name =
+        g_strdup_printf(X86_CPU_ACCEL_NAME("%s"), accel_name);
+    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(object_class_by_name(cpu_accel_name));
+    assert(acc);
+    x86_cpu_accel_init(acc);
+}
diff --git a/target/i386/hvf/cpu.c b/target/i386/hvf/cpu.c
index 29e672191f..358351018f 100644
--- a/target/i386/hvf/cpu.c
+++ b/target/i386/hvf/cpu.c
@@ -46,19 +46,23 @@ static void hvf_cpu_instance_init(X86CPU *cpu)
     }
 }
 
-static const X86CPUAccel hvf_cpu_accel = {
-    .name = TYPE_X86_CPU "-hvf",
+static void hvf_cpu_accel_interface_init(ObjectClass *oc, void *data)
+{
+    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(oc);
+    acc->realizefn = host_cpu_realizefn;
+    acc->common_class_init = hvf_cpu_common_class_init;
+    acc->instance_init = hvf_cpu_instance_init;
+};
 
-    .realizefn = host_cpu_realizefn,
-    .common_class_init = hvf_cpu_common_class_init,
-    .instance_init = hvf_cpu_instance_init,
+static const TypeInfo hvf_cpu_accel_type_info = {
+    .name = X86_CPU_ACCEL_NAME("hvf"),
+    .parent = TYPE_X86_CPU_ACCEL,
+    .class_init = hvf_cpu_accel_interface_init,
 };
 
 static void hvf_cpu_accel_init(void)
 {
-    if (hvf_enabled()) {
-        x86_cpu_accel_init(&hvf_cpu_accel);
-    }
+    type_register_static(&hvf_cpu_accel_type_info);
 }
 
-accel_cpu_init(hvf_cpu_accel_init);
+type_init(hvf_cpu_accel_init);
diff --git a/target/i386/kvm/cpu.c b/target/i386/kvm/cpu.c
index 76982865eb..b6a1a4d200 100644
--- a/target/i386/kvm/cpu.c
+++ b/target/i386/kvm/cpu.c
@@ -128,18 +128,23 @@ static void kvm_cpu_instance_init(X86CPU *cpu)
     }
 }
 
-static const X86CPUAccel kvm_cpu_accel = {
-    .name = TYPE_X86_CPU "-kvm",
+static void kvm_cpu_accel_interface_init(ObjectClass *oc, void *data)
+{
+    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(oc);
+    acc->realizefn = kvm_cpu_realizefn;
+    acc->common_class_init = kvm_cpu_common_class_init;
+    acc->instance_init = kvm_cpu_instance_init;
+};
 
-    .realizefn = kvm_cpu_realizefn,
-    .common_class_init = kvm_cpu_common_class_init,
-    .instance_init = kvm_cpu_instance_init,
+static const TypeInfo kvm_cpu_accel_type_info = {
+    .name = X86_CPU_ACCEL_NAME("kvm"),
+    .parent = TYPE_X86_CPU_ACCEL,
+    .class_init = kvm_cpu_accel_interface_init,
 };
 
 static void kvm_cpu_accel_init(void)
 {
-    if (kvm_enabled()) {
-        x86_cpu_accel_init(&kvm_cpu_accel);
-    }
+    type_register_static(&kvm_cpu_accel_type_info);
 }
-accel_cpu_init(kvm_cpu_accel_init);
+
+type_init(kvm_cpu_accel_init);
diff --git a/target/i386/tcg/cpu.c b/target/i386/tcg/cpu.c
index 25cf4cfb46..0321688cd3 100644
--- a/target/i386/tcg/cpu.c
+++ b/target/i386/tcg/cpu.c
@@ -150,19 +150,23 @@ static void tcg_cpu_instance_init(X86CPU *cpu)
     x86_cpu_apply_props(cpu, tcg_default_props);
 }
 
-static const X86CPUAccel tcg_cpu_accel = {
-    .name = TYPE_X86_CPU "-tcg",
+static void tcg_cpu_accel_interface_init(ObjectClass *oc, void *data)
+{
+    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(oc);
+    acc->realizefn = tcg_cpu_realizefn;
+    acc->common_class_init = tcg_cpu_common_class_init;
+    acc->instance_init = tcg_cpu_instance_init;
+};
 
-    .realizefn = tcg_cpu_realizefn,
-    .common_class_init = tcg_cpu_common_class_init,
-    .instance_init = tcg_cpu_instance_init,
+static const TypeInfo tcg_cpu_accel_type_info = {
+    .name = X86_CPU_ACCEL_NAME("tcg"),
+    .parent = TYPE_X86_CPU_ACCEL,
+    .class_init = tcg_cpu_accel_interface_init,
 };
 
 static void tcg_cpu_accel_init(void)
 {
-    if (tcg_enabled()) {
-        x86_cpu_accel_init(&tcg_cpu_accel);
-    }
+    type_register_static(&tcg_cpu_accel_type_info);
 }
 
-accel_cpu_init(tcg_cpu_accel_init);
+type_init(tcg_cpu_accel_init);
diff --git a/stubs/meson.build b/stubs/meson.build
index 82b7ba60ab..1d66de1fae 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -1,4 +1,5 @@
 stub_ss.add(files('arch_type.c'))
+stub_ss.add(files('cpu_accel_arch_init.c'))
 stub_ss.add(files('bdrv-next-monitor-owned.c'))
 stub_ss.add(files('blk-commit-all.c'))
 stub_ss.add(files('blk-exp-close-all.c'))



-- 
Eduardo



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

* Re: [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-18 18:28   ` Eduardo Habkost
@ 2020-11-19  8:53     ` Claudio Fontana
  2020-11-19 19:23       ` Eduardo Habkost
  0 siblings, 1 reply; 41+ messages in thread
From: Claudio Fontana @ 2020-11-19  8:53 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Wenchao Wang,
	haxm-team, Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Olaf Hering, Colin Xu

Hi,

On 11/18/20 7:28 PM, Eduardo Habkost wrote:
> On Wed, Nov 18, 2020 at 11:29:36AM +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.c        KVM x86 cpu type
>> hvf/cpu.c        HVF x86 cpu type
>> tcg/cpu.c        TCG x86 cpu type
>>
>> The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
>> time, when the accelerator is known.
>>
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
> [...]
>> +/**
>> + * X86CPUAccel:
>> + * @name: string name of the X86 CPU Accelerator
>> + *
>> + * @common_class_init: initializer for the common cpu
> 
> So this will be called for every single CPU class.

Not really, it's called for every TYPE_X86_CPU cpu class (if an accel interface is registered).

This function extends the existing x86_cpu_common_class_init (target/i386/cpu.c),
where some methods of the base class CPUClass are set.

> 
>> + * @instance_init: cpu instance initialization
>> + * @realizefn: realize function, called first in x86 cpu realize
>> + *
>> + * X86 CPU accelerator-specific CPU initializations
>> + */
>> +
>> +struct X86CPUAccel {
>> +    const char *name;
>> +
>> +    void (*common_class_init)(X86CPUClass *xcc);
>> +    void (*instance_init)(X86CPU *cpu);
>> +    void (*realizefn)(X86CPU *cpu, Error **errp);
>>  };
>>  
>> +void x86_cpu_accel_init(const X86CPUAccel *accel);
> [...]
>> +static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
>> +{
>> +    X86CPUClass *xcc = X86_CPU_CLASS(klass);
>> +    const X86CPUAccel **accel = opaque;
>> +
>> +    xcc->accel = *accel;
>> +    xcc->accel->common_class_init(xcc);
>> +}
>> +
>> +void x86_cpu_accel_init(const X86CPUAccel *accel)
>> +{
>> +    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
>> +}
> 
> This matches the documented behavior.
> 
> [...]
>> +void host_cpu_class_init(X86CPUClass *xcc)
>> +{
>> +    xcc->host_cpuid_required = true;
>> +    xcc->ordering = 8;
>> +    xcc->model_description =
>> +        g_strdup_printf("%s processor with all supported host features ",
>> +                        xcc->accel->name);
>> +}
> [...]
>> +static void hvf_cpu_common_class_init(X86CPUClass *xcc)
>> +{
>> +    host_cpu_class_init(xcc);
> 
> Why are you calling host_cpu_class_init() for all CPU types?

I am not..

> 
>> +}
> [...]
>> +static void kvm_cpu_common_class_init(X86CPUClass *xcc)
>> +{
>> +    host_cpu_class_init(xcc);
>> +}
> 
> Same question as above.
> 

Ciao,

Claudio


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

* Re: [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-19  8:53     ` Claudio Fontana
@ 2020-11-19 19:23       ` Eduardo Habkost
  2020-11-20  9:08         ` Claudio Fontana
  0 siblings, 1 reply; 41+ messages in thread
From: Eduardo Habkost @ 2020-11-19 19:23 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Wenchao Wang,
	haxm-team, Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Olaf Hering, Colin Xu

On Thu, Nov 19, 2020 at 09:53:09AM +0100, Claudio Fontana wrote:
> Hi,
> 
> On 11/18/20 7:28 PM, Eduardo Habkost wrote:
> > On Wed, Nov 18, 2020 at 11:29:36AM +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.c        KVM x86 cpu type
> >> hvf/cpu.c        HVF x86 cpu type
> >> tcg/cpu.c        TCG x86 cpu type
> >>
> >> The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
> >> time, when the accelerator is known.
> >>
> >> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> >> ---
> > [...]
> >> +/**
> >> + * X86CPUAccel:
> >> + * @name: string name of the X86 CPU Accelerator
> >> + *
> >> + * @common_class_init: initializer for the common cpu
> > 
> > So this will be called for every single CPU class.
> 
> Not really, it's called for every TYPE_X86_CPU cpu class (if an accel interface is registered).

This means every single non-abstract CPU class in
qemu-system-x86_64, correct?

> 
> This function extends the existing x86_cpu_common_class_init (target/i386/cpu.c),
> where some methods of the base class CPUClass are set.
> 
> > 
> >> + * @instance_init: cpu instance initialization
> >> + * @realizefn: realize function, called first in x86 cpu realize
> >> + *
> >> + * X86 CPU accelerator-specific CPU initializations
> >> + */
> >> +
> >> +struct X86CPUAccel {
> >> +    const char *name;
> >> +
> >> +    void (*common_class_init)(X86CPUClass *xcc);
> >> +    void (*instance_init)(X86CPU *cpu);
> >> +    void (*realizefn)(X86CPU *cpu, Error **errp);
> >>  };
> >>  
> >> +void x86_cpu_accel_init(const X86CPUAccel *accel);
> > [...]
> >> +static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
> >> +{
> >> +    X86CPUClass *xcc = X86_CPU_CLASS(klass);
> >> +    const X86CPUAccel **accel = opaque;
> >> +
> >> +    xcc->accel = *accel;
> >> +    xcc->accel->common_class_init(xcc);
> >> +}
> >> +
> >> +void x86_cpu_accel_init(const X86CPUAccel *accel)
> >> +{
> >> +    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
> >> +}
> > 
> > This matches the documented behavior.
> > 
> > [...]
> >> +void host_cpu_class_init(X86CPUClass *xcc)
> >> +{
> >> +    xcc->host_cpuid_required = true;
> >> +    xcc->ordering = 8;
> >> +    xcc->model_description =
> >> +        g_strdup_printf("%s processor with all supported host features ",
> >> +                        xcc->accel->name);
> >> +}
> > [...]
> >> +static void hvf_cpu_common_class_init(X86CPUClass *xcc)
> >> +{
> >> +    host_cpu_class_init(xcc);
> > 
> > Why are you calling host_cpu_class_init() for all CPU types?
> 
> I am not..

I don't get it.  You are calling host_cpu_class_init() for every
single non-abstract TYPE_X86_CPU subclass (which includes all CPU
models in qemu-system-x86_64), and I don't understand why, or if
this is really intentional.

> 
> > 
> >> +}
> > [...]
> >> +static void kvm_cpu_common_class_init(X86CPUClass *xcc)
> >> +{
> >> +    host_cpu_class_init(xcc);
> >> +}
> > 
> > Same question as above.
> > 
> 
> Ciao,
> 
> Claudio
> 

-- 
Eduardo



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

* Re: [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-19 19:23       ` Eduardo Habkost
@ 2020-11-20  9:08         ` Claudio Fontana
  2020-11-23 18:24           ` Eduardo Habkost
  0 siblings, 1 reply; 41+ messages in thread
From: Claudio Fontana @ 2020-11-20  9:08 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Wenchao Wang,
	haxm-team, Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Olaf Hering, Colin Xu

On 11/19/20 8:23 PM, Eduardo Habkost wrote:
> On Thu, Nov 19, 2020 at 09:53:09AM +0100, Claudio Fontana wrote:
>> Hi,
>>
>> On 11/18/20 7:28 PM, Eduardo Habkost wrote:
>>> On Wed, Nov 18, 2020 at 11:29:36AM +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.c        KVM x86 cpu type
>>>> hvf/cpu.c        HVF x86 cpu type
>>>> tcg/cpu.c        TCG x86 cpu type
>>>>
>>>> The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
>>>> time, when the accelerator is known.
>>>>
>>>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>>>> ---
>>> [...]
>>>> +/**
>>>> + * X86CPUAccel:
>>>> + * @name: string name of the X86 CPU Accelerator
>>>> + *
>>>> + * @common_class_init: initializer for the common cpu
>>>
>>> So this will be called for every single CPU class.
>>
>> Not really, it's called for every TYPE_X86_CPU cpu class (if an accel interface is registered).
> 
> This means every single non-abstract CPU class in
> qemu-system-x86_64, correct?
> 
>>
>> This function extends the existing x86_cpu_common_class_init (target/i386/cpu.c),
>> where some methods of the base class CPUClass are set.
>>
>>>
>>>> + * @instance_init: cpu instance initialization
>>>> + * @realizefn: realize function, called first in x86 cpu realize
>>>> + *
>>>> + * X86 CPU accelerator-specific CPU initializations
>>>> + */
>>>> +
>>>> +struct X86CPUAccel {
>>>> +    const char *name;
>>>> +
>>>> +    void (*common_class_init)(X86CPUClass *xcc);
>>>> +    void (*instance_init)(X86CPU *cpu);
>>>> +    void (*realizefn)(X86CPU *cpu, Error **errp);
>>>>  };
>>>>  
>>>> +void x86_cpu_accel_init(const X86CPUAccel *accel);
>>> [...]
>>>> +static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
>>>> +{
>>>> +    X86CPUClass *xcc = X86_CPU_CLASS(klass);
>>>> +    const X86CPUAccel **accel = opaque;
>>>> +
>>>> +    xcc->accel = *accel;
>>>> +    xcc->accel->common_class_init(xcc);
>>>> +}
>>>> +
>>>> +void x86_cpu_accel_init(const X86CPUAccel *accel)
>>>> +{
>>>> +    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
>>>> +}
>>>
>>> This matches the documented behavior.
>>>
>>> [...]
>>>> +void host_cpu_class_init(X86CPUClass *xcc)
>>>> +{
>>>> +    xcc->host_cpuid_required = true;
>>>> +    xcc->ordering = 8;
>>>> +    xcc->model_description =
>>>> +        g_strdup_printf("%s processor with all supported host features ",
>>>> +                        xcc->accel->name);
>>>> +}
>>> [...]
>>>> +static void hvf_cpu_common_class_init(X86CPUClass *xcc)
>>>> +{
>>>> +    host_cpu_class_init(xcc);
>>>
>>> Why are you calling host_cpu_class_init() for all CPU types?
>>
>> I am not..
> 
> I don't get it.  You are calling host_cpu_class_init() for every
> single non-abstract TYPE_X86_CPU subclass (which includes all CPU
> models in qemu-system-x86_64), and I don't understand why, or if
> this is really intentional.

It is really intentional what is done here,

when HVF accelerator is enabled, and only when the HVF accelerator is enabled,

all X86 CPU classes and subclasses (cpu models, which have been implemented as subclasses of TYPE_X86_CPU), are updated with a link to the accelerator-specific HVF interface.


> 
>>
>>>
>>>> +}
>>> [...]
>>>> +static void kvm_cpu_common_class_init(X86CPUClass *xcc)
>>>> +{
>>>> +    host_cpu_class_init(xcc);
>>>> +}
>>>
>>> Same question as above.
>>>
>>
>> Ciao,
>>
>> Claudio
>>
> 



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

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

On 11/18/20 11:07 PM, Eduardo Habkost wrote:
> On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
>> On 18/11/20 18:30, Eduardo Habkost wrote:
>>>> Adding a layer of indirect calls is not very different from monkey patching
>>>> though.
>>>
>>> I'm a little bothered by monkey patching, but I'm more
>>> bothered by having to:
>>>
>>> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
>>>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
>>>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
>>>        (4) will be saved in multiple QOM classes, so that
>>>          (5) we will call the right X86CPUClass.accel method at the right moment
>>>              (common_class_init(), instance_init(), realizefn()),
>>> where:
>>>    step 4 must be done before any CPU object is created
>>>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
>>>       will be silently ignored), and
>>>    step 3 must be done after all QOM types were registered.
>>>
>>>> You also have to consider that accel currently does not exist in usermode
>>>> emulators, so that's an issue too. I would rather get a simple change in
>>>> quickly, instead of designing the perfect class hierarchy.
>>>
>>> It doesn't have to be perfect.  I agree that simple is better.
>>>
>>> To me, registering a QOM type and looking it up when necessary is
>>> simpler than the above.  Even if it's a weird class having no
>>> object instances.  It probably could be an interface type.
>>
>> Registering a QOM type still has quite some boilerplate.  [...]
> 
> We're working on that.  :)
> 
>>                                                    [...]  Also registering a
>> QOM type has a public side effect (shows up in qom-list-types).  In general
>> I don't look at QOM unless I want its property mechanism, but maybe that's
>> just me.
> 
> We have lots of internal-use-only types returned by
> qom-list-types, I don't think it's a big deal.
> 
>>
>>>> Perhaps another idea would be to allow adding interfaces to classes
>>>> *separately from the registration of the types*. Then we can use it to add
>>>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
>>>> add the accel object to usermode emulators.
>>>
>>> I'm not sure I follow.  What do you mean by bare bones accel
>>> class, and when exactly would you add the new interfaces to the
>>> classes?
>>
>> A bare bones accel class would not have init_machine and setup_post methods;
>> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
>> properties (such as tb-size for TCG) and would be able to register compat
>> properties.
> 
> Oh, I think I see.  This could save us having a lot of parallel type
> hierarchies.
> 
>>
>> Where would I add it, I don't know.  It could be a simple public wrapper
>> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
>> QOM.
>>
>> Or without adding a new phase, it could be a class_type->array of
>> (interface_type, init_fn) hash table.  type_initialize would look up the
>> class_type by name, add the interfaces would to the class with
>> type_initialize_interface, and then call the init_fn to fill in the vtable.
> 
> That sounds nice.  I don't think Claudio's cleanup should be
> blocked until this new mechanism is ready, though.
> 
> We don't really need the type representing X86CPUAccel to be a
> subtype of TYPE_ACCEL or an interface implemented by
> current_machine->accelerator, in the first version.  We just need
> a simple way for the CPU initialization code to find the correct
> X86CPUAccel struct.
> 
> While we don't have the new mechanism, it can be just a:
>   object_class_by_name("%s-x86-cpu-accel" % (accel->name))
> call.
> 
> Below is a rough draft of what I mean.  There's still lots of
> room for cleaning it up (especially getting rid of the
> X86CPUClass.common_class_init and X86CPUClass.accel fields).
> 
> git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> diff --git a/include/qemu/module.h b/include/qemu/module.h
> index 485eda986a..944d403cbd 100644
> --- a/include/qemu/module.h
> +++ b/include/qemu/module.h
> @@ -44,7 +44,6 @@ 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,
> @@ -55,7 +54,6 @@ 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/include/sysemu/cpus.h b/include/sysemu/cpus.h
> index 032169ccd3..14491297bb 100644
> --- a/include/sysemu/cpus.h
> +++ b/include/sysemu/cpus.h
> @@ -25,6 +25,9 @@ typedef struct CpuAccelOps {
>  /* register accel-specific cpus interface implementation */
>  void cpus_register_accel(const CpuAccelOps *i);
>  
> +/* Call arch-specific accel initialization */
> +void cpu_accel_arch_init(const char *accel_name);
> +
>  /* Create a dummy vcpu for CpuAccelOps->create_vcpu_thread */
>  void dummy_start_vcpu_thread(CPUState *);
>  
> diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
> index 79fcbd3b9b..eafd86dc22 100644
> --- a/target/i386/cpu-qom.h
> +++ b/target/i386/cpu-qom.h
> @@ -34,7 +34,7 @@ OBJECT_DECLARE_TYPE(X86CPU, X86CPUClass,
>                      X86_CPU)
>  
>  typedef struct X86CPUModel X86CPUModel;
> -typedef struct X86CPUAccel X86CPUAccel;
> +typedef struct X86CPUAccelInterface X86CPUAccelInterface;
>  
>  /**
>   * X86CPUClass:
> @@ -71,13 +71,11 @@ struct X86CPUClass {
>      DeviceUnrealize parent_unrealize;
>      DeviceReset parent_reset;
>  
> -    const X86CPUAccel *accel;
> +    const X86CPUAccelInterface *accel;
>  };
>  
>  /**
> - * X86CPUAccel:
> - * @name: string name of the X86 CPU Accelerator
> - *
> + * X86CPUAccelInterface:
>   * @common_class_init: initializer for the common cpu
>   * @instance_init: cpu instance initialization
>   * @realizefn: realize function, called first in x86 cpu realize
> @@ -85,14 +83,16 @@ struct X86CPUClass {
>   * X86 CPU accelerator-specific CPU initializations
>   */
>  
> -struct X86CPUAccel {
> -    const char *name;
> -
> +struct X86CPUAccelInterface {
> +    ObjectClass parent_class;
>      void (*common_class_init)(X86CPUClass *xcc);
>      void (*instance_init)(X86CPU *cpu);
>      void (*realizefn)(X86CPU *cpu, Error **errp);
>  };
>  
> -void x86_cpu_accel_init(const X86CPUAccel *accel);
> +#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
> +OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);


I am not exactly sure what precisely you are doing here,

I get the general intention to use the existing interface-related "stuff" in QOM,
but I do not see any OBJECT_DECLARE_INTERFACE around, and does not seem like the other boilerplate used for interfaces.

Could you clarify what happens here? Should we just use a normal object, call it "Interface" and call it a day?

Thanks,

Claudio


> +
> +#define X86_CPU_ACCEL_NAME(acc) (acc "-x86-cpu-accel")
>  
>  #endif
> diff --git a/bsd-user/main.c b/bsd-user/main.c
> index 9f88ae952a..6107c8ca24 100644
> --- a/bsd-user/main.c
> +++ b/bsd-user/main.c
> @@ -909,7 +909,8 @@ int main(int argc, char **argv)
>  
>      /* init tcg before creating CPUs and to get qemu_host_page_size */
>      tcg_exec_init(0);
> -    module_call_init(MODULE_INIT_ACCEL_CPU);
> +    cpu_accel_arch_init("tcg");
> +
>  
>      cpu_type = parse_cpu_option(cpu_model);
>      cpu = cpu_create(cpu_type);
> diff --git a/linux-user/main.c b/linux-user/main.c
> index a745901d86..c36564fd61 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -704,7 +704,7 @@ int main(int argc, char **argv, char **envp)
>  
>      /* init tcg before creating CPUs and to get qemu_host_page_size */
>      tcg_exec_init(0);
> -    module_call_init(MODULE_INIT_ACCEL_CPU);
> +    cpu_accel_arch_init("tcg");
>  
>      cpu = cpu_create(cpu_type);
>      env = cpu->env_ptr;
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index df4bed056a..b90d107475 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2744,6 +2744,7 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
>          return 0;
>      }
>  
> +    cpu_accel_arch_init(acc);
>      return 1;
>  }
>  
> @@ -4173,12 +4174,6 @@ 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/stubs/cpu_accel_arch_init.c b/stubs/cpu_accel_arch_init.c
> new file mode 100644
> index 0000000000..b80cbdd847
> --- /dev/null
> +++ b/stubs/cpu_accel_arch_init.c
> @@ -0,0 +1,6 @@
> +#include "qemu/osdep.h"
> +#include "sysemu/cpus.h"
> +
> +void cpu_accel_arch_init(const char *accel_name)
> +{
> +}
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index b53e958926..b91e0b44ca 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -7041,6 +7041,12 @@ static const TypeInfo x86_base_cpu_type_info = {
>          .class_init = x86_cpu_base_class_init,
>  };
>  
> +static const TypeInfo x86_cpu_accel_type_info = {
> +    .name = TYPE_X86_CPU_ACCEL,
> +    .parent = TYPE_INTERFACE,
> +    .class_size = sizeof(X86CPUAccelInterface),
> +};
> +
>  static void x86_cpu_register_types(void)
>  {
>      int i;
> @@ -7051,6 +7057,7 @@ static void x86_cpu_register_types(void)
>      }
>      type_register_static(&max_x86_cpu_type_info);
>      type_register_static(&x86_base_cpu_type_info);
> +    type_register_static(&x86_cpu_accel_type_info);
>  }
>  
>  type_init(x86_cpu_register_types)
> @@ -7058,13 +7065,22 @@ type_init(x86_cpu_register_types)
>  static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
>  {
>      X86CPUClass *xcc = X86_CPU_CLASS(klass);
> -    const X86CPUAccel **accel = opaque;
> +    const X86CPUAccelInterface **accel = opaque;
>  
>      xcc->accel = *accel;
>      xcc->accel->common_class_init(xcc);
>  }
>  
> -void x86_cpu_accel_init(const X86CPUAccel *accel)
> +static void x86_cpu_accel_init(const X86CPUAccelInterface *accel)
>  {
>      object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
>  }
> +
> +void cpu_accel_arch_init(const char *accel_name)
> +{
> +    g_autofree char *cpu_accel_name =
> +        g_strdup_printf(X86_CPU_ACCEL_NAME("%s"), accel_name);
> +    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(object_class_by_name(cpu_accel_name));
> +    assert(acc);
> +    x86_cpu_accel_init(acc);
> +}
> diff --git a/target/i386/hvf/cpu.c b/target/i386/hvf/cpu.c
> index 29e672191f..358351018f 100644
> --- a/target/i386/hvf/cpu.c
> +++ b/target/i386/hvf/cpu.c
> @@ -46,19 +46,23 @@ static void hvf_cpu_instance_init(X86CPU *cpu)
>      }
>  }
>  
> -static const X86CPUAccel hvf_cpu_accel = {
> -    .name = TYPE_X86_CPU "-hvf",
> +static void hvf_cpu_accel_interface_init(ObjectClass *oc, void *data)
> +{
> +    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(oc);
> +    acc->realizefn = host_cpu_realizefn;
> +    acc->common_class_init = hvf_cpu_common_class_init;
> +    acc->instance_init = hvf_cpu_instance_init;
> +};
>  
> -    .realizefn = host_cpu_realizefn,
> -    .common_class_init = hvf_cpu_common_class_init,
> -    .instance_init = hvf_cpu_instance_init,
> +static const TypeInfo hvf_cpu_accel_type_info = {
> +    .name = X86_CPU_ACCEL_NAME("hvf"),
> +    .parent = TYPE_X86_CPU_ACCEL,
> +    .class_init = hvf_cpu_accel_interface_init,
>  };
>  
>  static void hvf_cpu_accel_init(void)
>  {
> -    if (hvf_enabled()) {
> -        x86_cpu_accel_init(&hvf_cpu_accel);
> -    }
> +    type_register_static(&hvf_cpu_accel_type_info);
>  }
>  
> -accel_cpu_init(hvf_cpu_accel_init);
> +type_init(hvf_cpu_accel_init);
> diff --git a/target/i386/kvm/cpu.c b/target/i386/kvm/cpu.c
> index 76982865eb..b6a1a4d200 100644
> --- a/target/i386/kvm/cpu.c
> +++ b/target/i386/kvm/cpu.c
> @@ -128,18 +128,23 @@ static void kvm_cpu_instance_init(X86CPU *cpu)
>      }
>  }
>  
> -static const X86CPUAccel kvm_cpu_accel = {
> -    .name = TYPE_X86_CPU "-kvm",
> +static void kvm_cpu_accel_interface_init(ObjectClass *oc, void *data)
> +{
> +    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(oc);
> +    acc->realizefn = kvm_cpu_realizefn;
> +    acc->common_class_init = kvm_cpu_common_class_init;
> +    acc->instance_init = kvm_cpu_instance_init;
> +};
>  
> -    .realizefn = kvm_cpu_realizefn,
> -    .common_class_init = kvm_cpu_common_class_init,
> -    .instance_init = kvm_cpu_instance_init,
> +static const TypeInfo kvm_cpu_accel_type_info = {
> +    .name = X86_CPU_ACCEL_NAME("kvm"),
> +    .parent = TYPE_X86_CPU_ACCEL,
> +    .class_init = kvm_cpu_accel_interface_init,
>  };
>  
>  static void kvm_cpu_accel_init(void)
>  {
> -    if (kvm_enabled()) {
> -        x86_cpu_accel_init(&kvm_cpu_accel);
> -    }
> +    type_register_static(&kvm_cpu_accel_type_info);
>  }
> -accel_cpu_init(kvm_cpu_accel_init);
> +
> +type_init(kvm_cpu_accel_init);
> diff --git a/target/i386/tcg/cpu.c b/target/i386/tcg/cpu.c
> index 25cf4cfb46..0321688cd3 100644
> --- a/target/i386/tcg/cpu.c
> +++ b/target/i386/tcg/cpu.c
> @@ -150,19 +150,23 @@ static void tcg_cpu_instance_init(X86CPU *cpu)
>      x86_cpu_apply_props(cpu, tcg_default_props);
>  }
>  
> -static const X86CPUAccel tcg_cpu_accel = {
> -    .name = TYPE_X86_CPU "-tcg",
> +static void tcg_cpu_accel_interface_init(ObjectClass *oc, void *data)
> +{
> +    X86CPUAccelInterface *acc = X86_CPU_ACCEL_CLASS(oc);
> +    acc->realizefn = tcg_cpu_realizefn;
> +    acc->common_class_init = tcg_cpu_common_class_init;
> +    acc->instance_init = tcg_cpu_instance_init;
> +};
>  
> -    .realizefn = tcg_cpu_realizefn,
> -    .common_class_init = tcg_cpu_common_class_init,
> -    .instance_init = tcg_cpu_instance_init,
> +static const TypeInfo tcg_cpu_accel_type_info = {
> +    .name = X86_CPU_ACCEL_NAME("tcg"),
> +    .parent = TYPE_X86_CPU_ACCEL,
> +    .class_init = tcg_cpu_accel_interface_init,
>  };
>  
>  static void tcg_cpu_accel_init(void)
>  {
> -    if (tcg_enabled()) {
> -        x86_cpu_accel_init(&tcg_cpu_accel);
> -    }
> +    type_register_static(&tcg_cpu_accel_type_info);
>  }
>  
> -accel_cpu_init(tcg_cpu_accel_init);
> +type_init(tcg_cpu_accel_init);
> diff --git a/stubs/meson.build b/stubs/meson.build
> index 82b7ba60ab..1d66de1fae 100644
> --- a/stubs/meson.build
> +++ b/stubs/meson.build
> @@ -1,4 +1,5 @@
>  stub_ss.add(files('arch_type.c'))
> +stub_ss.add(files('cpu_accel_arch_init.c'))
>  stub_ss.add(files('bdrv-next-monitor-owned.c'))
>  stub_ss.add(files('blk-commit-all.c'))
>  stub_ss.add(files('blk-exp-close-all.c'))
> 
> 
> 



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

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

On Fri, Nov 20, 2020 at 01:13:33PM +0100, Claudio Fontana wrote:
> On 11/18/20 11:07 PM, Eduardo Habkost wrote:
> > On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
> >> On 18/11/20 18:30, Eduardo Habkost wrote:
> >>>> Adding a layer of indirect calls is not very different from monkey patching
> >>>> though.
> >>>
> >>> I'm a little bothered by monkey patching, but I'm more
> >>> bothered by having to:
> >>>
> >>> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
> >>>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
> >>>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
> >>>        (4) will be saved in multiple QOM classes, so that
> >>>          (5) we will call the right X86CPUClass.accel method at the right moment
> >>>              (common_class_init(), instance_init(), realizefn()),
> >>> where:
> >>>    step 4 must be done before any CPU object is created
> >>>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
> >>>       will be silently ignored), and
> >>>    step 3 must be done after all QOM types were registered.
> >>>
> >>>> You also have to consider that accel currently does not exist in usermode
> >>>> emulators, so that's an issue too. I would rather get a simple change in
> >>>> quickly, instead of designing the perfect class hierarchy.
> >>>
> >>> It doesn't have to be perfect.  I agree that simple is better.
> >>>
> >>> To me, registering a QOM type and looking it up when necessary is
> >>> simpler than the above.  Even if it's a weird class having no
> >>> object instances.  It probably could be an interface type.
> >>
> >> Registering a QOM type still has quite some boilerplate.  [...]
> > 
> > We're working on that.  :)
> > 
> >>                                                    [...]  Also registering a
> >> QOM type has a public side effect (shows up in qom-list-types).  In general
> >> I don't look at QOM unless I want its property mechanism, but maybe that's
> >> just me.
> > 
> > We have lots of internal-use-only types returned by
> > qom-list-types, I don't think it's a big deal.
> > 
> >>
> >>>> Perhaps another idea would be to allow adding interfaces to classes
> >>>> *separately from the registration of the types*. Then we can use it to add
> >>>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
> >>>> add the accel object to usermode emulators.
> >>>
> >>> I'm not sure I follow.  What do you mean by bare bones accel
> >>> class, and when exactly would you add the new interfaces to the
> >>> classes?
> >>
> >> A bare bones accel class would not have init_machine and setup_post methods;
> >> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
> >> properties (such as tb-size for TCG) and would be able to register compat
> >> properties.

[1]

> > 
> > Oh, I think I see.  This could save us having a lot of parallel type
> > hierarchies.
> > 
> >>
> >> Where would I add it, I don't know.  It could be a simple public wrapper
> >> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
> >> QOM.
> >>
> >> Or without adding a new phase, it could be a class_type->array of
> >> (interface_type, init_fn) hash table.  type_initialize would look up the
> >> class_type by name, add the interfaces would to the class with
> >> type_initialize_interface, and then call the init_fn to fill in the vtable.
> > 
> > That sounds nice.  I don't think Claudio's cleanup should be
> > blocked until this new mechanism is ready, though.
> > 
> > We don't really need the type representing X86CPUAccel to be a
> > subtype of TYPE_ACCEL or an interface implemented by
> > current_machine->accelerator, in the first version.  We just need
> > a simple way for the CPU initialization code to find the correct
> > X86CPUAccel struct.
> > 
> > While we don't have the new mechanism, it can be just a:
> >   object_class_by_name("%s-x86-cpu-accel" % (accel->name))
> > call.
> > 
> > Below is a rough draft of what I mean.  There's still lots of
> > room for cleaning it up (especially getting rid of the
> > X86CPUClass.common_class_init and X86CPUClass.accel fields).
> > 
> > git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
> > 
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
[...]
> >  /**
> > - * X86CPUAccel:
> > - * @name: string name of the X86 CPU Accelerator
> > - *
> > + * X86CPUAccelInterface:
> >   * @common_class_init: initializer for the common cpu
> >   * @instance_init: cpu instance initialization
> >   * @realizefn: realize function, called first in x86 cpu realize
> > @@ -85,14 +83,16 @@ struct X86CPUClass {
> >   * X86 CPU accelerator-specific CPU initializations
> >   */
> >  
> > -struct X86CPUAccel {
> > -    const char *name;
> > -
> > +struct X86CPUAccelInterface {
> > +    ObjectClass parent_class;
> >      void (*common_class_init)(X86CPUClass *xcc);
> >      void (*instance_init)(X86CPU *cpu);
> >      void (*realizefn)(X86CPU *cpu, Error **errp);
> >  };
> >  
> > -void x86_cpu_accel_init(const X86CPUAccel *accel);
> > +#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
> > +OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);
> 
> 
> I am not exactly sure what precisely you are doing here,
> 
> I get the general intention to use the existing interface-related "stuff" in QOM,
> but I do not see any OBJECT_DECLARE_INTERFACE around, and does not seem like the other boilerplate used for interfaces.

See the git URL I sent above, for other related changes:

  https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel

> 
> Could you clarify what happens here? Should we just use a normal object, call it "Interface" and call it a day?

An interface is declared in a very similar way, but instance_size
and the instance type cast macro is a bit different (because
instances of interface types are never created directly).

For the draft we have here, it shouldn't make any difference if
you use OBJECT_DECLARE_TYPE, because the instance type cast
macros are left unused.

Normally the use case for interfaces is not like what I did here.
Interfaces are usually attached to other classes (to declare that
object instances of that class implement the methods of that
interface).  Using interfaces would be just an intermediate step
to the solution Paolo was mentioning (dynamically adding
interface to classes, see [1] above).

-- 
Eduardo



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

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

On 11/20/20 6:19 PM, Eduardo Habkost wrote:
> On Fri, Nov 20, 2020 at 01:13:33PM +0100, Claudio Fontana wrote:
>> On 11/18/20 11:07 PM, Eduardo Habkost wrote:
>>> On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
>>>> On 18/11/20 18:30, Eduardo Habkost wrote:
>>>>>> Adding a layer of indirect calls is not very different from monkey patching
>>>>>> though.
>>>>>
>>>>> I'm a little bothered by monkey patching, but I'm more
>>>>> bothered by having to:
>>>>>
>>>>> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
>>>>>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
>>>>>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
>>>>>        (4) will be saved in multiple QOM classes, so that
>>>>>          (5) we will call the right X86CPUClass.accel method at the right moment
>>>>>              (common_class_init(), instance_init(), realizefn()),
>>>>> where:
>>>>>    step 4 must be done before any CPU object is created
>>>>>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
>>>>>       will be silently ignored), and
>>>>>    step 3 must be done after all QOM types were registered.
>>>>>
>>>>>> You also have to consider that accel currently does not exist in usermode
>>>>>> emulators, so that's an issue too. I would rather get a simple change in
>>>>>> quickly, instead of designing the perfect class hierarchy.
>>>>>
>>>>> It doesn't have to be perfect.  I agree that simple is better.
>>>>>
>>>>> To me, registering a QOM type and looking it up when necessary is
>>>>> simpler than the above.  Even if it's a weird class having no
>>>>> object instances.  It probably could be an interface type.
>>>>
>>>> Registering a QOM type still has quite some boilerplate.  [...]
>>>
>>> We're working on that.  :)
>>>
>>>>                                                    [...]  Also registering a
>>>> QOM type has a public side effect (shows up in qom-list-types).  In general
>>>> I don't look at QOM unless I want its property mechanism, but maybe that's
>>>> just me.
>>>
>>> We have lots of internal-use-only types returned by
>>> qom-list-types, I don't think it's a big deal.
>>>
>>>>
>>>>>> Perhaps another idea would be to allow adding interfaces to classes
>>>>>> *separately from the registration of the types*. Then we can use it to add
>>>>>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
>>>>>> add the accel object to usermode emulators.
>>>>>
>>>>> I'm not sure I follow.  What do you mean by bare bones accel
>>>>> class, and when exactly would you add the new interfaces to the
>>>>> classes?
>>>>
>>>> A bare bones accel class would not have init_machine and setup_post methods;
>>>> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
>>>> properties (such as tb-size for TCG) and would be able to register compat
>>>> properties.
> 
> [1]
> 
>>>
>>> Oh, I think I see.  This could save us having a lot of parallel type
>>> hierarchies.
>>>
>>>>
>>>> Where would I add it, I don't know.  It could be a simple public wrapper
>>>> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
>>>> QOM.
>>>>
>>>> Or without adding a new phase, it could be a class_type->array of
>>>> (interface_type, init_fn) hash table.  type_initialize would look up the
>>>> class_type by name, add the interfaces would to the class with
>>>> type_initialize_interface, and then call the init_fn to fill in the vtable.
>>>
>>> That sounds nice.  I don't think Claudio's cleanup should be
>>> blocked until this new mechanism is ready, though.
>>>
>>> We don't really need the type representing X86CPUAccel to be a
>>> subtype of TYPE_ACCEL or an interface implemented by
>>> current_machine->accelerator, in the first version.  We just need
>>> a simple way for the CPU initialization code to find the correct
>>> X86CPUAccel struct.
>>>
>>> While we don't have the new mechanism, it can be just a:
>>>   object_class_by_name("%s-x86-cpu-accel" % (accel->name))
>>> call.
>>>
>>> Below is a rough draft of what I mean.  There's still lots of
>>> room for cleaning it up (especially getting rid of the
>>> X86CPUClass.common_class_init and X86CPUClass.accel fields).
>>>
>>> git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>>
>>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> [...]
>>>  /**
>>> - * X86CPUAccel:
>>> - * @name: string name of the X86 CPU Accelerator
>>> - *
>>> + * X86CPUAccelInterface:
>>>   * @common_class_init: initializer for the common cpu
>>>   * @instance_init: cpu instance initialization
>>>   * @realizefn: realize function, called first in x86 cpu realize
>>> @@ -85,14 +83,16 @@ struct X86CPUClass {
>>>   * X86 CPU accelerator-specific CPU initializations
>>>   */
>>>  
>>> -struct X86CPUAccel {
>>> -    const char *name;
>>> -
>>> +struct X86CPUAccelInterface {
>>> +    ObjectClass parent_class;
>>>      void (*common_class_init)(X86CPUClass *xcc);
>>>      void (*instance_init)(X86CPU *cpu);
>>>      void (*realizefn)(X86CPU *cpu, Error **errp);
>>>  };
>>>  
>>> -void x86_cpu_accel_init(const X86CPUAccel *accel);
>>> +#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
>>> +OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);
>>
>>
>> I am not exactly sure what precisely you are doing here,
>>
>> I get the general intention to use the existing interface-related "stuff" in QOM,
>> but I do not see any OBJECT_DECLARE_INTERFACE around, and does not seem like the other boilerplate used for interfaces.
> 
> See the git URL I sent above, for other related changes:
> 
>   https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel


Aaah I missed this, there are quite a few more changes there;

for me it's great if you take it from there, I see you are developing a solution on top of the previous series.


> 
>>
>> Could you clarify what happens here? Should we just use a normal object, call it "Interface" and call it a day?
> 
> An interface is declared in a very similar way, but instance_size
> and the instance type cast macro is a bit different (because
> instances of interface types are never created directly).
> 
> For the draft we have here, it shouldn't make any difference if
> you use OBJECT_DECLARE_TYPE, because the instance type cast
> macros are left unused.
> 
> Normally the use case for interfaces is not like what I did here.
> Interfaces are usually attached to other classes (to declare that
> object instances of that class implement the methods of that
> interface).  Using interfaces would be just an intermediate step
> to the solution Paolo was mentioning (dynamically adding
> interface to classes, see [1] above).
> 

Makes sense to me,
let me know how you guys would like to proceed from here.

The thing I am still uncertain about, looking at your tree at:

https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel

is the removal of MODULE_INIT_ACCEL_CPU, it would be way simpler to understand I think,
both for CpuAccelOps and X86CPUAccel, and is actualy in my view a perfect fit for
the problem that module_call_init is supposed to solve.

But, my 2c of course,

Ciao,

Claudio









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

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

On Fri, Nov 20, 2020 at 06:41:35PM +0100, Claudio Fontana wrote:
> On 11/20/20 6:19 PM, Eduardo Habkost wrote:
> > On Fri, Nov 20, 2020 at 01:13:33PM +0100, Claudio Fontana wrote:
> >> On 11/18/20 11:07 PM, Eduardo Habkost wrote:
> >>> On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
> >>>> On 18/11/20 18:30, Eduardo Habkost wrote:
> >>>>>> Adding a layer of indirect calls is not very different from monkey patching
> >>>>>> though.
> >>>>>
> >>>>> I'm a little bothered by monkey patching, but I'm more
> >>>>> bothered by having to:
> >>>>>
> >>>>> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
> >>>>>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
> >>>>>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
> >>>>>        (4) will be saved in multiple QOM classes, so that
> >>>>>          (5) we will call the right X86CPUClass.accel method at the right moment
> >>>>>              (common_class_init(), instance_init(), realizefn()),
> >>>>> where:
> >>>>>    step 4 must be done before any CPU object is created
> >>>>>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
> >>>>>       will be silently ignored), and
> >>>>>    step 3 must be done after all QOM types were registered.
> >>>>>
> >>>>>> You also have to consider that accel currently does not exist in usermode
> >>>>>> emulators, so that's an issue too. I would rather get a simple change in
> >>>>>> quickly, instead of designing the perfect class hierarchy.
> >>>>>
> >>>>> It doesn't have to be perfect.  I agree that simple is better.
> >>>>>
> >>>>> To me, registering a QOM type and looking it up when necessary is
> >>>>> simpler than the above.  Even if it's a weird class having no
> >>>>> object instances.  It probably could be an interface type.
> >>>>
> >>>> Registering a QOM type still has quite some boilerplate.  [...]
> >>>
> >>> We're working on that.  :)
> >>>
> >>>>                                                    [...]  Also registering a
> >>>> QOM type has a public side effect (shows up in qom-list-types).  In general
> >>>> I don't look at QOM unless I want its property mechanism, but maybe that's
> >>>> just me.
> >>>
> >>> We have lots of internal-use-only types returned by
> >>> qom-list-types, I don't think it's a big deal.
> >>>
> >>>>
> >>>>>> Perhaps another idea would be to allow adding interfaces to classes
> >>>>>> *separately from the registration of the types*. Then we can use it to add
> >>>>>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
> >>>>>> add the accel object to usermode emulators.
> >>>>>
> >>>>> I'm not sure I follow.  What do you mean by bare bones accel
> >>>>> class, and when exactly would you add the new interfaces to the
> >>>>> classes?
> >>>>
> >>>> A bare bones accel class would not have init_machine and setup_post methods;
> >>>> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
> >>>> properties (such as tb-size for TCG) and would be able to register compat
> >>>> properties.
> > 
> > [1]
> > 
> >>>
> >>> Oh, I think I see.  This could save us having a lot of parallel type
> >>> hierarchies.
> >>>
> >>>>
> >>>> Where would I add it, I don't know.  It could be a simple public wrapper
> >>>> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
> >>>> QOM.
> >>>>
> >>>> Or without adding a new phase, it could be a class_type->array of
> >>>> (interface_type, init_fn) hash table.  type_initialize would look up the
> >>>> class_type by name, add the interfaces would to the class with
> >>>> type_initialize_interface, and then call the init_fn to fill in the vtable.
> >>>
> >>> That sounds nice.  I don't think Claudio's cleanup should be
> >>> blocked until this new mechanism is ready, though.
> >>>
> >>> We don't really need the type representing X86CPUAccel to be a
> >>> subtype of TYPE_ACCEL or an interface implemented by
> >>> current_machine->accelerator, in the first version.  We just need
> >>> a simple way for the CPU initialization code to find the correct
> >>> X86CPUAccel struct.
> >>>
> >>> While we don't have the new mechanism, it can be just a:
> >>>   object_class_by_name("%s-x86-cpu-accel" % (accel->name))
> >>> call.
> >>>
> >>> Below is a rough draft of what I mean.  There's still lots of
> >>> room for cleaning it up (especially getting rid of the
> >>> X86CPUClass.common_class_init and X86CPUClass.accel fields).
> >>>
> >>> git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
> >>>
> >>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > [...]
> >>>  /**
> >>> - * X86CPUAccel:
> >>> - * @name: string name of the X86 CPU Accelerator
> >>> - *
> >>> + * X86CPUAccelInterface:
> >>>   * @common_class_init: initializer for the common cpu
> >>>   * @instance_init: cpu instance initialization
> >>>   * @realizefn: realize function, called first in x86 cpu realize
> >>> @@ -85,14 +83,16 @@ struct X86CPUClass {
> >>>   * X86 CPU accelerator-specific CPU initializations
> >>>   */
> >>>  
> >>> -struct X86CPUAccel {
> >>> -    const char *name;
> >>> -
> >>> +struct X86CPUAccelInterface {
> >>> +    ObjectClass parent_class;
> >>>      void (*common_class_init)(X86CPUClass *xcc);
> >>>      void (*instance_init)(X86CPU *cpu);
> >>>      void (*realizefn)(X86CPU *cpu, Error **errp);
> >>>  };
> >>>  
> >>> -void x86_cpu_accel_init(const X86CPUAccel *accel);
> >>> +#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
> >>> +OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);
> >>
> >>
> >> I am not exactly sure what precisely you are doing here,
> >>
> >> I get the general intention to use the existing interface-related "stuff" in QOM,
> >> but I do not see any OBJECT_DECLARE_INTERFACE around, and does not seem like the other boilerplate used for interfaces.
> > 
> > See the git URL I sent above, for other related changes:
> > 
> >   https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
> 
> 
> Aaah I missed this, there are quite a few more changes there;
> 
> for me it's great if you take it from there, I see you are
> developing a solution on top of the previous series.

I'm a bit busy with other stuff, so I'm probably not going to be
able to make sure the patches are in a good shape to be submitted
soon.

I don't want to impose any obstacles for the work you are doing,
either.  Please consider the patch I sent (and the git tree
above) as just an example of a possible solution to the two issues
Paolo raised at https://lore.kernel.org/qemu-devel/8f829e99-c346-00bc-efdd-3e6d69cfba35@redhat.com

> 
> 
> > 
> >>
> >> Could you clarify what happens here? Should we just use a normal object, call it "Interface" and call it a day?
> > 
> > An interface is declared in a very similar way, but instance_size
> > and the instance type cast macro is a bit different (because
> > instances of interface types are never created directly).
> > 
> > For the draft we have here, it shouldn't make any difference if
> > you use OBJECT_DECLARE_TYPE, because the instance type cast
> > macros are left unused.
> > 
> > Normally the use case for interfaces is not like what I did here.
> > Interfaces are usually attached to other classes (to declare that
> > object instances of that class implement the methods of that
> > interface).  Using interfaces would be just an intermediate step
> > to the solution Paolo was mentioning (dynamically adding
> > interface to classes, see [1] above).
> > 
> 
> Makes sense to me,
> let me know how you guys would like to proceed from here.
> 

To me, the main issue (also raised by Paolo above) is the fact
that you are doing *_enabled() checks in the module init
functions.  Every single use case we have for module init
functions today is for unconditionally registering code or data
structures provided by a code module (config group names, QOM
types, block backends, multifd methods, etc.), and none of them
depend on runtime options (like machine or accelerator options).

The x86_cpu_accel_init() calls, on the other hand, are not module
initialization, but just one additional step of
machine/accelerator/cpu initialization.


> The thing I am still uncertain about, looking at your tree at:
> 
> https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
> 
> is the removal of MODULE_INIT_ACCEL_CPU, it would be way simpler to understand I think,
> both for CpuAccelOps and X86CPUAccel, and is actualy in my view a perfect fit for
> the problem that module_call_init is supposed to solve.

That was one of my goals.  My first goal was the removal of the
(hvm|kvm|tcg)_enabled() checks in the accel init functions.  My
secondary goal (and a side effect of the first goal) was making
MODULE_INIT_ACCEL_CPU unnecessary.

If we are not trying to remove the *_enabled() checks in the
accel init functions (nor trying to make MODULE_INIT_ACCEL_CPU
unnecessary), my suggestion of using QOM doesn't make things
simpler.

Let's hear what Paolo thinks.

If you want to proceed with the accel_register_call() solution
suggested by Paolo, that's OK to me.  I just don't think we
really need it, because QOM already solves the problem for us.

-- 
Eduardo



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

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

On 11/20/20 7:09 PM, Eduardo Habkost wrote:
> On Fri, Nov 20, 2020 at 06:41:35PM +0100, Claudio Fontana wrote:
>> On 11/20/20 6:19 PM, Eduardo Habkost wrote:
>>> On Fri, Nov 20, 2020 at 01:13:33PM +0100, Claudio Fontana wrote:
>>>> On 11/18/20 11:07 PM, Eduardo Habkost wrote:
>>>>> On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
>>>>>> On 18/11/20 18:30, Eduardo Habkost wrote:
>>>>>>>> Adding a layer of indirect calls is not very different from monkey patching
>>>>>>>> though.
>>>>>>>
>>>>>>> I'm a little bothered by monkey patching, but I'm more
>>>>>>> bothered by having to:
>>>>>>>
>>>>>>> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
>>>>>>>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
>>>>>>>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
>>>>>>>        (4) will be saved in multiple QOM classes, so that
>>>>>>>          (5) we will call the right X86CPUClass.accel method at the right moment
>>>>>>>              (common_class_init(), instance_init(), realizefn()),
>>>>>>> where:
>>>>>>>    step 4 must be done before any CPU object is created
>>>>>>>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
>>>>>>>       will be silently ignored), and
>>>>>>>    step 3 must be done after all QOM types were registered.
>>>>>>>
>>>>>>>> You also have to consider that accel currently does not exist in usermode
>>>>>>>> emulators, so that's an issue too. I would rather get a simple change in
>>>>>>>> quickly, instead of designing the perfect class hierarchy.
>>>>>>>
>>>>>>> It doesn't have to be perfect.  I agree that simple is better.
>>>>>>>
>>>>>>> To me, registering a QOM type and looking it up when necessary is
>>>>>>> simpler than the above.  Even if it's a weird class having no
>>>>>>> object instances.  It probably could be an interface type.
>>>>>>
>>>>>> Registering a QOM type still has quite some boilerplate.  [...]
>>>>>
>>>>> We're working on that.  :)
>>>>>
>>>>>>                                                    [...]  Also registering a
>>>>>> QOM type has a public side effect (shows up in qom-list-types).  In general
>>>>>> I don't look at QOM unless I want its property mechanism, but maybe that's
>>>>>> just me.
>>>>>
>>>>> We have lots of internal-use-only types returned by
>>>>> qom-list-types, I don't think it's a big deal.
>>>>>
>>>>>>
>>>>>>>> Perhaps another idea would be to allow adding interfaces to classes
>>>>>>>> *separately from the registration of the types*. Then we can use it to add
>>>>>>>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
>>>>>>>> add the accel object to usermode emulators.
>>>>>>>
>>>>>>> I'm not sure I follow.  What do you mean by bare bones accel
>>>>>>> class, and when exactly would you add the new interfaces to the
>>>>>>> classes?
>>>>>>
>>>>>> A bare bones accel class would not have init_machine and setup_post methods;
>>>>>> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
>>>>>> properties (such as tb-size for TCG) and would be able to register compat
>>>>>> properties.
>>>
>>> [1]
>>>
>>>>>
>>>>> Oh, I think I see.  This could save us having a lot of parallel type
>>>>> hierarchies.
>>>>>
>>>>>>
>>>>>> Where would I add it, I don't know.  It could be a simple public wrapper
>>>>>> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
>>>>>> QOM.
>>>>>>
>>>>>> Or without adding a new phase, it could be a class_type->array of
>>>>>> (interface_type, init_fn) hash table.  type_initialize would look up the
>>>>>> class_type by name, add the interfaces would to the class with
>>>>>> type_initialize_interface, and then call the init_fn to fill in the vtable.
>>>>>
>>>>> That sounds nice.  I don't think Claudio's cleanup should be
>>>>> blocked until this new mechanism is ready, though.
>>>>>
>>>>> We don't really need the type representing X86CPUAccel to be a
>>>>> subtype of TYPE_ACCEL or an interface implemented by
>>>>> current_machine->accelerator, in the first version.  We just need
>>>>> a simple way for the CPU initialization code to find the correct
>>>>> X86CPUAccel struct.
>>>>>
>>>>> While we don't have the new mechanism, it can be just a:
>>>>>   object_class_by_name("%s-x86-cpu-accel" % (accel->name))
>>>>> call.
>>>>>
>>>>> Below is a rough draft of what I mean.  There's still lots of
>>>>> room for cleaning it up (especially getting rid of the
>>>>> X86CPUClass.common_class_init and X86CPUClass.accel fields).
>>>>>
>>>>> git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>>>>
>>>>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
>>> [...]
>>>>>  /**
>>>>> - * X86CPUAccel:
>>>>> - * @name: string name of the X86 CPU Accelerator
>>>>> - *
>>>>> + * X86CPUAccelInterface:
>>>>>   * @common_class_init: initializer for the common cpu
>>>>>   * @instance_init: cpu instance initialization
>>>>>   * @realizefn: realize function, called first in x86 cpu realize
>>>>> @@ -85,14 +83,16 @@ struct X86CPUClass {
>>>>>   * X86 CPU accelerator-specific CPU initializations
>>>>>   */
>>>>>  
>>>>> -struct X86CPUAccel {
>>>>> -    const char *name;
>>>>> -
>>>>> +struct X86CPUAccelInterface {
>>>>> +    ObjectClass parent_class;
>>>>>      void (*common_class_init)(X86CPUClass *xcc);
>>>>>      void (*instance_init)(X86CPU *cpu);
>>>>>      void (*realizefn)(X86CPU *cpu, Error **errp);
>>>>>  };
>>>>>  
>>>>> -void x86_cpu_accel_init(const X86CPUAccel *accel);
>>>>> +#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
>>>>> +OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);
>>>>
>>>>
>>>> I am not exactly sure what precisely you are doing here,
>>>>
>>>> I get the general intention to use the existing interface-related "stuff" in QOM,
>>>> but I do not see any OBJECT_DECLARE_INTERFACE around, and does not seem like the other boilerplate used for interfaces.
>>>
>>> See the git URL I sent above, for other related changes:
>>>
>>>   https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>
>>
>> Aaah I missed this, there are quite a few more changes there;
>>
>> for me it's great if you take it from there, I see you are
>> developing a solution on top of the previous series.
> 
> I'm a bit busy with other stuff, so I'm probably not going to be
> able to make sure the patches are in a good shape to be submitted
> soon.
> 
> I don't want to impose any obstacles for the work you are doing,
> either.  Please consider the patch I sent (and the git tree
> above) as just an example of a possible solution to the two issues
> Paolo raised at https://lore.kernel.org/qemu-devel/8f829e99-c346-00bc-efdd-3e6d69cfba35@redhat.com


Ok, thanks for the clarification,
will take those two issues up in my next attempt.


> 
>>
>>
>>>
>>>>
>>>> Could you clarify what happens here? Should we just use a normal object, call it "Interface" and call it a day?
>>>
>>> An interface is declared in a very similar way, but instance_size
>>> and the instance type cast macro is a bit different (because
>>> instances of interface types are never created directly).
>>>
>>> For the draft we have here, it shouldn't make any difference if
>>> you use OBJECT_DECLARE_TYPE, because the instance type cast
>>> macros are left unused.
>>>
>>> Normally the use case for interfaces is not like what I did here.
>>> Interfaces are usually attached to other classes (to declare that
>>> object instances of that class implement the methods of that
>>> interface).  Using interfaces would be just an intermediate step
>>> to the solution Paolo was mentioning (dynamically adding
>>> interface to classes, see [1] above).
>>>
>>
>> Makes sense to me,
>> let me know how you guys would like to proceed from here.
>>
> 
> To me, the main issue (also raised by Paolo above) is the fact
> that you are doing *_enabled() checks in the module init
> functions.  Every single use case we have for module init
> functions today is for unconditionally registering code or data
> structures provided by a code module (config group names, QOM
> types, block backends, multifd methods, etc.), and none of them
> depend on runtime options (like machine or accelerator options).


Ok, no _enabled() checks, got it.

Just to note, since _enabled() has multiple meanings depending on configuration (CONFIG_KVM),
the _enabled() used in kvm/cpu.c has actually the meaning of:

if (accelerator_finally_chosen == KVM).

But we can refactor this implicit check out, and make it instead a

accel_cpu_init("kvm"), like you suggest, so that the ifs disappear.



> 
> The x86_cpu_accel_init() calls, on the other hand, are not module
> initialization, but just one additional step of
> machine/accelerator/cpu initialization.
> 
> 
>> The thing I am still uncertain about, looking at your tree at:
>>
>> https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>
>> is the removal of MODULE_INIT_ACCEL_CPU, it would be way simpler to understand I think,
>> both for CpuAccelOps and X86CPUAccel, and is actualy in my view a perfect fit for
>> the problem that module_call_init is supposed to solve.
> 
> That was one of my goals.  My first goal was the removal of the
> (hvm|kvm|tcg)_enabled() checks in the accel init functions.  My
> secondary goal (and a side effect of the first goal) was making
> MODULE_INIT_ACCEL_CPU unnecessary.
> 
> If we are not trying to remove the *_enabled() checks in the
> accel init functions (nor trying to make MODULE_INIT_ACCEL_CPU
> unnecessary), my suggestion of using QOM doesn't make things
> simpler.
> 
> Let's hear what Paolo thinks.
> 
> If you want to proceed with the accel_register_call() solution
> suggested by Paolo, that's OK to me.  I just don't think we
> really need it, because QOM already solves the problem for us.
> 

Ok, thanks for all the input, will need some time to process,

thanks,

Claudio


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

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

On 11/23/20 10:29 AM, Claudio Fontana wrote:
> On 11/20/20 7:09 PM, Eduardo Habkost wrote:
>> On Fri, Nov 20, 2020 at 06:41:35PM +0100, Claudio Fontana wrote:
>>> On 11/20/20 6:19 PM, Eduardo Habkost wrote:
>>>> On Fri, Nov 20, 2020 at 01:13:33PM +0100, Claudio Fontana wrote:
>>>>> On 11/18/20 11:07 PM, Eduardo Habkost wrote:
>>>>>> On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote:
>>>>>>> On 18/11/20 18:30, Eduardo Habkost wrote:
>>>>>>>>> Adding a layer of indirect calls is not very different from monkey patching
>>>>>>>>> though.
>>>>>>>>
>>>>>>>> I'm a little bothered by monkey patching, but I'm more
>>>>>>>> bothered by having to:
>>>>>>>>
>>>>>>>> (1) register (module_init()) a function (kvm_cpu_accel_register()) that
>>>>>>>>    (2) register (accel_register_call()) a function (kvm_cpu_accel_init()) that
>>>>>>>>      (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel kvm_cpu_accel) that
>>>>>>>>        (4) will be saved in multiple QOM classes, so that
>>>>>>>>          (5) we will call the right X86CPUClass.accel method at the right moment
>>>>>>>>              (common_class_init(), instance_init(), realizefn()),
>>>>>>>> where:
>>>>>>>>    step 4 must be done before any CPU object is created
>>>>>>>>      (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn
>>>>>>>>       will be silently ignored), and
>>>>>>>>    step 3 must be done after all QOM types were registered.
>>>>>>>>
>>>>>>>>> You also have to consider that accel currently does not exist in usermode
>>>>>>>>> emulators, so that's an issue too. I would rather get a simple change in
>>>>>>>>> quickly, instead of designing the perfect class hierarchy.
>>>>>>>>
>>>>>>>> It doesn't have to be perfect.  I agree that simple is better.
>>>>>>>>
>>>>>>>> To me, registering a QOM type and looking it up when necessary is
>>>>>>>> simpler than the above.  Even if it's a weird class having no
>>>>>>>> object instances.  It probably could be an interface type.
>>>>>>>
>>>>>>> Registering a QOM type still has quite some boilerplate.  [...]
>>>>>>
>>>>>> We're working on that.  :)
>>>>>>
>>>>>>>                                                    [...]  Also registering a
>>>>>>> QOM type has a public side effect (shows up in qom-list-types).  In general
>>>>>>> I don't look at QOM unless I want its property mechanism, but maybe that's
>>>>>>> just me.
>>>>>>
>>>>>> We have lots of internal-use-only types returned by
>>>>>> qom-list-types, I don't think it's a big deal.
>>>>>>
>>>>>>>
>>>>>>>>> Perhaps another idea would be to allow adding interfaces to classes
>>>>>>>>> *separately from the registration of the types*. Then we can use it to add
>>>>>>>>> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, and
>>>>>>>>> add the accel object to usermode emulators.
>>>>>>>>
>>>>>>>> I'm not sure I follow.  What do you mean by bare bones accel
>>>>>>>> class, and when exactly would you add the new interfaces to the
>>>>>>>> classes?
>>>>>>>
>>>>>>> A bare bones accel class would not have init_machine and setup_post methods;
>>>>>>> those would be in a TYPE_SOFTMMU_ACCEL interface.  It would still have
>>>>>>> properties (such as tb-size for TCG) and would be able to register compat
>>>>>>> properties.
>>>>
>>>> [1]
>>>>
>>>>>>
>>>>>> Oh, I think I see.  This could save us having a lot of parallel type
>>>>>> hierarchies.
>>>>>>
>>>>>>>
>>>>>>> Where would I add it, I don't know.  It could be a simple public wrapper
>>>>>>> around type_initialize_interface() if we add a new MODULE_INIT_* phase after
>>>>>>> QOM.
>>>>>>>
>>>>>>> Or without adding a new phase, it could be a class_type->array of
>>>>>>> (interface_type, init_fn) hash table.  type_initialize would look up the
>>>>>>> class_type by name, add the interfaces would to the class with
>>>>>>> type_initialize_interface, and then call the init_fn to fill in the vtable.
>>>>>>
>>>>>> That sounds nice.  I don't think Claudio's cleanup should be
>>>>>> blocked until this new mechanism is ready, though.
>>>>>>
>>>>>> We don't really need the type representing X86CPUAccel to be a
>>>>>> subtype of TYPE_ACCEL or an interface implemented by
>>>>>> current_machine->accelerator, in the first version.  We just need
>>>>>> a simple way for the CPU initialization code to find the correct
>>>>>> X86CPUAccel struct.
>>>>>>
>>>>>> While we don't have the new mechanism, it can be just a:
>>>>>>   object_class_by_name("%s-x86-cpu-accel" % (accel->name))
>>>>>> call.
>>>>>>
>>>>>> Below is a rough draft of what I mean.  There's still lots of
>>>>>> room for cleaning it up (especially getting rid of the
>>>>>> X86CPUClass.common_class_init and X86CPUClass.accel fields).
>>>>>>
>>>>>> git tree at https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>>>>>
>>>>>> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
>>>> [...]
>>>>>>  /**
>>>>>> - * X86CPUAccel:
>>>>>> - * @name: string name of the X86 CPU Accelerator
>>>>>> - *
>>>>>> + * X86CPUAccelInterface:
>>>>>>   * @common_class_init: initializer for the common cpu
>>>>>>   * @instance_init: cpu instance initialization
>>>>>>   * @realizefn: realize function, called first in x86 cpu realize
>>>>>> @@ -85,14 +83,16 @@ struct X86CPUClass {
>>>>>>   * X86 CPU accelerator-specific CPU initializations
>>>>>>   */
>>>>>>  
>>>>>> -struct X86CPUAccel {
>>>>>> -    const char *name;
>>>>>> -
>>>>>> +struct X86CPUAccelInterface {
>>>>>> +    ObjectClass parent_class;
>>>>>>      void (*common_class_init)(X86CPUClass *xcc);
>>>>>>      void (*instance_init)(X86CPU *cpu);
>>>>>>      void (*realizefn)(X86CPU *cpu, Error **errp);
>>>>>>  };
>>>>>>  
>>>>>> -void x86_cpu_accel_init(const X86CPUAccel *accel);
>>>>>> +#define TYPE_X86_CPU_ACCEL "x86-cpu-accel"
>>>>>> +OBJECT_DECLARE_INTERFACE(X86CPUAccel, X86CPUAccelInterface, X86_CPU_ACCEL);
>>>>>
>>>>>
>>>>> I am not exactly sure what precisely you are doing here,
>>>>>
>>>>> I get the general intention to use the existing interface-related "stuff" in QOM,
>>>>> but I do not see any OBJECT_DECLARE_INTERFACE around, and does not seem like the other boilerplate used for interfaces.
>>>>
>>>> See the git URL I sent above, for other related changes:
>>>>
>>>>   https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>>
>>>
>>> Aaah I missed this, there are quite a few more changes there;
>>>
>>> for me it's great if you take it from there, I see you are
>>> developing a solution on top of the previous series.
>>
>> I'm a bit busy with other stuff, so I'm probably not going to be
>> able to make sure the patches are in a good shape to be submitted
>> soon.
>>
>> I don't want to impose any obstacles for the work you are doing,
>> either.  Please consider the patch I sent (and the git tree
>> above) as just an example of a possible solution to the two issues
>> Paolo raised at https://lore.kernel.org/qemu-devel/8f829e99-c346-00bc-efdd-3e6d69cfba35@redhat.com
> 
> 
> Ok, thanks for the clarification,
> will take those two issues up in my next attempt.
> 
> 
>>
>>>
>>>
>>>>
>>>>>
>>>>> Could you clarify what happens here? Should we just use a normal object, call it "Interface" and call it a day?
>>>>
>>>> An interface is declared in a very similar way, but instance_size
>>>> and the instance type cast macro is a bit different (because
>>>> instances of interface types are never created directly).
>>>>
>>>> For the draft we have here, it shouldn't make any difference if
>>>> you use OBJECT_DECLARE_TYPE, because the instance type cast
>>>> macros are left unused.
>>>>
>>>> Normally the use case for interfaces is not like what I did here.
>>>> Interfaces are usually attached to other classes (to declare that
>>>> object instances of that class implement the methods of that
>>>> interface).  Using interfaces would be just an intermediate step
>>>> to the solution Paolo was mentioning (dynamically adding
>>>> interface to classes, see [1] above).
>>>>
>>>
>>> Makes sense to me,
>>> let me know how you guys would like to proceed from here.
>>>
>>
>> To me, the main issue (also raised by Paolo above) is the fact
>> that you are doing *_enabled() checks in the module init
>> functions.  Every single use case we have for module init
>> functions today is for unconditionally registering code or data
>> structures provided by a code module (config group names, QOM
>> types, block backends, multifd methods, etc.), and none of them
>> depend on runtime options (like machine or accelerator options).
> 
> 
> Ok, no _enabled() checks, got it.
> 
> Just to note, since _enabled() has multiple meanings depending on configuration (CONFIG_KVM),
> the _enabled() used in kvm/cpu.c has actually the meaning of:
> 
> if (accelerator_finally_chosen == KVM).
> 
> But we can refactor this implicit check out, and make it instead a
> 
> accel_cpu_init("kvm"), like you suggest, so that the ifs disappear.
> 
> 
> 
>>
>> The x86_cpu_accel_init() calls, on the other hand, are not module
>> initialization, but just one additional step of
>> machine/accelerator/cpu initialization.
>>
>>
>>> The thing I am still uncertain about, looking at your tree at:
>>>
>>> https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel
>>>
>>> is the removal of MODULE_INIT_ACCEL_CPU, it would be way simpler to understand I think,
>>> both for CpuAccelOps and X86CPUAccel, and is actualy in my view a perfect fit for
>>> the problem that module_call_init is supposed to solve.
>>
>> That was one of my goals.  My first goal was the removal of the
>> (hvm|kvm|tcg)_enabled() checks in the accel init functions.  My
>> secondary goal (and a side effect of the first goal) was making
>> MODULE_INIT_ACCEL_CPU unnecessary.
>>
>> If we are not trying to remove the *_enabled() checks in the
>> accel init functions (nor trying to make MODULE_INIT_ACCEL_CPU
>> unnecessary), my suggestion of using QOM doesn't make things
>> simpler.
>>
>> Let's hear what Paolo thinks.
>>
>> If you want to proceed with the accel_register_call() solution
>> suggested by Paolo, that's OK to me.  I just don't think we
>> really need it, because QOM already solves the problem for us.
>>
> 
> Ok, thanks for all the input, will need some time to process,
> 
> thanks,
> 
> Claudio
> 

One idea that came to mind is, why not extend accel.h to user mode?

It already contains

#ifndef CONFIG_USER_ONLY

parts, so maybe it was meant to be used by both, and just happened to end up confined to include/softmmu ?

Basically I was thinking, we could have an AccelState and an AccelClass for user mode as well (without bringing in the whole machine thing),
and from there we could use current_accel() to build up the right name for the chosen accelerator?

Ciao,

Claudio





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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-23  9:55                                     ` Claudio Fontana
@ 2020-11-23 13:18                                       ` Paolo Bonzini
  2020-11-23 15:02                                         ` Claudio Fontana
  0 siblings, 1 reply; 41+ messages in thread
From: Paolo Bonzini @ 2020-11-23 13:18 UTC (permalink / raw)
  To: Claudio Fontana, Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Colin Xu

On 23/11/20 10:55, Claudio Fontana wrote:
> One idea that came to mind is, why not extend accel.h to user mode?
> 
> It already contains
> 
> #ifndef CONFIG_USER_ONLY
> 
> parts, so maybe it was meant to be used by both, and just happened to
> end up confined to include/softmmu ?
> 
> Basically I was thinking, we could have an AccelState and an
> AccelClass for user mode as well (without bringing in the whole
> machine thing), and from there we could use current_accel() to build
> up the right name for the chosen accelerator?

Yes, extending the accelerator class to usermode emulation is certainly 
a good idea.

Paolo



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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-23 13:18                                       ` Paolo Bonzini
@ 2020-11-23 15:02                                         ` Claudio Fontana
  2020-11-23 15:14                                           ` Paolo Bonzini
  2020-11-23 18:20                                           ` Eduardo Habkost
  0 siblings, 2 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-23 15:02 UTC (permalink / raw)
  To: Paolo Bonzini, Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Colin Xu

On 11/23/20 2:18 PM, Paolo Bonzini wrote:
> On 23/11/20 10:55, Claudio Fontana wrote:
>> One idea that came to mind is, why not extend accel.h to user mode?
>>
>> It already contains
>>
>> #ifndef CONFIG_USER_ONLY
>>
>> parts, so maybe it was meant to be used by both, and just happened to
>> end up confined to include/softmmu ?
>>
>> Basically I was thinking, we could have an AccelState and an
>> AccelClass for user mode as well (without bringing in the whole
>> machine thing), and from there we could use current_accel() to build
>> up the right name for the chosen accelerator?
> 
> Yes, extending the accelerator class to usermode emulation is certainly 
> a good idea.
> 
> Paolo
> 

Thanks, I'll work on this option.

Btw considering that CpusAccel for tcg is actually three different interfaces (for mttcg, for icount, and plain RR),
it will be tough to, in the stated objective, "remove all conditionals", even after removing the tcg_enabled().

I wonder how you see this issue (patches for 3 TCG split are in Richard's queue atm).

static void tcg_accel_cpu_init(void)
{
    if (tcg_enabled()) {
        TCGState *s = TCG_STATE(current_accel());

        if (s->mttcg_enabled) {
            cpus_register_accel(&tcg_cpus_mttcg);
        } else if (icount_enabled()) {
            cpus_register_accel(&tcg_cpus_icount);
        } else {
            cpus_register_accel(&tcg_cpus_rr);
        }
    }
}

Ciao,

Claudio


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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-23 15:02                                         ` Claudio Fontana
@ 2020-11-23 15:14                                           ` Paolo Bonzini
  2020-11-23 18:20                                           ` Eduardo Habkost
  1 sibling, 0 replies; 41+ messages in thread
From: Paolo Bonzini @ 2020-11-23 15:14 UTC (permalink / raw)
  To: Claudio Fontana, Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Sunil Muthuswamy,
	Dario Faggioli, Olaf Hering, Colin Xu

On 23/11/20 16:02, Claudio Fontana wrote:
> Thanks, I'll work on this option.
> 
> Btw considering that CpusAccel for tcg is actually three different interfaces (for mttcg, for icount, and plain RR),
> it will be tough to, in the stated objective, "remove all conditionals", even after removing the tcg_enabled().

I'm not sure removing all conditionals is a goal in and of itself, but 
of course keeping the conditionals more local should be a good.

Paolo

> I wonder how you see this issue (patches for 3 TCG split are in Richard's queue atm).
> 
> static void tcg_accel_cpu_init(void)
> {
>      if (tcg_enabled()) {
>          TCGState *s = TCG_STATE(current_accel());
> 
>          if (s->mttcg_enabled) {
>              cpus_register_accel(&tcg_cpus_mttcg);
>          } else if (icount_enabled()) {
>              cpus_register_accel(&tcg_cpus_icount);
>          } else {
>              cpus_register_accel(&tcg_cpus_rr);
>          }
>      }



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

* Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
  2020-11-23 15:02                                         ` Claudio Fontana
  2020-11-23 15:14                                           ` Paolo Bonzini
@ 2020-11-23 18:20                                           ` Eduardo Habkost
  1 sibling, 0 replies; 41+ messages in thread
From: Eduardo Habkost @ 2020-11-23 18:20 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Bruce Rogers, Roman Bolshakov, Wenchao Wang, haxm-team,
	Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Dario Faggioli, Olaf Hering, Colin Xu

On Mon, Nov 23, 2020 at 04:02:24PM +0100, Claudio Fontana wrote:
> On 11/23/20 2:18 PM, Paolo Bonzini wrote:
> > On 23/11/20 10:55, Claudio Fontana wrote:
> >> One idea that came to mind is, why not extend accel.h to user mode?
> >>
> >> It already contains
> >>
> >> #ifndef CONFIG_USER_ONLY
> >>
> >> parts, so maybe it was meant to be used by both, and just happened to
> >> end up confined to include/softmmu ?
> >>
> >> Basically I was thinking, we could have an AccelState and an
> >> AccelClass for user mode as well (without bringing in the whole
> >> machine thing), and from there we could use current_accel() to build
> >> up the right name for the chosen accelerator?
> > 
> > Yes, extending the accelerator class to usermode emulation is certainly 
> > a good idea.
> > 
> > Paolo
> > 
> 
> Thanks, I'll work on this option.
> 
> Btw considering that CpusAccel for tcg is actually three different interfaces (for mttcg, for icount, and plain RR),
> it will be tough to, in the stated objective, "remove all conditionals", even after removing the tcg_enabled().

The main issue were the conditionals inside module init function.
They are completely OK inside accel-specific methods.

> 
> I wonder how you see this issue (patches for 3 TCG split are in Richard's queue atm).
> 
> static void tcg_accel_cpu_init(void)
> {
>     if (tcg_enabled()) {
>         TCGState *s = TCG_STATE(current_accel());
> 
>         if (s->mttcg_enabled) {
>             cpus_register_accel(&tcg_cpus_mttcg);
>         } else if (icount_enabled()) {
>             cpus_register_accel(&tcg_cpus_icount);
>         } else {
>             cpus_register_accel(&tcg_cpus_rr);
>         }
>     }
> }

Probably what we are missing here is a non-softmmu-specific
AccelClass.init() method?

-- 
Eduardo



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

* Re: [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-20  9:08         ` Claudio Fontana
@ 2020-11-23 18:24           ` Eduardo Habkost
  2020-11-23 18:34             ` Claudio Fontana
  0 siblings, 1 reply; 41+ messages in thread
From: Eduardo Habkost @ 2020-11-23 18:24 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Wenchao Wang,
	haxm-team, Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Olaf Hering, Colin Xu

On Fri, Nov 20, 2020 at 10:08:46AM +0100, Claudio Fontana wrote:
> On 11/19/20 8:23 PM, Eduardo Habkost wrote:
> > On Thu, Nov 19, 2020 at 09:53:09AM +0100, Claudio Fontana wrote:
> >> Hi,
> >>
> >> On 11/18/20 7:28 PM, Eduardo Habkost wrote:
> >>> On Wed, Nov 18, 2020 at 11:29:36AM +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.c        KVM x86 cpu type
> >>>> hvf/cpu.c        HVF x86 cpu type
> >>>> tcg/cpu.c        TCG x86 cpu type
> >>>>
> >>>> The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
> >>>> time, when the accelerator is known.
> >>>>
> >>>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
> >>>> ---
> >>> [...]
> >>>> +/**
> >>>> + * X86CPUAccel:
> >>>> + * @name: string name of the X86 CPU Accelerator
> >>>> + *
> >>>> + * @common_class_init: initializer for the common cpu
> >>>
> >>> So this will be called for every single CPU class.
> >>
> >> Not really, it's called for every TYPE_X86_CPU cpu class (if an accel interface is registered).
> > 
> > This means every single non-abstract CPU class in
> > qemu-system-x86_64, correct?
> > 
> >>
> >> This function extends the existing x86_cpu_common_class_init (target/i386/cpu.c),
> >> where some methods of the base class CPUClass are set.
> >>
> >>>
> >>>> + * @instance_init: cpu instance initialization
> >>>> + * @realizefn: realize function, called first in x86 cpu realize
> >>>> + *
> >>>> + * X86 CPU accelerator-specific CPU initializations
> >>>> + */
> >>>> +
> >>>> +struct X86CPUAccel {
> >>>> +    const char *name;
> >>>> +
> >>>> +    void (*common_class_init)(X86CPUClass *xcc);
> >>>> +    void (*instance_init)(X86CPU *cpu);
> >>>> +    void (*realizefn)(X86CPU *cpu, Error **errp);
> >>>>  };
> >>>>  
> >>>> +void x86_cpu_accel_init(const X86CPUAccel *accel);
> >>> [...]
> >>>> +static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
> >>>> +{
> >>>> +    X86CPUClass *xcc = X86_CPU_CLASS(klass);
> >>>> +    const X86CPUAccel **accel = opaque;
> >>>> +
> >>>> +    xcc->accel = *accel;
> >>>> +    xcc->accel->common_class_init(xcc);
> >>>> +}
> >>>> +
> >>>> +void x86_cpu_accel_init(const X86CPUAccel *accel)
> >>>> +{
> >>>> +    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
> >>>> +}
> >>>
> >>> This matches the documented behavior.
> >>>
> >>> [...]
> >>>> +void host_cpu_class_init(X86CPUClass *xcc)
> >>>> +{
> >>>> +    xcc->host_cpuid_required = true;
> >>>> +    xcc->ordering = 8;
> >>>> +    xcc->model_description =
> >>>> +        g_strdup_printf("%s processor with all supported host features ",
> >>>> +                        xcc->accel->name);
> >>>> +}
> >>> [...]
> >>>> +static void hvf_cpu_common_class_init(X86CPUClass *xcc)
> >>>> +{
> >>>> +    host_cpu_class_init(xcc);
> >>>
> >>> Why are you calling host_cpu_class_init() for all CPU types?
> >>
> >> I am not..
> > 
> > I don't get it.  You are calling host_cpu_class_init() for every
> > single non-abstract TYPE_X86_CPU subclass (which includes all CPU
> > models in qemu-system-x86_64), and I don't understand why, or if
> > this is really intentional.
> 
> It is really intentional what is done here,
> 
> when HVF accelerator is enabled, and only when the HVF accelerator is enabled,
> 
> all X86 CPU classes and subclasses (cpu models, which have been
> implemented as subclasses of TYPE_X86_CPU), are updated with a
> link to the accelerator-specific HVF interface.

I'm confused.  That (updating the class with a link) is not what
host_cpu_class_init() does.

This is what host_cpu_class_init() does:

void host_cpu_class_init(X86CPUClass *xcc)
{
    xcc->host_cpuid_required = true;
    xcc->ordering = 8;
    xcc->model_description =
        g_strdup_printf("%s processor with all supported host features ",
                        xcc->accel->name);
}

Why do you want to call host_cpu_class_init() for every non-abstract
TYPE_X86_CPU subclass?

-- 
Eduardo



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

* Re: [RFC v3 9/9] i386: split cpu accelerators from cpu.c
  2020-11-23 18:24           ` Eduardo Habkost
@ 2020-11-23 18:34             ` Claudio Fontana
  0 siblings, 0 replies; 41+ messages in thread
From: Claudio Fontana @ 2020-11-23 18:34 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Laurent Vivier, Thomas Huth, Stefano Stabellini, Paul Durrant,
	Philippe Mathieu-Daudé,
	Jason Wang, Marcelo Tosatti, Richard Henderson, qemu-devel,
	Peter Xu, Dario Faggioli, Roman Bolshakov, Wenchao Wang,
	haxm-team, Cameron Esfahani, Anthony Perard, Paolo Bonzini,
	Sunil Muthuswamy, Bruce Rogers, Olaf Hering, Colin Xu

On 11/23/20 7:24 PM, Eduardo Habkost wrote:
> On Fri, Nov 20, 2020 at 10:08:46AM +0100, Claudio Fontana wrote:
>> On 11/19/20 8:23 PM, Eduardo Habkost wrote:
>>> On Thu, Nov 19, 2020 at 09:53:09AM +0100, Claudio Fontana wrote:
>>>> Hi,
>>>>
>>>> On 11/18/20 7:28 PM, Eduardo Habkost wrote:
>>>>> On Wed, Nov 18, 2020 at 11:29:36AM +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.c        KVM x86 cpu type
>>>>>> hvf/cpu.c        HVF x86 cpu type
>>>>>> tcg/cpu.c        TCG x86 cpu type
>>>>>>
>>>>>> The accel interface of the X86CPUClass is set at MODULE_INIT_ACCEL_CPU
>>>>>> time, when the accelerator is known.
>>>>>>
>>>>>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>>>>>> ---
>>>>> [...]
>>>>>> +/**
>>>>>> + * X86CPUAccel:
>>>>>> + * @name: string name of the X86 CPU Accelerator
>>>>>> + *
>>>>>> + * @common_class_init: initializer for the common cpu
>>>>>
>>>>> So this will be called for every single CPU class.
>>>>
>>>> Not really, it's called for every TYPE_X86_CPU cpu class (if an accel interface is registered).
>>>
>>> This means every single non-abstract CPU class in
>>> qemu-system-x86_64, correct?
>>>
>>>>
>>>> This function extends the existing x86_cpu_common_class_init (target/i386/cpu.c),
>>>> where some methods of the base class CPUClass are set.
>>>>
>>>>>
>>>>>> + * @instance_init: cpu instance initialization
>>>>>> + * @realizefn: realize function, called first in x86 cpu realize
>>>>>> + *
>>>>>> + * X86 CPU accelerator-specific CPU initializations
>>>>>> + */
>>>>>> +
>>>>>> +struct X86CPUAccel {
>>>>>> +    const char *name;
>>>>>> +
>>>>>> +    void (*common_class_init)(X86CPUClass *xcc);
>>>>>> +    void (*instance_init)(X86CPU *cpu);
>>>>>> +    void (*realizefn)(X86CPU *cpu, Error **errp);
>>>>>>  };
>>>>>>  
>>>>>> +void x86_cpu_accel_init(const X86CPUAccel *accel);
>>>>> [...]
>>>>>> +static void x86_cpu_accel_init_aux(ObjectClass *klass, void *opaque)
>>>>>> +{
>>>>>> +    X86CPUClass *xcc = X86_CPU_CLASS(klass);
>>>>>> +    const X86CPUAccel **accel = opaque;
>>>>>> +
>>>>>> +    xcc->accel = *accel;
>>>>>> +    xcc->accel->common_class_init(xcc);
>>>>>> +}
>>>>>> +
>>>>>> +void x86_cpu_accel_init(const X86CPUAccel *accel)
>>>>>> +{
>>>>>> +    object_class_foreach(x86_cpu_accel_init_aux, TYPE_X86_CPU, false, &accel);
>>>>>> +}
>>>>>
>>>>> This matches the documented behavior.
>>>>>
>>>>> [...]
>>>>>> +void host_cpu_class_init(X86CPUClass *xcc)
>>>>>> +{
>>>>>> +    xcc->host_cpuid_required = true;
>>>>>> +    xcc->ordering = 8;
>>>>>> +    xcc->model_description =
>>>>>> +        g_strdup_printf("%s processor with all supported host features ",
>>>>>> +                        xcc->accel->name);
>>>>>> +}
>>>>> [...]
>>>>>> +static void hvf_cpu_common_class_init(X86CPUClass *xcc)
>>>>>> +{
>>>>>> +    host_cpu_class_init(xcc);
>>>>>
>>>>> Why are you calling host_cpu_class_init() for all CPU types?
>>>>
>>>> I am not..
>>>
>>> I don't get it.  You are calling host_cpu_class_init() for every
>>> single non-abstract TYPE_X86_CPU subclass (which includes all CPU
>>> models in qemu-system-x86_64), and I don't understand why, or if
>>> this is really intentional.
>>
>> It is really intentional what is done here,
>>
>> when HVF accelerator is enabled, and only when the HVF accelerator is enabled,
>>
>> all X86 CPU classes and subclasses (cpu models, which have been
>> implemented as subclasses of TYPE_X86_CPU), are updated with a
>> link to the accelerator-specific HVF interface.
> 
> I'm confused.  That (updating the class with a link) is not what
> host_cpu_class_init() does.
> 
> This is what host_cpu_class_init() does:
> 
> void host_cpu_class_init(X86CPUClass *xcc)
> {
>     xcc->host_cpuid_required = true;
>     xcc->ordering = 8;
>     xcc->model_description =
>         g_strdup_printf("%s processor with all supported host features ",
>                         xcc->accel->name);
> }
> 
> Why do you want to call host_cpu_class_init() for every non-abstract
> TYPE_X86_CPU subclass?
> 

Only now I got your point, sorry for not seeing it before. It is clearly a mistake, this should be referenced by the host cpu type!

Thanks a lot!

Claudio





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

end of thread, other threads:[~2020-11-23 18:36 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-18 10:29 [RFC v3 0/9] i386 cleanup Claudio Fontana
2020-11-18 10:29 ` [RFC v3 1/9] i386: move kvm accel files into kvm/ Claudio Fontana
2020-11-18 10:29 ` [RFC v3 2/9] i386: move whpx accel files into whpx/ Claudio Fontana
2020-11-18 10:29 ` [RFC v3 3/9] i386: move hax accel files into hax/ Claudio Fontana
2020-11-18 10:29 ` [RFC v3 4/9] i386: hvf: remove stale MAINTAINERS entry for old hvf stubs Claudio Fontana
2020-11-18 16:09   ` Roman Bolshakov
2020-11-18 10:29 ` [RFC v3 5/9] i386: move TCG accel files into tcg/ Claudio Fontana
2020-11-18 10:29 ` [RFC v3 6/9] i386: move cpu dump out of helper.c into cpu-dump.c Claudio Fontana
2020-11-18 10:29 ` [RFC v3 7/9] i386: move TCG cpu class initialization out of helper.c Claudio Fontana
2020-11-18 10:29 ` [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU Claudio Fontana
2020-11-18 12:38   ` Claudio Fontana
2020-11-18 12:48   ` Eduardo Habkost
2020-11-18 13:48     ` Claudio Fontana
2020-11-18 14:05       ` Paolo Bonzini
2020-11-18 14:36         ` Eduardo Habkost
2020-11-18 14:51           ` Paolo Bonzini
2020-11-18 15:25             ` Eduardo Habkost
2020-11-18 15:43               ` Paolo Bonzini
2020-11-18 16:11                 ` Eduardo Habkost
2020-11-18 16:22                   ` Paolo Bonzini
2020-11-18 17:30                     ` Eduardo Habkost
2020-11-18 19:13                       ` Paolo Bonzini
2020-11-18 22:07                         ` Eduardo Habkost
2020-11-20 12:13                           ` Claudio Fontana
2020-11-20 17:19                             ` Eduardo Habkost
2020-11-20 17:41                               ` Claudio Fontana
2020-11-20 18:09                                 ` Eduardo Habkost
2020-11-23  9:29                                   ` Claudio Fontana
2020-11-23  9:55                                     ` Claudio Fontana
2020-11-23 13:18                                       ` Paolo Bonzini
2020-11-23 15:02                                         ` Claudio Fontana
2020-11-23 15:14                                           ` Paolo Bonzini
2020-11-23 18:20                                           ` Eduardo Habkost
2020-11-18 10:29 ` [RFC v3 9/9] i386: split cpu accelerators from cpu.c Claudio Fontana
2020-11-18 18:28   ` Eduardo Habkost
2020-11-19  8:53     ` Claudio Fontana
2020-11-19 19:23       ` Eduardo Habkost
2020-11-20  9:08         ` Claudio Fontana
2020-11-23 18:24           ` Eduardo Habkost
2020-11-23 18:34             ` Claudio Fontana
2020-11-18 11:00 ` [RFC v3 0/9] 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.