* [PATCH 00/13] fix --without-default-devices build and (mostly) tests
@ 2024-05-09 17:00 Paolo Bonzini
2024-05-09 17:00 ` [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
` (12 more replies)
0 siblings, 13 replies; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
The recent change to make boards "default y" made them go away from
a --without-default-devices build, because the boards are not anymore
enabled explicitly in configs/devices/.
This is a problem for some targets that were not fully ready for this
and have generic target code that needs symbols from boards or devices.
The more complicated ones are s390x and i386. In some cases some
components simply have to be required by target/ARCH/, but often
it is better to move some code around, associating it with boards
instead of targets or vice versa.
--without-default-devices builds in practice will always use a
custom config, but let's keep things tidy. This series does
this for s390x (patches 1 to 5) and x86 (patches 6 to 12). As a
small addendum, patch 13 fixes qtest for ARM (32- and 64-bit) on a
--without-default-devices build.
The series seems huge, but it's mostly code movement. Patch 10
in particular moves board building code, which is unrelated to the
X86MachineState superclass and has many dependencies on NUMA or
hw/i386/pc-sysfw.c.
I suspect that there are more issues, for example when building
a CONFIG_MICROVM-only binary. Fixing builds without boards on vanilla
upstream configs is the more pressing problem, though.
Patches 6 and 7 were tested with the Avocado Xen-on-KVM tests.
Paolo
Paolo Bonzini (13):
s390x: move s390_cpu_addr2state to target/s390x/sigp.c
s390_flic: add migration-enabled property
s390: move css_migration_enabled from machine to css.c
s390x: select correct components for no-board build
tests/qtest: s390x: fix operation in a build without any boards or
devices
xen: initialize legacy backends from xen_bus_init()
xen: register legacy backends via xen_backend_init
i386: correctly select code in hw/i386 that depends on other
components
i386: pc: remove unnecessary MachineClass overrides
hw/i386: split x86.c in multiple parts
hw/i386: move rtc-reset-reinjection command out of hw/rtc
i386: select correct components for no-board build
tests/qtest: arm: fix operation in a build without any boards or
devices
include/hw/i386/x86.h | 10 +-
include/hw/rtc/mc146818rtc.h | 2 +-
include/hw/s390x/css.h | 6 +
include/hw/s390x/s390-virtio-ccw.h | 7 -
include/hw/s390x/s390_flic.h | 1 +
include/hw/xen/xen-legacy-backend.h | 14 +-
include/hw/xen/xen_pvdev.h | 1 -
hw/9pfs/xen-9p-backend.c | 8 +-
hw/display/xenfb.c | 8 +-
hw/i386/fw_cfg.c | 2 +
hw/i386/monitor.c | 46 ++
hw/i386/pc.c | 4 -
hw/i386/x86-common.c | 1007 +++++++++++++++++++++++++
hw/i386/x86-cpu.c | 97 +++
hw/i386/x86.c | 1058 +--------------------------
hw/intc/ioapic-stub.c | 29 +
hw/intc/s390_flic.c | 6 +-
hw/rtc/mc146818rtc.c | 12 +-
hw/s390x/css.c | 10 +-
hw/s390x/s390-virtio-ccw.c | 32 +-
hw/usb/xen-usb.c | 14 +-
hw/xen/xen-bus.c | 4 +
hw/xen/xen-hvm-common.c | 2 -
hw/xen/xen-legacy-backend.c | 16 -
hw/xenpv/xen_machine_pv.c | 5 +-
target/s390x/sigp.c | 17 +
tests/qtest/arm-cpu-features.c | 4 +
tests/qtest/drive_del-test.c | 7 +-
tests/qtest/migration-test.c | 6 +
tests/qtest/numa-test.c | 4 +
.gitlab-ci.d/buildtest.yml | 4 +-
hw/i386/meson.build | 7 +-
hw/intc/meson.build | 2 +-
target/i386/Kconfig | 1 +
target/s390x/Kconfig | 2 +
35 files changed, 1289 insertions(+), 1166 deletions(-)
create mode 100644 hw/i386/monitor.c
create mode 100644 hw/i386/x86-common.c
create mode 100644 hw/i386/x86-cpu.c
create mode 100644 hw/intc/ioapic-stub.c
--
2.45.0
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 4:59 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 02/13] s390_flic: add migration-enabled property Paolo Bonzini
` (11 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
This function has no dependency on the virtio-ccw machine type, though it
assumes that the CPU address corresponds to the core_id and the index.
If there is any need of something different or more fancy (unlikely)
S390 can include a MachineClass subclass and implement it there. For
now, move it to sigp.c for simplicity.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 16 ----------------
target/s390x/sigp.c | 17 +++++++++++++++++
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4dcc2138200..feabc173eb3 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -50,22 +50,6 @@
static Error *pv_mig_blocker;
-S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
-{
- static MachineState *ms;
-
- if (!ms) {
- ms = MACHINE(qdev_get_machine());
- g_assert(ms->possible_cpus);
- }
-
- /* CPU address corresponds to the core_id and the index */
- if (cpu_addr >= ms->possible_cpus->len) {
- return NULL;
- }
- return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
-}
-
static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
Error **errp)
{
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index 9dd977349ab..ad0ad61177d 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "s390x-internal.h"
+#include "hw/boards.h"
#include "sysemu/hw_accel.h"
#include "sysemu/runstate.h"
#include "exec/address-spaces.h"
@@ -435,6 +436,22 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
return SIGP_CC_STATUS_STORED;
}
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
+{
+ static MachineState *ms;
+
+ if (!ms) {
+ ms = MACHINE(qdev_get_machine());
+ g_assert(ms->possible_cpus);
+ }
+
+ /* CPU address corresponds to the core_id and the index */
+ if (cpu_addr >= ms->possible_cpus->len) {
+ return NULL;
+ }
+ return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
+}
+
int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
{
uint64_t *status_reg = &env->regs[r1];
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 02/13] s390_flic: add migration-enabled property
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
2024-05-09 17:00 ` [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 5:06 ` Thomas Huth
2024-05-16 14:42 ` Marc Hartmayer
2024-05-09 17:00 ` [PATCH 03/13] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
` (10 subsequent siblings)
12 siblings, 2 replies; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
Instead of mucking with css_migration_enabled(), add a property specific to
the FLIC device, similar to what is done for TYPE_S390_STATTRIB.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/s390x/s390_flic.h | 1 +
hw/intc/s390_flic.c | 6 +++++-
hw/s390x/s390-virtio-ccw.c | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 3907a13d076..bcb081def58 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -47,6 +47,7 @@ struct S390FLICState {
/* to limit AdapterRoutes.num_routes for compat */
uint32_t adapter_routes_max_batch;
bool ais_supported;
+ bool migration_enabled;
};
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index f4a848460b8..7f930800877 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -405,6 +405,8 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
static Property s390_flic_common_properties[] = {
DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState,
adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI),
+ DEFINE_PROP_BOOL("migration-enabled", S390FLICState,
+ migration_enabled, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -457,7 +459,9 @@ type_init(qemu_s390_flic_register_types)
static bool adapter_info_so_needed(void *opaque)
{
- return css_migration_enabled();
+ S390FLICState *fs = S390_FLIC_COMMON(opaque);
+
+ return fs->migration_enabled;
}
const VMStateDescription vmstate_adapter_info_so = {
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index feabc173eb3..1383e47eeb5 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -1174,6 +1174,7 @@ static void ccw_machine_2_9_class_options(MachineClass *mc)
S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
static GlobalProperty compat[] = {
{ TYPE_S390_STATTRIB, "migration-enabled", "off", },
+ { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
};
ccw_machine_2_10_class_options(mc);
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 03/13] s390: move css_migration_enabled from machine to css.c
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
2024-05-09 17:00 ` [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
2024-05-09 17:00 ` [PATCH 02/13] s390_flic: add migration-enabled property Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 5:37 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 04/13] s390x: select correct components for no-board build Paolo Bonzini
` (9 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
The CSS subsystem uses global variables, just face the truth and use
a variable also for whether the CSS vmstate is in use; remove the
indirection of fetching it from the machine type, which makes the
TCG code depend unnecessarily on the virtio-ccw machine.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/s390x/css.h | 6 ++++++
include/hw/s390x/s390-virtio-ccw.h | 7 -------
hw/s390x/css.c | 10 +++++++---
hw/s390x/s390-virtio-ccw.c | 15 +++------------
4 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index ba72ee3dd20..8289e458370 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -333,4 +333,10 @@ static inline int ccw_dstream_read_buf(CcwDataStream *cds, void *buff, int len)
#define ccw_dstream_read(cds, v) ccw_dstream_read_buf((cds), &(v), sizeof(v))
#define ccw_dstream_write(cds, v) ccw_dstream_write_buf((cds), &(v), sizeof(v))
+/**
+ * true if (vmstate based) migration of the channel subsystem
+ * is enabled, false if it is disabled.
+ */
+extern bool css_migration_enabled;
+
#endif
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index c1d46e78af8..c0494e511cb 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -43,7 +43,6 @@ struct S390CcwMachineClass {
/*< public >*/
bool ri_allowed;
bool cpu_model_allowed;
- bool css_migration_enabled;
bool hpage_1m_allowed;
int max_threads;
};
@@ -55,10 +54,4 @@ bool cpu_model_allowed(void);
/* 1M huge page mappings allowed by the machine */
bool hpage_1m_allowed(void);
-/**
- * Returns true if (vmstate based) migration of the channel subsystem
- * is enabled, false if it is disabled.
- */
-bool css_migration_enabled(void);
-
#endif
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 295530963a6..b2d5327dbf4 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -23,6 +23,8 @@
#include "hw/s390x/s390-virtio-ccw.h"
#include "hw/s390x/s390-ccw.h"
+bool css_migration_enabled = true;
+
typedef struct CrwContainer {
CRW crw;
QTAILQ_ENTRY(CrwContainer) sibling;
@@ -180,7 +182,7 @@ static const VMStateDescription vmstate_orb = {
static bool vmstate_schdev_orb_needed(void *opaque)
{
- return css_migration_enabled();
+ return css_migration_enabled;
}
static const VMStateDescription vmstate_schdev_orb = {
@@ -388,7 +390,7 @@ static int subch_dev_post_load(void *opaque, int version_id)
css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
}
- if (css_migration_enabled()) {
+ if (css_migration_enabled) {
/* No compat voodoo to do ;) */
return 0;
}
@@ -412,7 +414,9 @@ static int subch_dev_post_load(void *opaque, int version_id)
void css_register_vmstate(void)
{
- vmstate_register(NULL, 0, &vmstate_css, &channel_subsys);
+ if (css_migration_enabled) {
+ vmstate_register(NULL, 0, &vmstate_css, &channel_subsys);
+ }
}
IndAddr *get_indicator(hwaddr ind_addr, int len)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1383e47eeb5..aa90703d518 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -275,11 +275,9 @@ static void ccw_init(MachineState *machine)
s390_enable_css_support(s390_cpu_addr2state(0));
ret = css_create_css_image(VIRTUAL_CSSID, true);
-
assert(ret == 0);
- if (css_migration_enabled()) {
- css_register_vmstate();
- }
+
+ css_register_vmstate();
/* Create VirtIO network adapters */
s390_create_virtio_net(BUS(css_bus), mc->default_nic);
@@ -741,7 +739,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
s390mc->ri_allowed = true;
s390mc->cpu_model_allowed = true;
- s390mc->css_migration_enabled = true;
s390mc->hpage_1m_allowed = true;
s390mc->max_threads = 1;
mc->init = ccw_init;
@@ -811,11 +808,6 @@ static const TypeInfo ccw_machine_info = {
},
};
-bool css_migration_enabled(void)
-{
- return get_machine_class()->css_migration_enabled;
-}
-
#define DEFINE_CCW_MACHINE(suffix, verstr, latest) \
static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \
void *data) \
@@ -1171,7 +1163,6 @@ static void ccw_machine_2_9_instance_options(MachineState *machine)
static void ccw_machine_2_9_class_options(MachineClass *mc)
{
- S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
static GlobalProperty compat[] = {
{ TYPE_S390_STATTRIB, "migration-enabled", "off", },
{ TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
@@ -1180,7 +1171,7 @@ static void ccw_machine_2_9_class_options(MachineClass *mc)
ccw_machine_2_10_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
- s390mc->css_migration_enabled = false;
+ css_migration_enabled = false;
}
DEFINE_CCW_MACHINE(2_9, "2.9", false);
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 04/13] s390x: select correct components for no-board build
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (2 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 03/13] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 5:11 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
` (8 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
.gitlab-ci.d/buildtest.yml | 4 ++--
target/s390x/Kconfig | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 13afd0df1f0..f8502905203 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
# Check our reduced build configurations
# requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
# mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, s390x, x86_64
+# does not build without boards: i386, x86_64
build-without-defaults:
extends: .native_build_job_template
needs:
@@ -666,7 +666,7 @@ build-without-defaults:
--disable-strip
TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
mips-softmmu mips64-softmmu mipsel-softmmu
- sh4-softmmu sh4eb-softmmu sparc-softmmu
+ s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
hexagon-linux-user i386-linux-user s390x-linux-user
MAKE_CHECK_ARGS: check
diff --git a/target/s390x/Kconfig b/target/s390x/Kconfig
index 72da48136c6..d886be48b47 100644
--- a/target/s390x/Kconfig
+++ b/target/s390x/Kconfig
@@ -1,2 +1,4 @@
config S390X
bool
+ select PCI
+ select S390_FLIC
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (3 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 04/13] s390x: select correct components for no-board build Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 5:13 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 06/13] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
` (7 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
Do the bare minimum to ensure that at least a vanilla
--without-default-devices build works for all targets except i386,
x86_64 and ppc64. In particular this fixes s390x-softmmu; i386 and
x86_64 have about a dozen failing tests that do not pass -M and therefore
require a default machine type; ppc64 has the same issue, though only
with numa-test.
If we can for now ignore the cases where boards and devices are picked
by hand, drive_del-test however can be fixed easily; almost all tests
check for the virtio-blk or virtio-scsi device that they use, and are
already skipped. Only one didn't get the memo; plus another one does
not need a machine at all and can be run with -M none.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/qtest/drive_del-test.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tests/qtest/drive_del-test.c b/tests/qtest/drive_del-test.c
index 8a6f3ac963d..7b67a4bbee4 100644
--- a/tests/qtest/drive_del-test.c
+++ b/tests/qtest/drive_del-test.c
@@ -173,7 +173,7 @@ static void test_drive_without_dev(void)
QTestState *qts;
/* Start with an empty drive */
- qts = qtest_init("-drive if=none,id=drive0");
+ qts = qtest_init("-drive if=none,id=drive0 -M none");
/* Delete the drive */
drive_del(qts);
@@ -192,6 +192,11 @@ static void test_after_failed_device_add(void)
QDict *response;
QTestState *qts;
+ if (!has_device_builtin("virtio-blk")) {
+ g_test_skip("Device virtio-blk is not available");
+ return;
+ }
+
snprintf(driver, sizeof(driver), "virtio-blk-%s",
qvirtio_get_dev_type());
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 06/13] xen: initialize legacy backends from xen_bus_init()
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (4 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 10:18 ` Philippe Mathieu-Daudé
2024-05-09 17:00 ` [PATCH 07/13] xen: register legacy backends via xen_backend_init Paolo Bonzini
` (6 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
Prepare for moving the calls to xen_be_register() under the
control of xen_bus_init(), using the normal xen_backend_init()
method that is used by the "modern" backends.
This requires the xenstore global variable to be initialized,
which is done by xen_be_init(). To ensure that everything is
ready at the time the xen_backend_init() functions are called,
remove the xen_be_init() function from all the boards and
place it directly in xen_bus_init().
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/i386/pc.c | 1 -
hw/xen/xen-bus.c | 4 ++++
hw/xen/xen-hvm-common.c | 2 --
hw/xenpv/xen_machine_pv.c | 5 +----
4 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 505ea750f4d..19f21953b4a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1250,7 +1250,6 @@ void pc_basic_device_init(struct PCMachineState *pcms,
pci_create_simple(pcms->pcibus, -1, "xen-platform");
}
xen_bus_init();
- xen_be_init();
}
#endif
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index fb82cc33e48..95b207ac8b4 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -13,6 +13,7 @@
#include "hw/sysbus.h"
#include "hw/xen/xen.h"
#include "hw/xen/xen-backend.h"
+#include "hw/xen/xen-legacy-backend.h" /* xen_be_init() */
#include "hw/xen/xen-bus.h"
#include "hw/xen/xen-bus-helper.h"
#include "monitor/monitor.h"
@@ -329,6 +330,9 @@ static void xen_bus_realize(BusState *bus, Error **errp)
goto fail;
}
+ /* Initialize legacy backend core & drivers */
+ xen_be_init();
+
if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
"domid", NULL, "%u", &domid) == 1) {
xenbus->backend_id = domid;
diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c
index 1627da73982..2d1b0321214 100644
--- a/hw/xen/xen-hvm-common.c
+++ b/hw/xen/xen-hvm-common.c
@@ -872,8 +872,6 @@ void xen_register_ioreq(XenIOState *state, unsigned int max_cpus,
xen_bus_init();
- xen_be_init();
-
return;
err:
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 1130d1a1479..b500ce09891 100644
--- a/hw/xenpv/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c
@@ -34,8 +34,7 @@ static void xen_init_pv(MachineState *machine)
{
setup_xen_backend_ops();
- /* Initialize backend core & drivers */
- xen_be_init();
+ xen_bus_init();
switch (xen_mode) {
case XEN_ATTACH:
@@ -60,8 +59,6 @@ static void xen_init_pv(MachineState *machine)
vga_interface_created = true;
}
- xen_bus_init();
-
/* config cleanup hook */
atexit(xen_config_cleanup);
}
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 07/13] xen: register legacy backends via xen_backend_init
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (5 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 06/13] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 10:52 ` Philippe Mathieu-Daudé
2024-05-09 17:00 ` [PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
` (5 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
It is okay to register legacy backends in the middle of xen_bus_init().
All that the registration does is record the existence of the backend
in xenstore.
This makes it possible to remove them from the build without introducing
undefined symbols in xen_be_init(). It also removes the need for the
backend_register callback, whose only purpose is to avoid registering
nonfunctional backends.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/xen/xen-legacy-backend.h | 14 ++------------
include/hw/xen/xen_pvdev.h | 1 -
hw/9pfs/xen-9p-backend.c | 8 +++++++-
hw/display/xenfb.c | 8 +++++++-
hw/usb/xen-usb.c | 14 ++++----------
hw/xen/xen-legacy-backend.c | 16 ----------------
6 files changed, 20 insertions(+), 41 deletions(-)
diff --git a/include/hw/xen/xen-legacy-backend.h b/include/hw/xen/xen-legacy-backend.h
index 2cca1747786..979c4ea04c5 100644
--- a/include/hw/xen/xen-legacy-backend.h
+++ b/include/hw/xen/xen-legacy-backend.h
@@ -66,18 +66,8 @@ static inline void xen_be_unmap_grant_ref(struct XenLegacyDevice *xendev,
return xen_be_unmap_grant_refs(xendev, ptr, &ref, 1);
}
-/* actual backend drivers */
-extern struct XenDevOps xen_console_ops; /* xen_console.c */
-extern struct XenDevOps xen_kbdmouse_ops; /* xen_framebuffer.c */
-extern struct XenDevOps xen_framebuffer_ops; /* xen_framebuffer.c */
-extern struct XenDevOps xen_blkdev_ops; /* xen_disk.c */
-#ifdef CONFIG_VIRTFS
-extern struct XenDevOps xen_9pfs_ops; /* xen-9p-backend.c */
-#endif
-extern struct XenDevOps xen_netdev_ops; /* xen_nic.c */
-#ifdef CONFIG_USB_LIBUSB
-extern struct XenDevOps xen_usb_ops; /* xen-usb.c */
-#endif
+/* backend drivers not included in all machines */
+extern struct XenDevOps xen_framebuffer_ops; /* xenfb.c */
/* configuration (aka xenbus setup) */
void xen_config_cleanup(void);
diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h
index ddad4b9f36a..fdf84f47af1 100644
--- a/include/hw/xen/xen_pvdev.h
+++ b/include/hw/xen/xen_pvdev.h
@@ -29,7 +29,6 @@ struct XenDevOps {
const char *node);
void (*frontend_changed)(struct XenLegacyDevice *xendev,
const char *node);
- int (*backend_register)(void);
};
struct XenLegacyDevice {
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index 4aa9c8c736d..a3ac53f989e 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -513,7 +513,7 @@ static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
}
-struct XenDevOps xen_9pfs_ops = {
+static struct XenDevOps xen_9pfs_ops = {
.size = sizeof(Xen9pfsDev),
.flags = DEVOPS_FLAG_NEED_GNTDEV,
.alloc = xen_9pfs_alloc,
@@ -522,3 +522,9 @@ struct XenDevOps xen_9pfs_ops = {
.disconnect = xen_9pfs_disconnect,
.free = xen_9pfs_free,
};
+
+static void xen_9pfs_register_backend(void)
+{
+ xen_be_register("9pfs", &xen_9pfs_ops);
+}
+xen_backend_init(xen_9pfs_register_backend);
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index b2130a0d700..27536bfce0c 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -972,7 +972,7 @@ static void fb_event(struct XenLegacyDevice *xendev)
/* -------------------------------------------------------------------- */
-struct XenDevOps xen_kbdmouse_ops = {
+static struct XenDevOps xen_kbdmouse_ops = {
.size = sizeof(struct XenInput),
.init = input_init,
.initialise = input_initialise,
@@ -995,3 +995,9 @@ static const GraphicHwOps xenfb_ops = {
.gfx_update = xenfb_update,
.ui_info = xenfb_ui_info,
};
+
+static void xen_vkbd_register_backend(void)
+{
+ xen_be_register("vkbd", &xen_kbdmouse_ops);
+}
+xen_backend_init(xen_vkbd_register_backend);
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index 09ec326aeae..416623f956a 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -1083,7 +1083,7 @@ static void usbback_event(struct XenLegacyDevice *xendev)
qemu_bh_schedule(usbif->bh);
}
-struct XenDevOps xen_usb_ops = {
+static struct XenDevOps xen_usb_ops = {
.size = sizeof(struct usbback_info),
.flags = DEVOPS_FLAG_NEED_GNTDEV,
.init = usbback_init,
@@ -1095,15 +1095,9 @@ struct XenDevOps xen_usb_ops = {
.event = usbback_event,
};
-#else /* USBIF_SHORT_NOT_OK */
-
-static int usbback_not_supported(void)
+static void xen_usb_register_backend(void)
{
- return -EINVAL;
+ xen_be_register("qusb", &xen_usb_ops);
}
-
-struct XenDevOps xen_usb_ops = {
- .backend_register = usbback_not_supported,
-};
-
+xen_backend_init(xen_usb_register_backend);
#endif
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 124dd5f3d68..6f0b300a421 100644
--- a/hw/xen/xen-legacy-backend.c
+++ b/hw/xen/xen-legacy-backend.c
@@ -622,27 +622,11 @@ void xen_be_init(void)
qbus_set_bus_hotplug_handler(xen_sysbus);
xen_set_dynamic_sysbus();
-
- xen_be_register("vkbd", &xen_kbdmouse_ops);
-#ifdef CONFIG_VIRTFS
- xen_be_register("9pfs", &xen_9pfs_ops);
-#endif
-#ifdef CONFIG_USB_LIBUSB
- xen_be_register("qusb", &xen_usb_ops);
-#endif
}
int xen_be_register(const char *type, struct XenDevOps *ops)
{
char path[50];
- int rc;
-
- if (ops->backend_register) {
- rc = ops->backend_register();
- if (rc) {
- return rc;
- }
- }
snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
type);
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (6 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 07/13] xen: register legacy backends via xen_backend_init Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 12:15 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
` (4 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
fw_cfg.c and vapic.c are currently included unconditionally but
depend on other components. vapic.c depends on the local APIC,
while fw_cfg.c includes a piece of AML builder code that depends
on CONFIG_ACPI.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/i386/fw_cfg.c | 2 ++
hw/i386/meson.build | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index d802d2787f0..6e0d9945d07 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -203,6 +203,7 @@ void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg)
fw_cfg_add_file(fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
}
+#ifdef CONFIG_ACPI
void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
{
/*
@@ -229,3 +230,4 @@ void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
+#endif
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index d8b70ef3e9c..d9da676038c 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -1,12 +1,12 @@
i386_ss = ss.source_set()
i386_ss.add(files(
'fw_cfg.c',
- 'vapic.c',
'e820_memory_layout.c',
'multiboot.c',
'x86.c',
))
+i386_ss.add(when: 'CONFIG_APIC', if_true: files('vapic.c'))
i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
if_false: files('x86-iommu-stub.c'))
i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'),
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (7 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 12:05 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 10/13] hw/i386: split x86.c in multiple parts Paolo Bonzini
` (3 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
There is no need to override these fields of MachineClass because they are
already set to the right value in the superclass.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/i386/x86.h | 4 ----
hw/i386/pc.c | 3 ---
hw/i386/x86.c | 6 +++---
3 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index d7b7d3f3ce0..c2062db13f5 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -114,10 +114,6 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
-CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
- unsigned cpu_index);
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx);
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);
CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 19f21953b4a..bfb46e9b548 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1826,9 +1826,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = pc_get_hotplug_handler;
mc->hotplug_allowed = pc_hotplug_allowed;
- mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
- mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
- mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
mc->auto_enable_numa_with_memhp = true;
mc->auto_enable_numa_with_memdev = true;
mc->has_hotpluggable_cpus = true;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index c61f4ebfa6a..fcef652c1e3 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -443,7 +443,7 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
numa_cpu_pre_plug(cpu_slot, dev, errp);
}
-CpuInstanceProperties
+static CpuInstanceProperties
x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
@@ -453,7 +453,7 @@ x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
return possible_cpus->cpus[cpu_index].props;
}
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
+static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
{
X86CPUTopoIDs topo_ids;
X86MachineState *x86ms = X86_MACHINE(ms);
@@ -467,7 +467,7 @@ int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
return topo_ids.pkg_id % ms->numa_state->num_nodes;
}
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
+static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
{
X86MachineState *x86ms = X86_MACHINE(ms);
unsigned int max_cpus = ms->smp.max_cpus;
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 10/13] hw/i386: split x86.c in multiple parts
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (8 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 12:32 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
` (2 subsequent siblings)
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
Keep the basic X86MachineState definition in x86.c. Move out functions that
are only needed by other files: x86-common.c for the pc and microvm machines,
x86-cpu.c for those used by accelerator code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/i386/x86.h | 6 +-
hw/i386/x86-common.c | 1007 +++++++++++++++++++++++++++++++++++++++
hw/i386/x86-cpu.c | 97 ++++
hw/i386/x86.c | 1052 +----------------------------------------
hw/i386/meson.build | 4 +-
5 files changed, 1113 insertions(+), 1053 deletions(-)
create mode 100644 hw/i386/x86-common.c
create mode 100644 hw/i386/x86-cpu.c
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index c2062db13f5..b006f16b8d3 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -21,6 +21,7 @@
#include "exec/memory.h"
#include "hw/boards.h"
+#include "hw/i386/topology.h"
#include "hw/intc/ioapic.h"
#include "hw/isa/isa.h"
#include "qom/object.h"
@@ -109,12 +110,11 @@ struct X86MachineState {
#define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86")
OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE)
-uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
+void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
+uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
unsigned int cpu_index);
-void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
-CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
new file mode 100644
index 00000000000..67b03c913a5
--- /dev/null
+++ b/hw/i386/x86-common.c
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2019, 2024 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/cutils.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+#include "qapi/error.h"
+#include "sysemu/numa.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/xen.h"
+#include "trace.h"
+
+#include "hw/i386/x86.h"
+#include "target/i386/cpu.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "target/i386/sev.h"
+
+#include "hw/acpi/cpu_hotplug.h"
+#include "hw/irq.h"
+#include "hw/loader.h"
+#include "multiboot.h"
+#include "elf.h"
+#include "standard-headers/asm-x86/bootparam.h"
+#include CONFIG_DEVICES
+#include "kvm/kvm_i386.h"
+
+#ifdef CONFIG_XEN_EMU
+#include "hw/xen/xen.h"
+#include "hw/i386/kvm/xen_evtchn.h"
+#endif
+
+/* Physical Address of PVH entry point read from kernel ELF NOTE */
+static size_t pvh_start_addr;
+
+static void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
+{
+ Object *cpu = object_new(MACHINE(x86ms)->cpu_type);
+
+ if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) {
+ goto out;
+ }
+ qdev_realize(DEVICE(cpu), NULL, errp);
+
+out:
+ object_unref(cpu);
+}
+
+void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
+{
+ int i;
+ const CPUArchIdList *possible_cpus;
+ MachineState *ms = MACHINE(x86ms);
+ MachineClass *mc = MACHINE_GET_CLASS(x86ms);
+
+ x86_cpu_set_default_version(default_cpu_version);
+
+ /*
+ * Calculates the limit to CPU APIC ID values
+ *
+ * Limit for the APIC ID value, so that all
+ * CPU APIC IDs are < x86ms->apic_id_limit.
+ *
+ * This is used for FW_CFG_MAX_CPUS. See comments on fw_cfg_arch_create().
+ */
+ x86ms->apic_id_limit = x86_cpu_apic_id_from_index(x86ms,
+ ms->smp.max_cpus - 1) + 1;
+
+ /*
+ * Can we support APIC ID 255 or higher? With KVM, that requires
+ * both in-kernel lapic and X2APIC userspace API.
+ *
+ * kvm_enabled() must go first to ensure that kvm_* references are
+ * not emitted for the linker to consume (kvm_enabled() is
+ * a literal `0` in configurations where kvm_* aren't defined)
+ */
+ if (kvm_enabled() && x86ms->apic_id_limit > 255 &&
+ kvm_irqchip_in_kernel() && !kvm_enable_x2apic()) {
+ error_report("current -smp configuration requires kernel "
+ "irqchip and X2APIC API support.");
+ exit(EXIT_FAILURE);
+ }
+
+ if (kvm_enabled()) {
+ kvm_set_max_apic_id(x86ms->apic_id_limit);
+ }
+
+ if (!kvm_irqchip_in_kernel()) {
+ apic_set_max_apic_id(x86ms->apic_id_limit);
+ }
+
+ possible_cpus = mc->possible_cpu_arch_ids(ms);
+ for (i = 0; i < ms->smp.cpus; i++) {
+ x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal);
+ }
+}
+
+void x86_rtc_set_cpus_count(ISADevice *s, uint16_t cpus_count)
+{
+ MC146818RtcState *rtc = MC146818_RTC(s);
+
+ if (cpus_count > 0xff) {
+ /*
+ * If the number of CPUs can't be represented in 8 bits, the
+ * BIOS must use "FW_CFG_NB_CPUS". Set RTC field to 0 just
+ * to make old BIOSes fail more predictably.
+ */
+ mc146818rtc_set_cmos_data(rtc, 0x5f, 0);
+ } else {
+ mc146818rtc_set_cmos_data(rtc, 0x5f, cpus_count - 1);
+ }
+}
+
+static int x86_apic_cmp(const void *a, const void *b)
+{
+ CPUArchId *apic_a = (CPUArchId *)a;
+ CPUArchId *apic_b = (CPUArchId *)b;
+
+ return apic_a->arch_id - apic_b->arch_id;
+}
+
+/*
+ * returns pointer to CPUArchId descriptor that matches CPU's apic_id
+ * in ms->possible_cpus->cpus, if ms->possible_cpus->cpus has no
+ * entry corresponding to CPU's apic_id returns NULL.
+ */
+static CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
+{
+ CPUArchId apic_id, *found_cpu;
+
+ apic_id.arch_id = id;
+ found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus,
+ ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
+ x86_apic_cmp);
+ if (found_cpu && idx) {
+ *idx = found_cpu - ms->possible_cpus->cpus;
+ }
+ return found_cpu;
+}
+
+void x86_cpu_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ CPUArchId *found_cpu;
+ Error *local_err = NULL;
+ X86CPU *cpu = X86_CPU(dev);
+ X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
+
+ if (x86ms->acpi_dev) {
+ hotplug_handler_plug(x86ms->acpi_dev, dev, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ }
+
+ /* increment the number of CPUs */
+ x86ms->boot_cpus++;
+ if (x86ms->rtc) {
+ x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
+ }
+ if (x86ms->fw_cfg) {
+ fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus);
+ }
+
+ found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL);
+ found_cpu->cpu = CPU(dev);
+out:
+ error_propagate(errp, local_err);
+}
+
+void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ int idx = -1;
+ X86CPU *cpu = X86_CPU(dev);
+ X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
+
+ if (!x86ms->acpi_dev) {
+ error_setg(errp, "CPU hot unplug not supported without ACPI");
+ return;
+ }
+
+ x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx);
+ assert(idx != -1);
+ if (idx == 0) {
+ error_setg(errp, "Boot CPU is unpluggable");
+ return;
+ }
+
+ hotplug_handler_unplug_request(x86ms->acpi_dev, dev,
+ errp);
+}
+
+void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ CPUArchId *found_cpu;
+ Error *local_err = NULL;
+ X86CPU *cpu = X86_CPU(dev);
+ X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
+
+ hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
+ found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL);
+ found_cpu->cpu = NULL;
+ qdev_unrealize(dev);
+
+ /* decrement the number of CPUs */
+ x86ms->boot_cpus--;
+ /* Update the number of CPUs in CMOS */
+ x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
+ fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus);
+ out:
+ error_propagate(errp, local_err);
+}
+
+void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ int idx;
+ CPUState *cs;
+ CPUArchId *cpu_slot;
+ X86CPUTopoIDs topo_ids;
+ X86CPU *cpu = X86_CPU(dev);
+ CPUX86State *env = &cpu->env;
+ MachineState *ms = MACHINE(hotplug_dev);
+ X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
+ unsigned int smp_cores = ms->smp.cores;
+ unsigned int smp_threads = ms->smp.threads;
+ X86CPUTopoInfo topo_info;
+
+ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
+ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
+ ms->cpu_type);
+ return;
+ }
+
+ if (x86ms->acpi_dev) {
+ Error *local_err = NULL;
+
+ hotplug_handler_pre_plug(HOTPLUG_HANDLER(x86ms->acpi_dev), dev,
+ &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+ init_topo_info(&topo_info, x86ms);
+
+ env->nr_dies = ms->smp.dies;
+
+ /*
+ * If APIC ID is not set,
+ * set it based on socket/die/core/thread properties.
+ */
+ if (cpu->apic_id == UNASSIGNED_APIC_ID) {
+ int max_socket = (ms->smp.max_cpus - 1) /
+ smp_threads / smp_cores / ms->smp.dies;
+
+ /*
+ * die-id was optional in QEMU 4.0 and older, so keep it optional
+ * if there's only one die per socket.
+ */
+ if (cpu->die_id < 0 && ms->smp.dies == 1) {
+ cpu->die_id = 0;
+ }
+
+ if (cpu->socket_id < 0) {
+ error_setg(errp, "CPU socket-id is not set");
+ return;
+ } else if (cpu->socket_id > max_socket) {
+ error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u",
+ cpu->socket_id, max_socket);
+ return;
+ }
+ if (cpu->die_id < 0) {
+ error_setg(errp, "CPU die-id is not set");
+ return;
+ } else if (cpu->die_id > ms->smp.dies - 1) {
+ error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u",
+ cpu->die_id, ms->smp.dies - 1);
+ return;
+ }
+ if (cpu->core_id < 0) {
+ error_setg(errp, "CPU core-id is not set");
+ return;
+ } else if (cpu->core_id > (smp_cores - 1)) {
+ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u",
+ cpu->core_id, smp_cores - 1);
+ return;
+ }
+ if (cpu->thread_id < 0) {
+ error_setg(errp, "CPU thread-id is not set");
+ return;
+ } else if (cpu->thread_id > (smp_threads - 1)) {
+ error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u",
+ cpu->thread_id, smp_threads - 1);
+ return;
+ }
+
+ topo_ids.pkg_id = cpu->socket_id;
+ topo_ids.die_id = cpu->die_id;
+ topo_ids.core_id = cpu->core_id;
+ topo_ids.smt_id = cpu->thread_id;
+ cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids);
+ }
+
+ cpu_slot = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx);
+ if (!cpu_slot) {
+ x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
+ error_setg(errp,
+ "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
+ " APIC ID %" PRIu32 ", valid index range 0:%d",
+ topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id,
+ cpu->apic_id, ms->possible_cpus->len - 1);
+ return;
+ }
+
+ if (cpu_slot->cpu) {
+ error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists",
+ idx, cpu->apic_id);
+ return;
+ }
+
+ /* if 'address' properties socket-id/core-id/thread-id are not set, set them
+ * so that machine_query_hotpluggable_cpus would show correct values
+ */
+ /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn()
+ * once -smp refactoring is complete and there will be CPU private
+ * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
+ x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
+ if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) {
+ error_setg(errp, "property socket-id: %u doesn't match set apic-id:"
+ " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id,
+ topo_ids.pkg_id);
+ return;
+ }
+ cpu->socket_id = topo_ids.pkg_id;
+
+ if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) {
+ error_setg(errp, "property die-id: %u doesn't match set apic-id:"
+ " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id);
+ return;
+ }
+ cpu->die_id = topo_ids.die_id;
+
+ if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) {
+ error_setg(errp, "property core-id: %u doesn't match set apic-id:"
+ " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id,
+ topo_ids.core_id);
+ return;
+ }
+ cpu->core_id = topo_ids.core_id;
+
+ if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) {
+ error_setg(errp, "property thread-id: %u doesn't match set apic-id:"
+ " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id,
+ topo_ids.smt_id);
+ return;
+ }
+ cpu->thread_id = topo_ids.smt_id;
+
+ /*
+ * kvm_enabled() must go first to ensure that kvm_* references are
+ * not emitted for the linker to consume (kvm_enabled() is
+ * a literal `0` in configurations where kvm_* aren't defined)
+ */
+ if (kvm_enabled() && hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
+ !kvm_hv_vpindex_settable()) {
+ error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
+ return;
+ }
+
+ cs = CPU(cpu);
+ cs->cpu_index = idx;
+
+ numa_cpu_pre_plug(cpu_slot, dev, errp);
+}
+
+static long get_file_size(FILE *f)
+{
+ long where, size;
+
+ /* XXX: on Unix systems, using fstat() probably makes more sense */
+
+ where = ftell(f);
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ fseek(f, where, SEEK_SET);
+
+ return size;
+}
+
+void gsi_handler(void *opaque, int n, int level)
+{
+ GSIState *s = opaque;
+
+ trace_x86_gsi_interrupt(n, level);
+ switch (n) {
+ case 0 ... ISA_NUM_IRQS - 1:
+ if (s->i8259_irq[n]) {
+ /* Under KVM, Kernel will forward to both PIC and IOAPIC */
+ qemu_set_irq(s->i8259_irq[n], level);
+ }
+ /* fall through */
+ case ISA_NUM_IRQS ... IOAPIC_NUM_PINS - 1:
+#ifdef CONFIG_XEN_EMU
+ /*
+ * Xen delivers the GSI to the Legacy PIC (not that Legacy PIC
+ * routing actually works properly under Xen). And then to
+ * *either* the PIRQ handling or the I/OAPIC depending on
+ * whether the former wants it.
+ */
+ if (xen_mode == XEN_EMULATE && xen_evtchn_set_gsi(n, level)) {
+ break;
+ }
+#endif
+ qemu_set_irq(s->ioapic_irq[n], level);
+ break;
+ case IO_APIC_SECONDARY_IRQBASE
+ ... IO_APIC_SECONDARY_IRQBASE + IOAPIC_NUM_PINS - 1:
+ qemu_set_irq(s->ioapic2_irq[n - IO_APIC_SECONDARY_IRQBASE], level);
+ break;
+ }
+}
+
+void ioapic_init_gsi(GSIState *gsi_state, Object *parent)
+{
+ DeviceState *dev;
+ SysBusDevice *d;
+ unsigned int i;
+
+ assert(parent);
+ if (kvm_ioapic_in_kernel()) {
+ dev = qdev_new(TYPE_KVM_IOAPIC);
+ } else {
+ dev = qdev_new(TYPE_IOAPIC);
+ }
+ object_property_add_child(parent, "ioapic", OBJECT(dev));
+ d = SYS_BUS_DEVICE(dev);
+ sysbus_realize_and_unref(d, &error_fatal);
+ sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
+
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
+ }
+}
+
+DeviceState *ioapic_init_secondary(GSIState *gsi_state)
+{
+ DeviceState *dev;
+ SysBusDevice *d;
+ unsigned int i;
+
+ dev = qdev_new(TYPE_IOAPIC);
+ d = SYS_BUS_DEVICE(dev);
+ sysbus_realize_and_unref(d, &error_fatal);
+ sysbus_mmio_map(d, 0, IO_APIC_SECONDARY_ADDRESS);
+
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ gsi_state->ioapic2_irq[i] = qdev_get_gpio_in(dev, i);
+ }
+ return dev;
+}
+
+/*
+ * The entry point into the kernel for PVH boot is different from
+ * the native entry point. The PVH entry is defined by the x86/HVM
+ * direct boot ABI and is available in an ELFNOTE in the kernel binary.
+ *
+ * This function is passed to load_elf() when it is called from
+ * load_elfboot() which then additionally checks for an ELF Note of
+ * type XEN_ELFNOTE_PHYS32_ENTRY and passes it to this function to
+ * parse the PVH entry address from the ELF Note.
+ *
+ * Due to trickery in elf_opts.h, load_elf() is actually available as
+ * load_elf32() or load_elf64() and this routine needs to be able
+ * to deal with being called as 32 or 64 bit.
+ *
+ * The address of the PVH entry point is saved to the 'pvh_start_addr'
+ * global variable. (although the entry point is 32-bit, the kernel
+ * binary can be either 32-bit or 64-bit).
+ */
+static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
+{
+ size_t *elf_note_data_addr;
+
+ /* Check if ELF Note header passed in is valid */
+ if (arg1 == NULL) {
+ return 0;
+ }
+
+ if (is64) {
+ struct elf64_note *nhdr64 = (struct elf64_note *)arg1;
+ uint64_t nhdr_size64 = sizeof(struct elf64_note);
+ uint64_t phdr_align = *(uint64_t *)arg2;
+ uint64_t nhdr_namesz = nhdr64->n_namesz;
+
+ elf_note_data_addr =
+ ((void *)nhdr64) + nhdr_size64 +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
+
+ pvh_start_addr = *elf_note_data_addr;
+ } else {
+ struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
+ uint32_t nhdr_size32 = sizeof(struct elf32_note);
+ uint32_t phdr_align = *(uint32_t *)arg2;
+ uint32_t nhdr_namesz = nhdr32->n_namesz;
+
+ elf_note_data_addr =
+ ((void *)nhdr32) + nhdr_size32 +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
+
+ pvh_start_addr = *(uint32_t *)elf_note_data_addr;
+ }
+
+ return pvh_start_addr;
+}
+
+static bool load_elfboot(const char *kernel_filename,
+ int kernel_file_size,
+ uint8_t *header,
+ size_t pvh_xen_start_addr,
+ FWCfgState *fw_cfg)
+{
+ uint32_t flags = 0;
+ uint32_t mh_load_addr = 0;
+ uint32_t elf_kernel_size = 0;
+ uint64_t elf_entry;
+ uint64_t elf_low, elf_high;
+ int kernel_size;
+
+ if (ldl_p(header) != 0x464c457f) {
+ return false; /* no elfboot */
+ }
+
+ bool elf_is64 = header[EI_CLASS] == ELFCLASS64;
+ flags = elf_is64 ?
+ ((Elf64_Ehdr *)header)->e_flags : ((Elf32_Ehdr *)header)->e_flags;
+
+ if (flags & 0x00010004) { /* LOAD_ELF_HEADER_HAS_ADDR */
+ error_report("elfboot unsupported flags = %x", flags);
+ exit(1);
+ }
+
+ uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
+ kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
+ NULL, &elf_note_type, &elf_entry,
+ &elf_low, &elf_high, NULL, 0, I386_ELF_MACHINE,
+ 0, 0);
+
+ if (kernel_size < 0) {
+ error_report("Error while loading elf kernel");
+ exit(1);
+ }
+ mh_load_addr = elf_low;
+ elf_kernel_size = elf_high - elf_low;
+
+ if (pvh_start_addr == 0) {
+ error_report("Error loading uncompressed kernel without PVH ELF Note");
+ exit(1);
+ }
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, pvh_start_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, elf_kernel_size);
+
+ return true;
+}
+
+void x86_load_linux(X86MachineState *x86ms,
+ FWCfgState *fw_cfg,
+ int acpi_data_size,
+ bool pvh_enabled)
+{
+ bool linuxboot_dma_enabled = X86_MACHINE_GET_CLASS(x86ms)->fwcfg_dma_enabled;
+ uint16_t protocol;
+ int setup_size, kernel_size, cmdline_size;
+ int dtb_size, setup_data_offset;
+ uint32_t initrd_max;
+ uint8_t header[8192], *setup, *kernel;
+ hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
+ FILE *f;
+ char *vmode;
+ MachineState *machine = MACHINE(x86ms);
+ struct setup_data *setup_data;
+ const char *kernel_filename = machine->kernel_filename;
+ const char *initrd_filename = machine->initrd_filename;
+ const char *dtb_filename = machine->dtb;
+ const char *kernel_cmdline = machine->kernel_cmdline;
+ SevKernelLoaderContext sev_load_ctx = {};
+
+ /* Align to 16 bytes as a paranoia measure */
+ cmdline_size = (strlen(kernel_cmdline) + 16) & ~15;
+
+ /* load the kernel header */
+ f = fopen(kernel_filename, "rb");
+ if (!f) {
+ fprintf(stderr, "qemu: could not open kernel file '%s': %s\n",
+ kernel_filename, strerror(errno));
+ exit(1);
+ }
+
+ kernel_size = get_file_size(f);
+ if (!kernel_size ||
+ fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
+ MIN(ARRAY_SIZE(header), kernel_size)) {
+ fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
+ kernel_filename, strerror(errno));
+ exit(1);
+ }
+
+ /* kernel protocol version */
+ if (ldl_p(header + 0x202) == 0x53726448) {
+ protocol = lduw_p(header + 0x206);
+ } else {
+ /*
+ * This could be a multiboot kernel. If it is, let's stop treating it
+ * like a Linux kernel.
+ * Note: some multiboot images could be in the ELF format (the same of
+ * PVH), so we try multiboot first since we check the multiboot magic
+ * header before to load it.
+ */
+ if (load_multiboot(x86ms, fw_cfg, f, kernel_filename, initrd_filename,
+ kernel_cmdline, kernel_size, header)) {
+ return;
+ }
+ /*
+ * Check if the file is an uncompressed kernel file (ELF) and load it,
+ * saving the PVH entry point used by the x86/HVM direct boot ABI.
+ * If load_elfboot() is successful, populate the fw_cfg info.
+ */
+ if (pvh_enabled &&
+ load_elfboot(kernel_filename, kernel_size,
+ header, pvh_start_addr, fw_cfg)) {
+ fclose(f);
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+ strlen(kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, sizeof(header));
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA,
+ header, sizeof(header));
+
+ /* load initrd */
+ if (initrd_filename) {
+ GMappedFile *mapped_file;
+ gsize initrd_size;
+ gchar *initrd_data;
+ GError *gerr = NULL;
+
+ mapped_file = g_mapped_file_new(initrd_filename, false, &gerr);
+ if (!mapped_file) {
+ fprintf(stderr, "qemu: error reading initrd %s: %s\n",
+ initrd_filename, gerr->message);
+ exit(1);
+ }
+ x86ms->initrd_mapped_file = mapped_file;
+
+ initrd_data = g_mapped_file_get_contents(mapped_file);
+ initrd_size = g_mapped_file_get_length(mapped_file);
+ initrd_max = x86ms->below_4g_mem_size - acpi_data_size - 1;
+ if (initrd_size >= initrd_max) {
+ fprintf(stderr, "qemu: initrd is too large, cannot support."
+ "(max: %"PRIu32", need %"PRId64")\n",
+ initrd_max, (uint64_t)initrd_size);
+ exit(1);
+ }
+
+ initrd_addr = (initrd_max - initrd_size) & ~4095;
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data,
+ initrd_size);
+ }
+
+ option_rom[nb_option_roms].bootindex = 0;
+ option_rom[nb_option_roms].name = "pvh.bin";
+ nb_option_roms++;
+
+ return;
+ }
+ protocol = 0;
+ }
+
+ if (protocol < 0x200 || !(header[0x211] & 0x01)) {
+ /* Low kernel */
+ real_addr = 0x90000;
+ cmdline_addr = 0x9a000 - cmdline_size;
+ prot_addr = 0x10000;
+ } else if (protocol < 0x202) {
+ /* High but ancient kernel */
+ real_addr = 0x90000;
+ cmdline_addr = 0x9a000 - cmdline_size;
+ prot_addr = 0x100000;
+ } else {
+ /* High and recent kernel */
+ real_addr = 0x10000;
+ cmdline_addr = 0x20000;
+ prot_addr = 0x100000;
+ }
+
+ /* highest address for loading the initrd */
+ if (protocol >= 0x20c &&
+ lduw_p(header + 0x236) & XLF_CAN_BE_LOADED_ABOVE_4G) {
+ /*
+ * Linux has supported initrd up to 4 GB for a very long time (2007,
+ * long before XLF_CAN_BE_LOADED_ABOVE_4G which was added in 2013),
+ * though it only sets initrd_max to 2 GB to "work around bootloader
+ * bugs". Luckily, QEMU firmware(which does something like bootloader)
+ * has supported this.
+ *
+ * It's believed that if XLF_CAN_BE_LOADED_ABOVE_4G is set, initrd can
+ * be loaded into any address.
+ *
+ * In addition, initrd_max is uint32_t simply because QEMU doesn't
+ * support the 64-bit boot protocol (specifically the ext_ramdisk_image
+ * field).
+ *
+ * Therefore here just limit initrd_max to UINT32_MAX simply as well.
+ */
+ initrd_max = UINT32_MAX;
+ } else if (protocol >= 0x203) {
+ initrd_max = ldl_p(header + 0x22c);
+ } else {
+ initrd_max = 0x37ffffff;
+ }
+
+ if (initrd_max >= x86ms->below_4g_mem_size - acpi_data_size) {
+ initrd_max = x86ms->below_4g_mem_size - acpi_data_size - 1;
+ }
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+ sev_load_ctx.cmdline_data = (char *)kernel_cmdline;
+ sev_load_ctx.cmdline_size = strlen(kernel_cmdline) + 1;
+
+ if (protocol >= 0x202) {
+ stl_p(header + 0x228, cmdline_addr);
+ } else {
+ stw_p(header + 0x20, 0xA33F);
+ stw_p(header + 0x22, cmdline_addr - real_addr);
+ }
+
+ /* handle vga= parameter */
+ vmode = strstr(kernel_cmdline, "vga=");
+ if (vmode) {
+ unsigned int video_mode;
+ const char *end;
+ int ret;
+ /* skip "vga=" */
+ vmode += 4;
+ if (!strncmp(vmode, "normal", 6)) {
+ video_mode = 0xffff;
+ } else if (!strncmp(vmode, "ext", 3)) {
+ video_mode = 0xfffe;
+ } else if (!strncmp(vmode, "ask", 3)) {
+ video_mode = 0xfffd;
+ } else {
+ ret = qemu_strtoui(vmode, &end, 0, &video_mode);
+ if (ret != 0 || (*end && *end != ' ')) {
+ fprintf(stderr, "qemu: invalid 'vga=' kernel parameter.\n");
+ exit(1);
+ }
+ }
+ stw_p(header + 0x1fa, video_mode);
+ }
+
+ /* loader type */
+ /*
+ * High nybble = B reserved for QEMU; low nybble is revision number.
+ * If this code is substantially changed, you may want to consider
+ * incrementing the revision.
+ */
+ if (protocol >= 0x200) {
+ header[0x210] = 0xB0;
+ }
+ /* heap */
+ if (protocol >= 0x201) {
+ header[0x211] |= 0x80; /* CAN_USE_HEAP */
+ stw_p(header + 0x224, cmdline_addr - real_addr - 0x200);
+ }
+
+ /* load initrd */
+ if (initrd_filename) {
+ GMappedFile *mapped_file;
+ gsize initrd_size;
+ gchar *initrd_data;
+ GError *gerr = NULL;
+
+ if (protocol < 0x200) {
+ fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
+ exit(1);
+ }
+
+ mapped_file = g_mapped_file_new(initrd_filename, false, &gerr);
+ if (!mapped_file) {
+ fprintf(stderr, "qemu: error reading initrd %s: %s\n",
+ initrd_filename, gerr->message);
+ exit(1);
+ }
+ x86ms->initrd_mapped_file = mapped_file;
+
+ initrd_data = g_mapped_file_get_contents(mapped_file);
+ initrd_size = g_mapped_file_get_length(mapped_file);
+ if (initrd_size >= initrd_max) {
+ fprintf(stderr, "qemu: initrd is too large, cannot support."
+ "(max: %"PRIu32", need %"PRId64")\n",
+ initrd_max, (uint64_t)initrd_size);
+ exit(1);
+ }
+
+ initrd_addr = (initrd_max - initrd_size) & ~4095;
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
+ sev_load_ctx.initrd_data = initrd_data;
+ sev_load_ctx.initrd_size = initrd_size;
+
+ stl_p(header + 0x218, initrd_addr);
+ stl_p(header + 0x21c, initrd_size);
+ }
+
+ /* load kernel and setup */
+ setup_size = header[0x1f1];
+ if (setup_size == 0) {
+ setup_size = 4;
+ }
+ setup_size = (setup_size + 1) * 512;
+ if (setup_size > kernel_size) {
+ fprintf(stderr, "qemu: invalid kernel header\n");
+ exit(1);
+ }
+ kernel_size -= setup_size;
+
+ setup = g_malloc(setup_size);
+ kernel = g_malloc(kernel_size);
+ fseek(f, 0, SEEK_SET);
+ if (fread(setup, 1, setup_size, f) != setup_size) {
+ fprintf(stderr, "fread() failed\n");
+ exit(1);
+ }
+ if (fread(kernel, 1, kernel_size, f) != kernel_size) {
+ fprintf(stderr, "fread() failed\n");
+ exit(1);
+ }
+ fclose(f);
+
+ /* append dtb to kernel */
+ if (dtb_filename) {
+ if (protocol < 0x209) {
+ fprintf(stderr, "qemu: Linux kernel too old to load a dtb\n");
+ exit(1);
+ }
+
+ dtb_size = get_image_size(dtb_filename);
+ if (dtb_size <= 0) {
+ fprintf(stderr, "qemu: error reading dtb %s: %s\n",
+ dtb_filename, strerror(errno));
+ exit(1);
+ }
+
+ setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
+ kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
+ kernel = g_realloc(kernel, kernel_size);
+
+ stq_p(header + 0x250, prot_addr + setup_data_offset);
+
+ setup_data = (struct setup_data *)(kernel + setup_data_offset);
+ setup_data->next = 0;
+ setup_data->type = cpu_to_le32(SETUP_DTB);
+ setup_data->len = cpu_to_le32(dtb_size);
+
+ load_image_size(dtb_filename, setup_data->data, dtb_size);
+ }
+
+ /*
+ * If we're starting an encrypted VM, it will be OVMF based, which uses the
+ * efi stub for booting and doesn't require any values to be placed in the
+ * kernel header. We therefore don't update the header so the hash of the
+ * kernel on the other side of the fw_cfg interface matches the hash of the
+ * file the user passed in.
+ */
+ if (!sev_enabled()) {
+ memcpy(setup, header, MIN(sizeof(header), setup_size));
+ }
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+ sev_load_ctx.kernel_data = (char *)kernel;
+ sev_load_ctx.kernel_size = kernel_size;
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
+ sev_load_ctx.setup_data = (char *)setup;
+ sev_load_ctx.setup_size = setup_size;
+
+ if (sev_enabled()) {
+ sev_add_kernel_loader_hashes(&sev_load_ctx, &error_fatal);
+ }
+
+ option_rom[nb_option_roms].bootindex = 0;
+ option_rom[nb_option_roms].name = "linuxboot.bin";
+ if (linuxboot_dma_enabled && fw_cfg_dma_enabled(fw_cfg)) {
+ option_rom[nb_option_roms].name = "linuxboot_dma.bin";
+ }
+ nb_option_roms++;
+}
+
+void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
+ MemoryRegion *bios, bool read_only)
+{
+ uint64_t bios_size = memory_region_size(bios);
+ uint64_t isa_bios_size = MIN(bios_size, 128 * KiB);
+
+ memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
+ bios_size - isa_bios_size, isa_bios_size);
+ memory_region_add_subregion_overlap(isa_memory, 1 * MiB - isa_bios_size,
+ isa_bios, 1);
+ memory_region_set_readonly(isa_bios, read_only);
+}
+
+void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
+ MemoryRegion *rom_memory, bool isapc_ram_fw)
+{
+ const char *bios_name;
+ char *filename;
+ int bios_size;
+ ssize_t ret;
+
+ /* BIOS load */
+ bios_name = MACHINE(x86ms)->firmware ?: default_firmware;
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ if (filename) {
+ bios_size = get_image_size(filename);
+ } else {
+ bios_size = -1;
+ }
+ if (bios_size <= 0 ||
+ (bios_size % 65536) != 0) {
+ goto bios_error;
+ }
+ memory_region_init_ram(&x86ms->bios, NULL, "pc.bios", bios_size,
+ &error_fatal);
+ if (sev_enabled()) {
+ /*
+ * The concept of a "reset" simply doesn't exist for
+ * confidential computing guests, we have to destroy and
+ * re-launch them instead. So there is no need to register
+ * the firmware as rom to properly re-initialize on reset.
+ * Just go for a straight file load instead.
+ */
+ void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
+ load_image_size(filename, ptr, bios_size);
+ x86_firmware_configure(ptr, bios_size);
+ } else {
+ memory_region_set_readonly(&x86ms->bios, !isapc_ram_fw);
+ ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
+ if (ret != 0) {
+ goto bios_error;
+ }
+ }
+ g_free(filename);
+
+ /* map the last 128KB of the BIOS in ISA space */
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
+ !isapc_ram_fw);
+
+ /* map all the bios at the top of memory */
+ memory_region_add_subregion(rom_memory,
+ (uint32_t)(-bios_size),
+ &x86ms->bios);
+ return;
+
+bios_error:
+ fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
+ exit(1);
+}
diff --git a/hw/i386/x86-cpu.c b/hw/i386/x86-cpu.c
new file mode 100644
index 00000000000..ab2920522d1
--- /dev/null
+++ b/hw/i386/x86-cpu.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2019, 2024 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "sysemu/whpx.h"
+#include "sysemu/cpu-timers.h"
+#include "trace.h"
+
+#include "hw/i386/x86.h"
+#include "target/i386/cpu.h"
+#include "hw/intc/i8259.h"
+#include "hw/irq.h"
+#include "sysemu/kvm.h"
+
+/* TSC handling */
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+ return cpus_get_elapsed_ticks();
+}
+
+/* IRQ handling */
+static void pic_irq_request(void *opaque, int irq, int level)
+{
+ CPUState *cs = first_cpu;
+ X86CPU *cpu = X86_CPU(cs);
+
+ trace_x86_pic_interrupt(irq, level);
+ if (cpu_is_apic_enabled(cpu->apic_state) && !kvm_irqchip_in_kernel() &&
+ !whpx_apic_in_platform()) {
+ CPU_FOREACH(cs) {
+ cpu = X86_CPU(cs);
+ if (apic_accept_pic_intr(cpu->apic_state)) {
+ apic_deliver_pic_intr(cpu->apic_state, level);
+ }
+ }
+ } else {
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
+ }
+}
+
+qemu_irq x86_allocate_cpu_irq(void)
+{
+ return qemu_allocate_irq(pic_irq_request, NULL, 0);
+}
+
+int cpu_get_pic_interrupt(CPUX86State *env)
+{
+ X86CPU *cpu = env_archcpu(env);
+ int intno;
+
+ if (!kvm_irqchip_in_kernel() && !whpx_apic_in_platform()) {
+ intno = apic_get_interrupt(cpu->apic_state);
+ if (intno >= 0) {
+ return intno;
+ }
+ /* read the irq from the PIC */
+ if (!apic_accept_pic_intr(cpu->apic_state)) {
+ return -1;
+ }
+ }
+
+ intno = pic_read_irq(isa_pic);
+ return intno;
+}
+
+DeviceState *cpu_get_current_apic(void)
+{
+ if (current_cpu) {
+ X86CPU *cpu = X86_CPU(current_cpu);
+ return cpu->apic_state;
+ } else {
+ return NULL;
+ }
+}
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index fcef652c1e3..0b5cc599566 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -22,52 +22,25 @@
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
-#include "qemu/option.h"
-#include "qemu/cutils.h"
#include "qemu/units.h"
-#include "qemu/datadir.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-common.h"
-#include "qapi/clone-visitor.h"
#include "qapi/qapi-visit-machine.h"
#include "qapi/visitor.h"
#include "sysemu/qtest.h"
-#include "sysemu/whpx.h"
#include "sysemu/numa.h"
-#include "sysemu/replay.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/cpu-timers.h"
-#include "sysemu/xen.h"
#include "trace.h"
+#include "hw/acpi/aml-build.h"
#include "hw/i386/x86.h"
-#include "target/i386/cpu.h"
#include "hw/i386/topology.h"
-#include "hw/i386/fw_cfg.h"
-#include "hw/intc/i8259.h"
-#include "hw/rtc/mc146818rtc.h"
-#include "target/i386/sev.h"
-#include "hw/acpi/cpu_hotplug.h"
-#include "hw/irq.h"
#include "hw/nmi.h"
-#include "hw/loader.h"
-#include "multiboot.h"
-#include "elf.h"
-#include "standard-headers/asm-x86/bootparam.h"
-#include CONFIG_DEVICES
#include "kvm/kvm_i386.h"
-#ifdef CONFIG_XEN_EMU
-#include "hw/xen/xen.h"
-#include "hw/i386/kvm/xen_evtchn.h"
-#endif
-/* Physical Address of PVH entry point read from kernel ELF NOTE */
-static size_t pvh_start_addr;
-
-static void init_topo_info(X86CPUTopoInfo *topo_info,
- const X86MachineState *x86ms)
+void init_topo_info(X86CPUTopoInfo *topo_info,
+ const X86MachineState *x86ms)
{
MachineState *ms = MACHINE(x86ms);
@@ -94,355 +67,6 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
return x86_apicid_from_cpu_idx(&topo_info, cpu_index);
}
-
-void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
-{
- Object *cpu = object_new(MACHINE(x86ms)->cpu_type);
-
- if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) {
- goto out;
- }
- qdev_realize(DEVICE(cpu), NULL, errp);
-
-out:
- object_unref(cpu);
-}
-
-void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
-{
- int i;
- const CPUArchIdList *possible_cpus;
- MachineState *ms = MACHINE(x86ms);
- MachineClass *mc = MACHINE_GET_CLASS(x86ms);
-
- x86_cpu_set_default_version(default_cpu_version);
-
- /*
- * Calculates the limit to CPU APIC ID values
- *
- * Limit for the APIC ID value, so that all
- * CPU APIC IDs are < x86ms->apic_id_limit.
- *
- * This is used for FW_CFG_MAX_CPUS. See comments on fw_cfg_arch_create().
- */
- x86ms->apic_id_limit = x86_cpu_apic_id_from_index(x86ms,
- ms->smp.max_cpus - 1) + 1;
-
- /*
- * Can we support APIC ID 255 or higher? With KVM, that requires
- * both in-kernel lapic and X2APIC userspace API.
- *
- * kvm_enabled() must go first to ensure that kvm_* references are
- * not emitted for the linker to consume (kvm_enabled() is
- * a literal `0` in configurations where kvm_* aren't defined)
- */
- if (kvm_enabled() && x86ms->apic_id_limit > 255 &&
- kvm_irqchip_in_kernel() && !kvm_enable_x2apic()) {
- error_report("current -smp configuration requires kernel "
- "irqchip and X2APIC API support.");
- exit(EXIT_FAILURE);
- }
-
- if (kvm_enabled()) {
- kvm_set_max_apic_id(x86ms->apic_id_limit);
- }
-
- if (!kvm_irqchip_in_kernel()) {
- apic_set_max_apic_id(x86ms->apic_id_limit);
- }
-
- possible_cpus = mc->possible_cpu_arch_ids(ms);
- for (i = 0; i < ms->smp.cpus; i++) {
- x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal);
- }
-}
-
-void x86_rtc_set_cpus_count(ISADevice *s, uint16_t cpus_count)
-{
- MC146818RtcState *rtc = MC146818_RTC(s);
-
- if (cpus_count > 0xff) {
- /*
- * If the number of CPUs can't be represented in 8 bits, the
- * BIOS must use "FW_CFG_NB_CPUS". Set RTC field to 0 just
- * to make old BIOSes fail more predictably.
- */
- mc146818rtc_set_cmos_data(rtc, 0x5f, 0);
- } else {
- mc146818rtc_set_cmos_data(rtc, 0x5f, cpus_count - 1);
- }
-}
-
-static int x86_apic_cmp(const void *a, const void *b)
-{
- CPUArchId *apic_a = (CPUArchId *)a;
- CPUArchId *apic_b = (CPUArchId *)b;
-
- return apic_a->arch_id - apic_b->arch_id;
-}
-
-/*
- * returns pointer to CPUArchId descriptor that matches CPU's apic_id
- * in ms->possible_cpus->cpus, if ms->possible_cpus->cpus has no
- * entry corresponding to CPU's apic_id returns NULL.
- */
-CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
-{
- CPUArchId apic_id, *found_cpu;
-
- apic_id.arch_id = id;
- found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus,
- ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
- x86_apic_cmp);
- if (found_cpu && idx) {
- *idx = found_cpu - ms->possible_cpus->cpus;
- }
- return found_cpu;
-}
-
-void x86_cpu_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- CPUArchId *found_cpu;
- Error *local_err = NULL;
- X86CPU *cpu = X86_CPU(dev);
- X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
-
- if (x86ms->acpi_dev) {
- hotplug_handler_plug(x86ms->acpi_dev, dev, &local_err);
- if (local_err) {
- goto out;
- }
- }
-
- /* increment the number of CPUs */
- x86ms->boot_cpus++;
- if (x86ms->rtc) {
- x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
- }
- if (x86ms->fw_cfg) {
- fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus);
- }
-
- found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL);
- found_cpu->cpu = CPU(dev);
-out:
- error_propagate(errp, local_err);
-}
-
-void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- int idx = -1;
- X86CPU *cpu = X86_CPU(dev);
- X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
-
- if (!x86ms->acpi_dev) {
- error_setg(errp, "CPU hot unplug not supported without ACPI");
- return;
- }
-
- x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx);
- assert(idx != -1);
- if (idx == 0) {
- error_setg(errp, "Boot CPU is unpluggable");
- return;
- }
-
- hotplug_handler_unplug_request(x86ms->acpi_dev, dev,
- errp);
-}
-
-void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- CPUArchId *found_cpu;
- Error *local_err = NULL;
- X86CPU *cpu = X86_CPU(dev);
- X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
-
- hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err);
- if (local_err) {
- goto out;
- }
-
- found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL);
- found_cpu->cpu = NULL;
- qdev_unrealize(dev);
-
- /* decrement the number of CPUs */
- x86ms->boot_cpus--;
- /* Update the number of CPUs in CMOS */
- x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
- fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus);
- out:
- error_propagate(errp, local_err);
-}
-
-void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- int idx;
- CPUState *cs;
- CPUArchId *cpu_slot;
- X86CPUTopoIDs topo_ids;
- X86CPU *cpu = X86_CPU(dev);
- CPUX86State *env = &cpu->env;
- MachineState *ms = MACHINE(hotplug_dev);
- X86MachineState *x86ms = X86_MACHINE(hotplug_dev);
- unsigned int smp_cores = ms->smp.cores;
- unsigned int smp_threads = ms->smp.threads;
- X86CPUTopoInfo topo_info;
-
- if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
- error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
- ms->cpu_type);
- return;
- }
-
- if (x86ms->acpi_dev) {
- Error *local_err = NULL;
-
- hotplug_handler_pre_plug(HOTPLUG_HANDLER(x86ms->acpi_dev), dev,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- }
-
- init_topo_info(&topo_info, x86ms);
-
- env->nr_dies = ms->smp.dies;
-
- /*
- * If APIC ID is not set,
- * set it based on socket/die/core/thread properties.
- */
- if (cpu->apic_id == UNASSIGNED_APIC_ID) {
- int max_socket = (ms->smp.max_cpus - 1) /
- smp_threads / smp_cores / ms->smp.dies;
-
- /*
- * die-id was optional in QEMU 4.0 and older, so keep it optional
- * if there's only one die per socket.
- */
- if (cpu->die_id < 0 && ms->smp.dies == 1) {
- cpu->die_id = 0;
- }
-
- if (cpu->socket_id < 0) {
- error_setg(errp, "CPU socket-id is not set");
- return;
- } else if (cpu->socket_id > max_socket) {
- error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u",
- cpu->socket_id, max_socket);
- return;
- }
- if (cpu->die_id < 0) {
- error_setg(errp, "CPU die-id is not set");
- return;
- } else if (cpu->die_id > ms->smp.dies - 1) {
- error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u",
- cpu->die_id, ms->smp.dies - 1);
- return;
- }
- if (cpu->core_id < 0) {
- error_setg(errp, "CPU core-id is not set");
- return;
- } else if (cpu->core_id > (smp_cores - 1)) {
- error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u",
- cpu->core_id, smp_cores - 1);
- return;
- }
- if (cpu->thread_id < 0) {
- error_setg(errp, "CPU thread-id is not set");
- return;
- } else if (cpu->thread_id > (smp_threads - 1)) {
- error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u",
- cpu->thread_id, smp_threads - 1);
- return;
- }
-
- topo_ids.pkg_id = cpu->socket_id;
- topo_ids.die_id = cpu->die_id;
- topo_ids.core_id = cpu->core_id;
- topo_ids.smt_id = cpu->thread_id;
- cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids);
- }
-
- cpu_slot = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx);
- if (!cpu_slot) {
- x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
- error_setg(errp,
- "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
- " APIC ID %" PRIu32 ", valid index range 0:%d",
- topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id,
- cpu->apic_id, ms->possible_cpus->len - 1);
- return;
- }
-
- if (cpu_slot->cpu) {
- error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists",
- idx, cpu->apic_id);
- return;
- }
-
- /* if 'address' properties socket-id/core-id/thread-id are not set, set them
- * so that machine_query_hotpluggable_cpus would show correct values
- */
- /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn()
- * once -smp refactoring is complete and there will be CPU private
- * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
- x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids);
- if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) {
- error_setg(errp, "property socket-id: %u doesn't match set apic-id:"
- " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id,
- topo_ids.pkg_id);
- return;
- }
- cpu->socket_id = topo_ids.pkg_id;
-
- if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) {
- error_setg(errp, "property die-id: %u doesn't match set apic-id:"
- " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id);
- return;
- }
- cpu->die_id = topo_ids.die_id;
-
- if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) {
- error_setg(errp, "property core-id: %u doesn't match set apic-id:"
- " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id,
- topo_ids.core_id);
- return;
- }
- cpu->core_id = topo_ids.core_id;
-
- if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) {
- error_setg(errp, "property thread-id: %u doesn't match set apic-id:"
- " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id,
- topo_ids.smt_id);
- return;
- }
- cpu->thread_id = topo_ids.smt_id;
-
- /*
- * kvm_enabled() must go first to ensure that kvm_* references are
- * not emitted for the linker to consume (kvm_enabled() is
- * a literal `0` in configurations where kvm_* aren't defined)
- */
- if (kvm_enabled() && hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
- !kvm_hv_vpindex_settable()) {
- error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
- return;
- }
-
- cs = CPU(cpu);
- cs->cpu_index = idx;
-
- numa_cpu_pre_plug(cpu_slot, dev, errp);
-}
-
static CpuInstanceProperties
x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
{
@@ -528,676 +152,6 @@ static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
}
}
-static long get_file_size(FILE *f)
-{
- long where, size;
-
- /* XXX: on Unix systems, using fstat() probably makes more sense */
-
- where = ftell(f);
- fseek(f, 0, SEEK_END);
- size = ftell(f);
- fseek(f, where, SEEK_SET);
-
- return size;
-}
-
-/* TSC handling */
-uint64_t cpu_get_tsc(CPUX86State *env)
-{
- return cpus_get_elapsed_ticks();
-}
-
-/* IRQ handling */
-static void pic_irq_request(void *opaque, int irq, int level)
-{
- CPUState *cs = first_cpu;
- X86CPU *cpu = X86_CPU(cs);
-
- trace_x86_pic_interrupt(irq, level);
- if (cpu_is_apic_enabled(cpu->apic_state) && !kvm_irqchip_in_kernel() &&
- !whpx_apic_in_platform()) {
- CPU_FOREACH(cs) {
- cpu = X86_CPU(cs);
- if (apic_accept_pic_intr(cpu->apic_state)) {
- apic_deliver_pic_intr(cpu->apic_state, level);
- }
- }
- } else {
- if (level) {
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
- }
- }
-}
-
-qemu_irq x86_allocate_cpu_irq(void)
-{
- return qemu_allocate_irq(pic_irq_request, NULL, 0);
-}
-
-int cpu_get_pic_interrupt(CPUX86State *env)
-{
- X86CPU *cpu = env_archcpu(env);
- int intno;
-
- if (!kvm_irqchip_in_kernel() && !whpx_apic_in_platform()) {
- intno = apic_get_interrupt(cpu->apic_state);
- if (intno >= 0) {
- return intno;
- }
- /* read the irq from the PIC */
- if (!apic_accept_pic_intr(cpu->apic_state)) {
- return -1;
- }
- }
-
- intno = pic_read_irq(isa_pic);
- return intno;
-}
-
-DeviceState *cpu_get_current_apic(void)
-{
- if (current_cpu) {
- X86CPU *cpu = X86_CPU(current_cpu);
- return cpu->apic_state;
- } else {
- return NULL;
- }
-}
-
-void gsi_handler(void *opaque, int n, int level)
-{
- GSIState *s = opaque;
-
- trace_x86_gsi_interrupt(n, level);
- switch (n) {
- case 0 ... ISA_NUM_IRQS - 1:
- if (s->i8259_irq[n]) {
- /* Under KVM, Kernel will forward to both PIC and IOAPIC */
- qemu_set_irq(s->i8259_irq[n], level);
- }
- /* fall through */
- case ISA_NUM_IRQS ... IOAPIC_NUM_PINS - 1:
-#ifdef CONFIG_XEN_EMU
- /*
- * Xen delivers the GSI to the Legacy PIC (not that Legacy PIC
- * routing actually works properly under Xen). And then to
- * *either* the PIRQ handling or the I/OAPIC depending on
- * whether the former wants it.
- */
- if (xen_mode == XEN_EMULATE && xen_evtchn_set_gsi(n, level)) {
- break;
- }
-#endif
- qemu_set_irq(s->ioapic_irq[n], level);
- break;
- case IO_APIC_SECONDARY_IRQBASE
- ... IO_APIC_SECONDARY_IRQBASE + IOAPIC_NUM_PINS - 1:
- qemu_set_irq(s->ioapic2_irq[n - IO_APIC_SECONDARY_IRQBASE], level);
- break;
- }
-}
-
-void ioapic_init_gsi(GSIState *gsi_state, Object *parent)
-{
- DeviceState *dev;
- SysBusDevice *d;
- unsigned int i;
-
- assert(parent);
- if (kvm_ioapic_in_kernel()) {
- dev = qdev_new(TYPE_KVM_IOAPIC);
- } else {
- dev = qdev_new(TYPE_IOAPIC);
- }
- object_property_add_child(parent, "ioapic", OBJECT(dev));
- d = SYS_BUS_DEVICE(dev);
- sysbus_realize_and_unref(d, &error_fatal);
- sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
-
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
- }
-}
-
-DeviceState *ioapic_init_secondary(GSIState *gsi_state)
-{
- DeviceState *dev;
- SysBusDevice *d;
- unsigned int i;
-
- dev = qdev_new(TYPE_IOAPIC);
- d = SYS_BUS_DEVICE(dev);
- sysbus_realize_and_unref(d, &error_fatal);
- sysbus_mmio_map(d, 0, IO_APIC_SECONDARY_ADDRESS);
-
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- gsi_state->ioapic2_irq[i] = qdev_get_gpio_in(dev, i);
- }
- return dev;
-}
-
-/*
- * The entry point into the kernel for PVH boot is different from
- * the native entry point. The PVH entry is defined by the x86/HVM
- * direct boot ABI and is available in an ELFNOTE in the kernel binary.
- *
- * This function is passed to load_elf() when it is called from
- * load_elfboot() which then additionally checks for an ELF Note of
- * type XEN_ELFNOTE_PHYS32_ENTRY and passes it to this function to
- * parse the PVH entry address from the ELF Note.
- *
- * Due to trickery in elf_opts.h, load_elf() is actually available as
- * load_elf32() or load_elf64() and this routine needs to be able
- * to deal with being called as 32 or 64 bit.
- *
- * The address of the PVH entry point is saved to the 'pvh_start_addr'
- * global variable. (although the entry point is 32-bit, the kernel
- * binary can be either 32-bit or 64-bit).
- */
-static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
-{
- size_t *elf_note_data_addr;
-
- /* Check if ELF Note header passed in is valid */
- if (arg1 == NULL) {
- return 0;
- }
-
- if (is64) {
- struct elf64_note *nhdr64 = (struct elf64_note *)arg1;
- uint64_t nhdr_size64 = sizeof(struct elf64_note);
- uint64_t phdr_align = *(uint64_t *)arg2;
- uint64_t nhdr_namesz = nhdr64->n_namesz;
-
- elf_note_data_addr =
- ((void *)nhdr64) + nhdr_size64 +
- QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
-
- pvh_start_addr = *elf_note_data_addr;
- } else {
- struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
- uint32_t nhdr_size32 = sizeof(struct elf32_note);
- uint32_t phdr_align = *(uint32_t *)arg2;
- uint32_t nhdr_namesz = nhdr32->n_namesz;
-
- elf_note_data_addr =
- ((void *)nhdr32) + nhdr_size32 +
- QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
-
- pvh_start_addr = *(uint32_t *)elf_note_data_addr;
- }
-
- return pvh_start_addr;
-}
-
-static bool load_elfboot(const char *kernel_filename,
- int kernel_file_size,
- uint8_t *header,
- size_t pvh_xen_start_addr,
- FWCfgState *fw_cfg)
-{
- uint32_t flags = 0;
- uint32_t mh_load_addr = 0;
- uint32_t elf_kernel_size = 0;
- uint64_t elf_entry;
- uint64_t elf_low, elf_high;
- int kernel_size;
-
- if (ldl_p(header) != 0x464c457f) {
- return false; /* no elfboot */
- }
-
- bool elf_is64 = header[EI_CLASS] == ELFCLASS64;
- flags = elf_is64 ?
- ((Elf64_Ehdr *)header)->e_flags : ((Elf32_Ehdr *)header)->e_flags;
-
- if (flags & 0x00010004) { /* LOAD_ELF_HEADER_HAS_ADDR */
- error_report("elfboot unsupported flags = %x", flags);
- exit(1);
- }
-
- uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
- kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
- NULL, &elf_note_type, &elf_entry,
- &elf_low, &elf_high, NULL, 0, I386_ELF_MACHINE,
- 0, 0);
-
- if (kernel_size < 0) {
- error_report("Error while loading elf kernel");
- exit(1);
- }
- mh_load_addr = elf_low;
- elf_kernel_size = elf_high - elf_low;
-
- if (pvh_start_addr == 0) {
- error_report("Error loading uncompressed kernel without PVH ELF Note");
- exit(1);
- }
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, pvh_start_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, elf_kernel_size);
-
- return true;
-}
-
-void x86_load_linux(X86MachineState *x86ms,
- FWCfgState *fw_cfg,
- int acpi_data_size,
- bool pvh_enabled)
-{
- bool linuxboot_dma_enabled = X86_MACHINE_GET_CLASS(x86ms)->fwcfg_dma_enabled;
- uint16_t protocol;
- int setup_size, kernel_size, cmdline_size;
- int dtb_size, setup_data_offset;
- uint32_t initrd_max;
- uint8_t header[8192], *setup, *kernel;
- hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
- FILE *f;
- char *vmode;
- MachineState *machine = MACHINE(x86ms);
- struct setup_data *setup_data;
- const char *kernel_filename = machine->kernel_filename;
- const char *initrd_filename = machine->initrd_filename;
- const char *dtb_filename = machine->dtb;
- const char *kernel_cmdline = machine->kernel_cmdline;
- SevKernelLoaderContext sev_load_ctx = {};
-
- /* Align to 16 bytes as a paranoia measure */
- cmdline_size = (strlen(kernel_cmdline) + 16) & ~15;
-
- /* load the kernel header */
- f = fopen(kernel_filename, "rb");
- if (!f) {
- fprintf(stderr, "qemu: could not open kernel file '%s': %s\n",
- kernel_filename, strerror(errno));
- exit(1);
- }
-
- kernel_size = get_file_size(f);
- if (!kernel_size ||
- fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
- MIN(ARRAY_SIZE(header), kernel_size)) {
- fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
- kernel_filename, strerror(errno));
- exit(1);
- }
-
- /* kernel protocol version */
- if (ldl_p(header + 0x202) == 0x53726448) {
- protocol = lduw_p(header + 0x206);
- } else {
- /*
- * This could be a multiboot kernel. If it is, let's stop treating it
- * like a Linux kernel.
- * Note: some multiboot images could be in the ELF format (the same of
- * PVH), so we try multiboot first since we check the multiboot magic
- * header before to load it.
- */
- if (load_multiboot(x86ms, fw_cfg, f, kernel_filename, initrd_filename,
- kernel_cmdline, kernel_size, header)) {
- return;
- }
- /*
- * Check if the file is an uncompressed kernel file (ELF) and load it,
- * saving the PVH entry point used by the x86/HVM direct boot ABI.
- * If load_elfboot() is successful, populate the fw_cfg info.
- */
- if (pvh_enabled &&
- load_elfboot(kernel_filename, kernel_size,
- header, pvh_start_addr, fw_cfg)) {
- fclose(f);
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
- strlen(kernel_cmdline) + 1);
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, sizeof(header));
- fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA,
- header, sizeof(header));
-
- /* load initrd */
- if (initrd_filename) {
- GMappedFile *mapped_file;
- gsize initrd_size;
- gchar *initrd_data;
- GError *gerr = NULL;
-
- mapped_file = g_mapped_file_new(initrd_filename, false, &gerr);
- if (!mapped_file) {
- fprintf(stderr, "qemu: error reading initrd %s: %s\n",
- initrd_filename, gerr->message);
- exit(1);
- }
- x86ms->initrd_mapped_file = mapped_file;
-
- initrd_data = g_mapped_file_get_contents(mapped_file);
- initrd_size = g_mapped_file_get_length(mapped_file);
- initrd_max = x86ms->below_4g_mem_size - acpi_data_size - 1;
- if (initrd_size >= initrd_max) {
- fprintf(stderr, "qemu: initrd is too large, cannot support."
- "(max: %"PRIu32", need %"PRId64")\n",
- initrd_max, (uint64_t)initrd_size);
- exit(1);
- }
-
- initrd_addr = (initrd_max - initrd_size) & ~4095;
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
- fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data,
- initrd_size);
- }
-
- option_rom[nb_option_roms].bootindex = 0;
- option_rom[nb_option_roms].name = "pvh.bin";
- nb_option_roms++;
-
- return;
- }
- protocol = 0;
- }
-
- if (protocol < 0x200 || !(header[0x211] & 0x01)) {
- /* Low kernel */
- real_addr = 0x90000;
- cmdline_addr = 0x9a000 - cmdline_size;
- prot_addr = 0x10000;
- } else if (protocol < 0x202) {
- /* High but ancient kernel */
- real_addr = 0x90000;
- cmdline_addr = 0x9a000 - cmdline_size;
- prot_addr = 0x100000;
- } else {
- /* High and recent kernel */
- real_addr = 0x10000;
- cmdline_addr = 0x20000;
- prot_addr = 0x100000;
- }
-
- /* highest address for loading the initrd */
- if (protocol >= 0x20c &&
- lduw_p(header + 0x236) & XLF_CAN_BE_LOADED_ABOVE_4G) {
- /*
- * Linux has supported initrd up to 4 GB for a very long time (2007,
- * long before XLF_CAN_BE_LOADED_ABOVE_4G which was added in 2013),
- * though it only sets initrd_max to 2 GB to "work around bootloader
- * bugs". Luckily, QEMU firmware(which does something like bootloader)
- * has supported this.
- *
- * It's believed that if XLF_CAN_BE_LOADED_ABOVE_4G is set, initrd can
- * be loaded into any address.
- *
- * In addition, initrd_max is uint32_t simply because QEMU doesn't
- * support the 64-bit boot protocol (specifically the ext_ramdisk_image
- * field).
- *
- * Therefore here just limit initrd_max to UINT32_MAX simply as well.
- */
- initrd_max = UINT32_MAX;
- } else if (protocol >= 0x203) {
- initrd_max = ldl_p(header + 0x22c);
- } else {
- initrd_max = 0x37ffffff;
- }
-
- if (initrd_max >= x86ms->below_4g_mem_size - acpi_data_size) {
- initrd_max = x86ms->below_4g_mem_size - acpi_data_size - 1;
- }
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline) + 1);
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
- sev_load_ctx.cmdline_data = (char *)kernel_cmdline;
- sev_load_ctx.cmdline_size = strlen(kernel_cmdline) + 1;
-
- if (protocol >= 0x202) {
- stl_p(header + 0x228, cmdline_addr);
- } else {
- stw_p(header + 0x20, 0xA33F);
- stw_p(header + 0x22, cmdline_addr - real_addr);
- }
-
- /* handle vga= parameter */
- vmode = strstr(kernel_cmdline, "vga=");
- if (vmode) {
- unsigned int video_mode;
- const char *end;
- int ret;
- /* skip "vga=" */
- vmode += 4;
- if (!strncmp(vmode, "normal", 6)) {
- video_mode = 0xffff;
- } else if (!strncmp(vmode, "ext", 3)) {
- video_mode = 0xfffe;
- } else if (!strncmp(vmode, "ask", 3)) {
- video_mode = 0xfffd;
- } else {
- ret = qemu_strtoui(vmode, &end, 0, &video_mode);
- if (ret != 0 || (*end && *end != ' ')) {
- fprintf(stderr, "qemu: invalid 'vga=' kernel parameter.\n");
- exit(1);
- }
- }
- stw_p(header + 0x1fa, video_mode);
- }
-
- /* loader type */
- /*
- * High nybble = B reserved for QEMU; low nybble is revision number.
- * If this code is substantially changed, you may want to consider
- * incrementing the revision.
- */
- if (protocol >= 0x200) {
- header[0x210] = 0xB0;
- }
- /* heap */
- if (protocol >= 0x201) {
- header[0x211] |= 0x80; /* CAN_USE_HEAP */
- stw_p(header + 0x224, cmdline_addr - real_addr - 0x200);
- }
-
- /* load initrd */
- if (initrd_filename) {
- GMappedFile *mapped_file;
- gsize initrd_size;
- gchar *initrd_data;
- GError *gerr = NULL;
-
- if (protocol < 0x200) {
- fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
- exit(1);
- }
-
- mapped_file = g_mapped_file_new(initrd_filename, false, &gerr);
- if (!mapped_file) {
- fprintf(stderr, "qemu: error reading initrd %s: %s\n",
- initrd_filename, gerr->message);
- exit(1);
- }
- x86ms->initrd_mapped_file = mapped_file;
-
- initrd_data = g_mapped_file_get_contents(mapped_file);
- initrd_size = g_mapped_file_get_length(mapped_file);
- if (initrd_size >= initrd_max) {
- fprintf(stderr, "qemu: initrd is too large, cannot support."
- "(max: %"PRIu32", need %"PRId64")\n",
- initrd_max, (uint64_t)initrd_size);
- exit(1);
- }
-
- initrd_addr = (initrd_max - initrd_size) & ~4095;
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
- fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
- sev_load_ctx.initrd_data = initrd_data;
- sev_load_ctx.initrd_size = initrd_size;
-
- stl_p(header + 0x218, initrd_addr);
- stl_p(header + 0x21c, initrd_size);
- }
-
- /* load kernel and setup */
- setup_size = header[0x1f1];
- if (setup_size == 0) {
- setup_size = 4;
- }
- setup_size = (setup_size + 1) * 512;
- if (setup_size > kernel_size) {
- fprintf(stderr, "qemu: invalid kernel header\n");
- exit(1);
- }
- kernel_size -= setup_size;
-
- setup = g_malloc(setup_size);
- kernel = g_malloc(kernel_size);
- fseek(f, 0, SEEK_SET);
- if (fread(setup, 1, setup_size, f) != setup_size) {
- fprintf(stderr, "fread() failed\n");
- exit(1);
- }
- if (fread(kernel, 1, kernel_size, f) != kernel_size) {
- fprintf(stderr, "fread() failed\n");
- exit(1);
- }
- fclose(f);
-
- /* append dtb to kernel */
- if (dtb_filename) {
- if (protocol < 0x209) {
- fprintf(stderr, "qemu: Linux kernel too old to load a dtb\n");
- exit(1);
- }
-
- dtb_size = get_image_size(dtb_filename);
- if (dtb_size <= 0) {
- fprintf(stderr, "qemu: error reading dtb %s: %s\n",
- dtb_filename, strerror(errno));
- exit(1);
- }
-
- setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
- kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
- kernel = g_realloc(kernel, kernel_size);
-
- stq_p(header + 0x250, prot_addr + setup_data_offset);
-
- setup_data = (struct setup_data *)(kernel + setup_data_offset);
- setup_data->next = 0;
- setup_data->type = cpu_to_le32(SETUP_DTB);
- setup_data->len = cpu_to_le32(dtb_size);
-
- load_image_size(dtb_filename, setup_data->data, dtb_size);
- }
-
- /*
- * If we're starting an encrypted VM, it will be OVMF based, which uses the
- * efi stub for booting and doesn't require any values to be placed in the
- * kernel header. We therefore don't update the header so the hash of the
- * kernel on the other side of the fw_cfg interface matches the hash of the
- * file the user passed in.
- */
- if (!sev_enabled()) {
- memcpy(setup, header, MIN(sizeof(header), setup_size));
- }
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
- fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
- sev_load_ctx.kernel_data = (char *)kernel;
- sev_load_ctx.kernel_size = kernel_size;
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
- fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
- sev_load_ctx.setup_data = (char *)setup;
- sev_load_ctx.setup_size = setup_size;
-
- if (sev_enabled()) {
- sev_add_kernel_loader_hashes(&sev_load_ctx, &error_fatal);
- }
-
- option_rom[nb_option_roms].bootindex = 0;
- option_rom[nb_option_roms].name = "linuxboot.bin";
- if (linuxboot_dma_enabled && fw_cfg_dma_enabled(fw_cfg)) {
- option_rom[nb_option_roms].name = "linuxboot_dma.bin";
- }
- nb_option_roms++;
-}
-
-void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
- MemoryRegion *bios, bool read_only)
-{
- uint64_t bios_size = memory_region_size(bios);
- uint64_t isa_bios_size = MIN(bios_size, 128 * KiB);
-
- memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
- bios_size - isa_bios_size, isa_bios_size);
- memory_region_add_subregion_overlap(isa_memory, 1 * MiB - isa_bios_size,
- isa_bios, 1);
- memory_region_set_readonly(isa_bios, read_only);
-}
-
-void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
- MemoryRegion *rom_memory, bool isapc_ram_fw)
-{
- const char *bios_name;
- char *filename;
- int bios_size;
- ssize_t ret;
-
- /* BIOS load */
- bios_name = MACHINE(x86ms)->firmware ?: default_firmware;
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- if (filename) {
- bios_size = get_image_size(filename);
- } else {
- bios_size = -1;
- }
- if (bios_size <= 0 ||
- (bios_size % 65536) != 0) {
- goto bios_error;
- }
- memory_region_init_ram(&x86ms->bios, NULL, "pc.bios", bios_size,
- &error_fatal);
- if (sev_enabled()) {
- /*
- * The concept of a "reset" simply doesn't exist for
- * confidential computing guests, we have to destroy and
- * re-launch them instead. So there is no need to register
- * the firmware as rom to properly re-initialize on reset.
- * Just go for a straight file load instead.
- */
- void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
- load_image_size(filename, ptr, bios_size);
- x86_firmware_configure(ptr, bios_size);
- } else {
- memory_region_set_readonly(&x86ms->bios, !isapc_ram_fw);
- ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
- if (ret != 0) {
- goto bios_error;
- }
- }
- g_free(filename);
-
- /* map the last 128KB of the BIOS in ISA space */
- x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
- !isapc_ram_fw);
-
- /* map all the bios at the top of memory */
- memory_region_add_subregion(rom_memory,
- (uint32_t)(-bios_size),
- &x86ms->bios);
- return;
-
-bios_error:
- fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
- exit(1);
-}
-
bool x86_machine_is_smm_enabled(const X86MachineState *x86ms)
{
bool smm_available = false;
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index d9da676038c..3437da0aad1 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -4,6 +4,7 @@ i386_ss.add(files(
'e820_memory_layout.c',
'multiboot.c',
'x86.c',
+ 'x86-cpu.c',
))
i386_ss.add(when: 'CONFIG_APIC', if_true: files('vapic.c'))
@@ -12,7 +13,7 @@ i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'),
if_false: files('amd_iommu-stub.c'))
i386_ss.add(when: 'CONFIG_I440FX', if_true: files('pc_piix.c'))
-i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c', 'microvm-dt.c'))
+i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('x86-common.c', 'microvm.c', 'acpi-microvm.c', 'microvm-dt.c'))
i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c'))
i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c'))
i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
@@ -22,6 +23,7 @@ i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c','sgx.c'),
i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
i386_ss.add(when: 'CONFIG_PC', if_true: files(
+ 'x86-common.c',
'pc.c',
'pc_sysfw.c',
'acpi-build.c',
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (9 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 10/13] hw/i386: split x86.c in multiple parts Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 12:37 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 12/13] i386: select correct components for no-board build Paolo Bonzini
2024-05-09 17:00 ` [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
The rtc-reset-reinjection QMP command is specific to x86, other boards do not
have the ACK tracking functionality that is needed for RTC interrupt
reinjection. Therefore the QMP command is only included in x86, but
qmp_rtc_reset_reinjection() is implemented by hw/rtc/mc146818rtc.c
and requires tracking of all created RTC devices. Move the implementation
to hw/i386, so that 1) it is available even if no RTC device exist
2) the only RTC that exists is easily found in x86ms->rtc.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/rtc/mc146818rtc.h | 2 +-
hw/i386/monitor.c | 46 ++++++++++++++++++++++++++++++++++++
hw/rtc/mc146818rtc.c | 12 ++--------
hw/i386/meson.build | 1 +
4 files changed, 50 insertions(+), 11 deletions(-)
create mode 100644 hw/i386/monitor.c
diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 97cec0b3e84..64893be1515 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -55,6 +55,6 @@ MC146818RtcState *mc146818_rtc_init(ISABus *bus, int base_year,
qemu_irq intercept_irq);
void mc146818rtc_set_cmos_data(MC146818RtcState *s, int addr, int val);
int mc146818rtc_get_cmos_data(MC146818RtcState *s, int addr);
-void qmp_rtc_reset_reinjection(Error **errp);
+void rtc_reset_reinjection(MC146818RtcState *rtc);
#endif /* HW_RTC_MC146818RTC_H */
diff --git a/hw/i386/monitor.c b/hw/i386/monitor.c
new file mode 100644
index 00000000000..1ebd3564bf2
--- /dev/null
+++ b/hw/i386/monitor.c
@@ -0,0 +1,46 @@
+/*
+ * QEMU monitor
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "hw/i386/x86.h"
+#include "hw/rtc/mc146818rtc.h"
+
+#include CONFIG_DEVICES
+
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+ X86MachineState *x86ms = X86_MACHINE(qdev_get_machine());
+
+#ifdef CONFIG_MC146818RTC
+ if (x86ms->rtc) {
+ rtc_reset_reinjection(MC146818_RTC(x86ms->rtc));
+ }
+#else
+ assert(!x86ms->rtc);
+#endif
+}
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index 3379f92748b..8ccee9a385d 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -104,16 +104,9 @@ static void rtc_coalesced_timer_update(MC146818RtcState *s)
}
}
-static QLIST_HEAD(, MC146818RtcState) rtc_devices =
- QLIST_HEAD_INITIALIZER(rtc_devices);
-
-void qmp_rtc_reset_reinjection(Error **errp)
+void rtc_reset_reinjection(MC146818RtcState *rtc)
{
- MC146818RtcState *s;
-
- QLIST_FOREACH(s, &rtc_devices, link) {
- s->irq_coalesced = 0;
- }
+ rtc->irq_coalesced = 0;
}
static bool rtc_policy_slew_deliver_irq(MC146818RtcState *s)
@@ -941,7 +934,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
object_property_add_tm(OBJECT(s), "date", rtc_get_date);
qdev_init_gpio_out(dev, &s->irq, 1);
- QLIST_INSERT_HEAD(&rtc_devices, s, link);
}
MC146818RtcState *mc146818_rtc_init(ISABus *bus, int base_year,
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 3437da0aad1..03aad10df7a 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -2,6 +2,7 @@ i386_ss = ss.source_set()
i386_ss.add(files(
'fw_cfg.c',
'e820_memory_layout.c',
+ 'monitor.c',
'multiboot.c',
'x86.c',
'x86-cpu.c',
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 12/13] i386: select correct components for no-board build
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (10 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 12:40 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
12 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
The local APIC is a part of the CPU and has callbacks that are invoked
from multiple accelerators.
The IOAPIC on the other hand is optional, but ioapic_eoi_broadcast is
used by common x86 code to implement the IOAPIC's implicit EOI mode.
Add a stub in case the IOAPIC device is not included but the APIC is.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/intc/ioapic-stub.c | 29 +++++++++++++++++++++++++++++
.gitlab-ci.d/buildtest.yml | 2 +-
hw/intc/meson.build | 2 +-
target/i386/Kconfig | 1 +
4 files changed, 32 insertions(+), 2 deletions(-)
create mode 100644 hw/intc/ioapic-stub.c
diff --git a/hw/intc/ioapic-stub.c b/hw/intc/ioapic-stub.c
new file mode 100644
index 00000000000..4dcd86248da
--- /dev/null
+++ b/hw/intc/ioapic-stub.c
@@ -0,0 +1,29 @@
+/*
+ * ioapic.c IOAPIC emulation logic
+ *
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ *
+ * Split the ioapic logic from apic.c
+ * Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/intc/ioapic.h"
+
+void ioapic_eoi_broadcast(int vector)
+{
+}
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index f8502905203..62616157206 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
# Check our reduced build configurations
# requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
# mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, x86_64
+# fails qtest without boards: i386, x86_64
build-without-defaults:
extends: .native_build_job_template
needs:
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index f4b540e6a8b..0d1b7d0a432 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -20,7 +20,7 @@ system_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
system_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
system_ss.add(when: 'CONFIG_I8259', if_true: files('i8259_common.c', 'i8259.c'))
system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_avic.c', 'imx_gpcv2.c'))
-system_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic_common.c'))
+system_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic_common.c'), if_false: files('ioapic-stub.c'))
system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c'))
system_ss.add(when: 'CONFIG_OPENPIC', if_true: files('openpic.c'))
system_ss.add(when: 'CONFIG_PL190', if_true: files('pl190.c'))
diff --git a/target/i386/Kconfig b/target/i386/Kconfig
index ad9291d3b8f..6b0feef0299 100644
--- a/target/i386/Kconfig
+++ b/target/i386/Kconfig
@@ -1,5 +1,6 @@
config I386
bool
+ select APIC
# kvm_arch_fixup_msi_route() needs to access PCIDevice
select PCI if KVM
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
` (11 preceding siblings ...)
2024-05-09 17:00 ` [PATCH 12/13] i386: select correct components for no-board build Paolo Bonzini
@ 2024-05-09 17:00 ` Paolo Bonzini
2024-05-10 5:55 ` Thomas Huth
2024-05-10 9:14 ` Philippe Mathieu-Daudé
12 siblings, 2 replies; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-09 17:00 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth
ARM/aarch64 are easy to fix because they already have to pass a machine
type by hand. Just guard the tests with a check that the machine actually
exists.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/qtest/arm-cpu-features.c | 4 ++++
tests/qtest/migration-test.c | 6 ++++++
tests/qtest/numa-test.c | 4 ++++
3 files changed, 14 insertions(+)
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index 9d6e6190d55..966c65d5c3e 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -632,6 +632,10 @@ int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
+ if (!qtest_has_machine("virt")) {
+ goto out;
+ }
+
if (qtest_has_accel("tcg")) {
qtest_add_data_func("/arm/query-cpu-model-expansion",
NULL, test_query_cpu_model_expansion);
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 5d6d8cd6343..31045b69fa7 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -813,6 +813,12 @@ static int test_migrate_start(QTestState **from, QTestState **to,
kvm_opts = ",dirty-ring-size=4096";
}
+ if (!qtest_has_machine(machine_alias)) {
+ g_autofree char *msg = g_strdup_printf("machine %s not supported", machine_alias);
+ g_test_skip(msg);
+ return -1;
+ }
+
machine = resolve_machine_version(machine_alias, QEMU_ENV_SRC,
QEMU_ENV_DST);
diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
index 4f4404a4b14..7aa262dbb99 100644
--- a/tests/qtest/numa-test.c
+++ b/tests/qtest/numa-test.c
@@ -558,6 +558,9 @@ int main(int argc, char **argv)
}
if (g_str_equal(arch, "aarch64")) {
+ if (!qtest_has_machine("virt")) {
+ goto out;
+ }
g_string_append(args, " -machine virt");
}
@@ -590,5 +593,6 @@ int main(int argc, char **argv)
aarch64_numa_cpu);
}
+out:
return g_test_run();
}
--
2.45.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c
2024-05-09 17:00 ` [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
@ 2024-05-10 4:59 ` Thomas Huth
0 siblings, 0 replies; 31+ messages in thread
From: Thomas Huth @ 2024-05-10 4:59 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel; +Cc: qemu-s390x
On 09/05/2024 19.00, Paolo Bonzini wrote:
> This function has no dependency on the virtio-ccw machine type, though it
> assumes that the CPU address corresponds to the core_id and the index.
>
> If there is any need of something different or more fancy (unlikely)
> S390 can include a MachineClass subclass and implement it there. For
> now, move it to sigp.c for simplicity.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/s390x/s390-virtio-ccw.c | 16 ----------------
> target/s390x/sigp.c | 17 +++++++++++++++++
> 2 files changed, 17 insertions(+), 16 deletions(-)
Reviewed-by: Thomas Huth <thuth@redhat.com>
> diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
> index 4dcc2138200..feabc173eb3 100644
> --- a/hw/s390x/s390-virtio-ccw.c
> +++ b/hw/s390x/s390-virtio-ccw.c
> @@ -50,22 +50,6 @@
>
> static Error *pv_mig_blocker;
>
> -S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
> -{
> - static MachineState *ms;
> -
> - if (!ms) {
> - ms = MACHINE(qdev_get_machine());
> - g_assert(ms->possible_cpus);
> - }
> -
> - /* CPU address corresponds to the core_id and the index */
> - if (cpu_addr >= ms->possible_cpus->len) {
> - return NULL;
> - }
> - return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
> -}
> -
> static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
> Error **errp)
> {
> diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
> index 9dd977349ab..ad0ad61177d 100644
> --- a/target/s390x/sigp.c
> +++ b/target/s390x/sigp.c
> @@ -11,6 +11,7 @@
> #include "qemu/osdep.h"
> #include "cpu.h"
> #include "s390x-internal.h"
> +#include "hw/boards.h"
> #include "sysemu/hw_accel.h"
> #include "sysemu/runstate.h"
> #include "exec/address-spaces.h"
> @@ -435,6 +436,22 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
> return SIGP_CC_STATUS_STORED;
> }
>
> +S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
> +{
> + static MachineState *ms;
> +
> + if (!ms) {
> + ms = MACHINE(qdev_get_machine());
> + g_assert(ms->possible_cpus);
> + }
> +
> + /* CPU address corresponds to the core_id and the index */
> + if (cpu_addr >= ms->possible_cpus->len) {
> + return NULL;
> + }
> + return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
> +}
> +
> int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
> {
> uint64_t *status_reg = &env->regs[r1];
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 02/13] s390_flic: add migration-enabled property
2024-05-09 17:00 ` [PATCH 02/13] s390_flic: add migration-enabled property Paolo Bonzini
@ 2024-05-10 5:06 ` Thomas Huth
2024-05-16 14:42 ` Marc Hartmayer
1 sibling, 0 replies; 31+ messages in thread
From: Thomas Huth @ 2024-05-10 5:06 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel; +Cc: qemu-s390x, Daniel P. Berrange
On 09/05/2024 19.00, Paolo Bonzini wrote:
> Instead of mucking with css_migration_enabled(), add a property specific to
> the FLIC device, similar to what is done for TYPE_S390_STATTRIB.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/s390x/s390_flic.h | 1 +
> hw/intc/s390_flic.c | 6 +++++-
> hw/s390x/s390-virtio-ccw.c | 1 +
> 3 files changed, 7 insertions(+), 1 deletion(-)
Reviewed-by: Thomas Huth <thuth@redhat.com>
(BTW: It's really good that Daniel's patch series is going to mark the old
machine types as deprecated, too ... migration stuff has been so hacky in
the 2.x days...)
> diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
> index 3907a13d076..bcb081def58 100644
> --- a/include/hw/s390x/s390_flic.h
> +++ b/include/hw/s390x/s390_flic.h
> @@ -47,6 +47,7 @@ struct S390FLICState {
> /* to limit AdapterRoutes.num_routes for compat */
> uint32_t adapter_routes_max_batch;
> bool ais_supported;
> + bool migration_enabled;
> };
>
>
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index f4a848460b8..7f930800877 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -405,6 +405,8 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
> static Property s390_flic_common_properties[] = {
> DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState,
> adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI),
> + DEFINE_PROP_BOOL("migration-enabled", S390FLICState,
> + migration_enabled, true),
> DEFINE_PROP_END_OF_LIST(),
> };
>
> @@ -457,7 +459,9 @@ type_init(qemu_s390_flic_register_types)
>
> static bool adapter_info_so_needed(void *opaque)
> {
> - return css_migration_enabled();
> + S390FLICState *fs = S390_FLIC_COMMON(opaque);
> +
> + return fs->migration_enabled;
> }
>
> const VMStateDescription vmstate_adapter_info_so = {
> diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
> index feabc173eb3..1383e47eeb5 100644
> --- a/hw/s390x/s390-virtio-ccw.c
> +++ b/hw/s390x/s390-virtio-ccw.c
> @@ -1174,6 +1174,7 @@ static void ccw_machine_2_9_class_options(MachineClass *mc)
> S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
> static GlobalProperty compat[] = {
> { TYPE_S390_STATTRIB, "migration-enabled", "off", },
> + { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
> };
>
> ccw_machine_2_10_class_options(mc);
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 04/13] s390x: select correct components for no-board build
2024-05-09 17:00 ` [PATCH 04/13] s390x: select correct components for no-board build Paolo Bonzini
@ 2024-05-10 5:11 ` Thomas Huth
0 siblings, 0 replies; 31+ messages in thread
From: Thomas Huth @ 2024-05-10 5:11 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 09/05/2024 19.00, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> .gitlab-ci.d/buildtest.yml | 4 ++--
> target/s390x/Kconfig | 2 ++
> 2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
> index 13afd0df1f0..f8502905203 100644
> --- a/.gitlab-ci.d/buildtest.yml
> +++ b/.gitlab-ci.d/buildtest.yml
> @@ -650,7 +650,7 @@ build-tci:
> # Check our reduced build configurations
> # requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
> # mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
> -# does not build without boards: i386, s390x, x86_64
> +# does not build without boards: i386, x86_64
> build-without-defaults:
> extends: .native_build_job_template
> needs:
> @@ -666,7 +666,7 @@ build-without-defaults:
> --disable-strip
> TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
> mips-softmmu mips64-softmmu mipsel-softmmu
> - sh4-softmmu sh4eb-softmmu sparc-softmmu
> + s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
> sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
> hexagon-linux-user i386-linux-user s390x-linux-user
> MAKE_CHECK_ARGS: check
> diff --git a/target/s390x/Kconfig b/target/s390x/Kconfig
> index 72da48136c6..d886be48b47 100644
> --- a/target/s390x/Kconfig
> +++ b/target/s390x/Kconfig
> @@ -1,2 +1,4 @@
> config S390X
> bool
> + select PCI
> + select S390_FLIC
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices
2024-05-09 17:00 ` [PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
@ 2024-05-10 5:13 ` Thomas Huth
0 siblings, 0 replies; 31+ messages in thread
From: Thomas Huth @ 2024-05-10 5:13 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 09/05/2024 19.00, Paolo Bonzini wrote:
> Do the bare minimum to ensure that at least a vanilla
> --without-default-devices build works for all targets except i386,
> x86_64 and ppc64. In particular this fixes s390x-softmmu; i386 and
> x86_64 have about a dozen failing tests that do not pass -M and therefore
> require a default machine type; ppc64 has the same issue, though only
> with numa-test.
>
> If we can for now ignore the cases where boards and devices are picked
> by hand, drive_del-test however can be fixed easily; almost all tests
> check for the virtio-blk or virtio-scsi device that they use, and are
> already skipped. Only one didn't get the memo; plus another one does
> not need a machine at all and can be run with -M none.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> tests/qtest/drive_del-test.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/tests/qtest/drive_del-test.c b/tests/qtest/drive_del-test.c
> index 8a6f3ac963d..7b67a4bbee4 100644
> --- a/tests/qtest/drive_del-test.c
> +++ b/tests/qtest/drive_del-test.c
> @@ -173,7 +173,7 @@ static void test_drive_without_dev(void)
> QTestState *qts;
>
> /* Start with an empty drive */
> - qts = qtest_init("-drive if=none,id=drive0");
> + qts = qtest_init("-drive if=none,id=drive0 -M none");
>
> /* Delete the drive */
> drive_del(qts);
> @@ -192,6 +192,11 @@ static void test_after_failed_device_add(void)
> QDict *response;
> QTestState *qts;
>
> + if (!has_device_builtin("virtio-blk")) {
> + g_test_skip("Device virtio-blk is not available");
> + return;
> + }
> +
> snprintf(driver, sizeof(driver), "virtio-blk-%s",
> qvirtio_get_dev_type());
>
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 03/13] s390: move css_migration_enabled from machine to css.c
2024-05-09 17:00 ` [PATCH 03/13] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
@ 2024-05-10 5:37 ` Thomas Huth
2024-05-10 9:19 ` Paolo Bonzini
0 siblings, 1 reply; 31+ messages in thread
From: Thomas Huth @ 2024-05-10 5:37 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 09/05/2024 19.00, Paolo Bonzini wrote:
> The CSS subsystem uses global variables, just face the truth and use
> a variable also for whether the CSS vmstate is in use; remove the
> indirection of fetching it from the machine type, which makes the
> TCG code depend unnecessarily on the virtio-ccw machine.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/s390x/css.h | 6 ++++++
> include/hw/s390x/s390-virtio-ccw.h | 7 -------
> hw/s390x/css.c | 10 +++++++---
> hw/s390x/s390-virtio-ccw.c | 15 +++------------
> 4 files changed, 16 insertions(+), 22 deletions(-)
>
> diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
> index ba72ee3dd20..8289e458370 100644
> --- a/include/hw/s390x/css.h
> +++ b/include/hw/s390x/css.h
> @@ -333,4 +333,10 @@ static inline int ccw_dstream_read_buf(CcwDataStream *cds, void *buff, int len)
> #define ccw_dstream_read(cds, v) ccw_dstream_read_buf((cds), &(v), sizeof(v))
> #define ccw_dstream_write(cds, v) ccw_dstream_write_buf((cds), &(v), sizeof(v))
>
> +/**
> + * true if (vmstate based) migration of the channel subsystem
> + * is enabled, false if it is disabled.
> + */
> +extern bool css_migration_enabled;
> +
> #endif
> diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
> index c1d46e78af8..c0494e511cb 100644
> --- a/include/hw/s390x/s390-virtio-ccw.h
> +++ b/include/hw/s390x/s390-virtio-ccw.h
> @@ -43,7 +43,6 @@ struct S390CcwMachineClass {
> /*< public >*/
> bool ri_allowed;
> bool cpu_model_allowed;
> - bool css_migration_enabled;
> bool hpage_1m_allowed;
> int max_threads;
> };
> @@ -55,10 +54,4 @@ bool cpu_model_allowed(void);
> /* 1M huge page mappings allowed by the machine */
> bool hpage_1m_allowed(void);
>
> -/**
> - * Returns true if (vmstate based) migration of the channel subsystem
> - * is enabled, false if it is disabled.
> - */
> -bool css_migration_enabled(void);
> -
> #endif
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index 295530963a6..b2d5327dbf4 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -23,6 +23,8 @@
> #include "hw/s390x/s390-virtio-ccw.h"
> #include "hw/s390x/s390-ccw.h"
>
> +bool css_migration_enabled = true;
> +
> typedef struct CrwContainer {
> CRW crw;
> QTAILQ_ENTRY(CrwContainer) sibling;
> @@ -180,7 +182,7 @@ static const VMStateDescription vmstate_orb = {
>
> static bool vmstate_schdev_orb_needed(void *opaque)
> {
> - return css_migration_enabled();
> + return css_migration_enabled;
> }
>
> static const VMStateDescription vmstate_schdev_orb = {
> @@ -388,7 +390,7 @@ static int subch_dev_post_load(void *opaque, int version_id)
> css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
> }
>
> - if (css_migration_enabled()) {
> + if (css_migration_enabled) {
> /* No compat voodoo to do ;) */
> return 0;
> }
> @@ -412,7 +414,9 @@ static int subch_dev_post_load(void *opaque, int version_id)
>
> void css_register_vmstate(void)
> {
> - vmstate_register(NULL, 0, &vmstate_css, &channel_subsys);
> + if (css_migration_enabled) {
> + vmstate_register(NULL, 0, &vmstate_css, &channel_subsys);
> + }
> }
>
> IndAddr *get_indicator(hwaddr ind_addr, int len)
> diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
> index 1383e47eeb5..aa90703d518 100644
> --- a/hw/s390x/s390-virtio-ccw.c
> +++ b/hw/s390x/s390-virtio-ccw.c
> @@ -275,11 +275,9 @@ static void ccw_init(MachineState *machine)
> s390_enable_css_support(s390_cpu_addr2state(0));
>
> ret = css_create_css_image(VIRTUAL_CSSID, true);
> -
> assert(ret == 0);
> - if (css_migration_enabled()) {
> - css_register_vmstate();
> - }
> +
> + css_register_vmstate();
>
> /* Create VirtIO network adapters */
> s390_create_virtio_net(BUS(css_bus), mc->default_nic);
> @@ -741,7 +739,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
>
> s390mc->ri_allowed = true;
> s390mc->cpu_model_allowed = true;
> - s390mc->css_migration_enabled = true;
> s390mc->hpage_1m_allowed = true;
> s390mc->max_threads = 1;
> mc->init = ccw_init;
> @@ -811,11 +808,6 @@ static const TypeInfo ccw_machine_info = {
> },
> };
>
> -bool css_migration_enabled(void)
> -{
> - return get_machine_class()->css_migration_enabled;
> -}
> -
> #define DEFINE_CCW_MACHINE(suffix, verstr, latest) \
> static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \
> void *data) \
> @@ -1171,7 +1163,6 @@ static void ccw_machine_2_9_instance_options(MachineState *machine)
>
> static void ccw_machine_2_9_class_options(MachineClass *mc)
> {
> - S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
> static GlobalProperty compat[] = {
> { TYPE_S390_STATTRIB, "migration-enabled", "off", },
> { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
> @@ -1180,7 +1171,7 @@ static void ccw_machine_2_9_class_options(MachineClass *mc)
> ccw_machine_2_10_class_options(mc);
> compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
> compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
> - s390mc->css_migration_enabled = false;
> + css_migration_enabled = false;
> }
> DEFINE_CCW_MACHINE(2_9, "2.9", false);
I think this is wrong: By adding this to ccw_machine_2_9_class_options the
variable now always gets set to false, even for newer machines, since the
*class_options functions are part of the "class_init" which is always done.
You have to add it to ccw_machine_2_9_instance_options() instead to make it
work as expected.
Thomas
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices
2024-05-09 17:00 ` [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
@ 2024-05-10 5:55 ` Thomas Huth
2024-05-10 9:14 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 31+ messages in thread
From: Thomas Huth @ 2024-05-10 5:55 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 09/05/2024 19.00, Paolo Bonzini wrote:
> ARM/aarch64 are easy to fix because they already have to pass a machine
> type by hand. Just guard the tests with a check that the machine actually
> exists.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> tests/qtest/arm-cpu-features.c | 4 ++++
> tests/qtest/migration-test.c | 6 ++++++
> tests/qtest/numa-test.c | 4 ++++
> 3 files changed, 14 insertions(+)
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices
2024-05-09 17:00 ` [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
2024-05-10 5:55 ` Thomas Huth
@ 2024-05-10 9:14 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-10 9:14 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel; +Cc: thuth
On 9/5/24 19:00, Paolo Bonzini wrote:
> ARM/aarch64 are easy to fix because they already have to pass a machine
> type by hand. Just guard the tests with a check that the machine actually
> exists.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> tests/qtest/arm-cpu-features.c | 4 ++++
> tests/qtest/migration-test.c | 6 ++++++
> tests/qtest/numa-test.c | 4 ++++
> 3 files changed, 14 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 03/13] s390: move css_migration_enabled from machine to css.c
2024-05-10 5:37 ` Thomas Huth
@ 2024-05-10 9:19 ` Paolo Bonzini
0 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2024-05-10 9:19 UTC (permalink / raw)
To: Thomas Huth; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]
On Fri, May 10, 2024 at 7:38 AM Thomas Huth <thuth@redhat.com> wrote:
> I think this is wrong: By adding this to ccw_machine_2_9_class_options the
> variable now always gets set to false, even for newer machines, since the
> *class_options functions are part of the "class_init" which is always
done.
> You have to add it to ccw_machine_2_9_instance_options() instead to make
it
> work as expected.
Indeed, this has to be squashed in:
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index aa90703d518..b7ddd36b8ba 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -1159,6 +1159,7 @@ static void
ccw_machine_2_9_instance_options(MachineState *machine)
s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI);
s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION);
s390_cpudef_featoff_greater(12, 1,
S390_FEAT_ADAPTER_EVENT_NOTIFICATION);
+ css_migration_enabled = false;
}
static void ccw_machine_2_9_class_options(MachineClass *mc)
@@ -1171,7 +1172,6 @@ static void
ccw_machine_2_9_class_options(MachineClass *mc)
ccw_machine_2_10_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_2_9, hw_compat_2_9_len);
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
- css_migration_enabled = false;
}
DEFINE_CCW_MACHINE(2_9, "2.9", false);
[-- Attachment #2: Type: text/html, Size: 2155 bytes --]
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 06/13] xen: initialize legacy backends from xen_bus_init()
2024-05-09 17:00 ` [PATCH 06/13] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
@ 2024-05-10 10:18 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-10 10:18 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel; +Cc: thuth
On 9/5/24 19:00, Paolo Bonzini wrote:
> Prepare for moving the calls to xen_be_register() under the
> control of xen_bus_init(), using the normal xen_backend_init()
> method that is used by the "modern" backends.
>
> This requires the xenstore global variable to be initialized,
> which is done by xen_be_init(). To ensure that everything is
> ready at the time the xen_backend_init() functions are called,
> remove the xen_be_init() function from all the boards and
> place it directly in xen_bus_init().
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/i386/pc.c | 1 -
> hw/xen/xen-bus.c | 4 ++++
> hw/xen/xen-hvm-common.c | 2 --
> hw/xenpv/xen_machine_pv.c | 5 +----
> 4 files changed, 5 insertions(+), 7 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 07/13] xen: register legacy backends via xen_backend_init
2024-05-09 17:00 ` [PATCH 07/13] xen: register legacy backends via xen_backend_init Paolo Bonzini
@ 2024-05-10 10:52 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-05-10 10:52 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel; +Cc: thuth
On 9/5/24 19:00, Paolo Bonzini wrote:
> It is okay to register legacy backends in the middle of xen_bus_init().
> All that the registration does is record the existence of the backend
> in xenstore.
>
> This makes it possible to remove them from the build without introducing
> undefined symbols in xen_be_init(). It also removes the need for the
> backend_register callback, whose only purpose is to avoid registering
> nonfunctional backends.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/xen/xen-legacy-backend.h | 14 ++------------
> include/hw/xen/xen_pvdev.h | 1 -
> hw/9pfs/xen-9p-backend.c | 8 +++++++-
> hw/display/xenfb.c | 8 +++++++-
> hw/usb/xen-usb.c | 14 ++++----------
> hw/xen/xen-legacy-backend.c | 16 ----------------
> 6 files changed, 20 insertions(+), 41 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides
2024-05-09 17:00 ` [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
@ 2024-05-10 12:05 ` Zhao Liu
0 siblings, 0 replies; 31+ messages in thread
From: Zhao Liu @ 2024-05-10 12:05 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, thuth
On Thu, May 09, 2024 at 07:00:40PM +0200, Paolo Bonzini wrote:
> Date: Thu, 9 May 2024 19:00:40 +0200
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides
> X-Mailer: git-send-email 2.45.0
>
> There is no need to override these fields of MachineClass because they are
> already set to the right value in the superclass.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/i386/x86.h | 4 ----
> hw/i386/pc.c | 3 ---
> hw/i386/x86.c | 6 +++---
> 3 files changed, 3 insertions(+), 10 deletions(-)
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components
2024-05-09 17:00 ` [PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
@ 2024-05-10 12:15 ` Zhao Liu
0 siblings, 0 replies; 31+ messages in thread
From: Zhao Liu @ 2024-05-10 12:15 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, thuth
On Thu, May 09, 2024 at 07:00:39PM +0200, Paolo Bonzini wrote:
> Date: Thu, 9 May 2024 19:00:39 +0200
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 08/13] i386: correctly select code in hw/i386 that depends
> on other components
> X-Mailer: git-send-email 2.45.0
>
> fw_cfg.c and vapic.c are currently included unconditionally but
> depend on other components. vapic.c depends on the local APIC,
> while fw_cfg.c includes a piece of AML builder code that depends
> on CONFIG_ACPI.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/i386/fw_cfg.c | 2 ++
> hw/i386/meson.build | 2 +-
> 2 files changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 10/13] hw/i386: split x86.c in multiple parts
2024-05-09 17:00 ` [PATCH 10/13] hw/i386: split x86.c in multiple parts Paolo Bonzini
@ 2024-05-10 12:32 ` Zhao Liu
0 siblings, 0 replies; 31+ messages in thread
From: Zhao Liu @ 2024-05-10 12:32 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, thuth
On Thu, May 09, 2024 at 07:00:41PM +0200, Paolo Bonzini wrote:
> Date: Thu, 9 May 2024 19:00:41 +0200
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 10/13] hw/i386: split x86.c in multiple parts
> X-Mailer: git-send-email 2.45.0
>
> Keep the basic X86MachineState definition in x86.c. Move out functions that
> are only needed by other files: x86-common.c for the pc and microvm machines,
> x86-cpu.c for those used by accelerator code.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/i386/x86.h | 6 +-
> hw/i386/x86-common.c | 1007 +++++++++++++++++++++++++++++++++++++++
> hw/i386/x86-cpu.c | 97 ++++
> hw/i386/x86.c | 1052 +----------------------------------------
> hw/i386/meson.build | 4 +-
> 5 files changed, 1113 insertions(+), 1053 deletions(-)
> create mode 100644 hw/i386/x86-common.c
> create mode 100644 hw/i386/x86-cpu.c
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Once this change is merged, I'll rebase my module topology series.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc
2024-05-09 17:00 ` [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
@ 2024-05-10 12:37 ` Zhao Liu
0 siblings, 0 replies; 31+ messages in thread
From: Zhao Liu @ 2024-05-10 12:37 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, thuth
On Thu, May 09, 2024 at 07:00:42PM +0200, Paolo Bonzini wrote:
> Date: Thu, 9 May 2024 19:00:42 +0200
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of
> hw/rtc
> X-Mailer: git-send-email 2.45.0
>
> The rtc-reset-reinjection QMP command is specific to x86, other boards do not
> have the ACK tracking functionality that is needed for RTC interrupt
> reinjection. Therefore the QMP command is only included in x86, but
> qmp_rtc_reset_reinjection() is implemented by hw/rtc/mc146818rtc.c
> and requires tracking of all created RTC devices. Move the implementation
> to hw/i386, so that 1) it is available even if no RTC device exist
> 2) the only RTC that exists is easily found in x86ms->rtc.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/rtc/mc146818rtc.h | 2 +-
> hw/i386/monitor.c | 46 ++++++++++++++++++++++++++++++++++++
> hw/rtc/mc146818rtc.c | 12 ++--------
> hw/i386/meson.build | 1 +
> 4 files changed, 50 insertions(+), 11 deletions(-)
> create mode 100644 hw/i386/monitor.c
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 12/13] i386: select correct components for no-board build
2024-05-09 17:00 ` [PATCH 12/13] i386: select correct components for no-board build Paolo Bonzini
@ 2024-05-10 12:40 ` Zhao Liu
0 siblings, 0 replies; 31+ messages in thread
From: Zhao Liu @ 2024-05-10 12:40 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, thuth
On Thu, May 09, 2024 at 07:00:43PM +0200, Paolo Bonzini wrote:
> Date: Thu, 9 May 2024 19:00:43 +0200
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 12/13] i386: select correct components for no-board build
> X-Mailer: git-send-email 2.45.0
>
> The local APIC is a part of the CPU and has callbacks that are invoked
> from multiple accelerators.
>
> The IOAPIC on the other hand is optional, but ioapic_eoi_broadcast is
> used by common x86 code to implement the IOAPIC's implicit EOI mode.
> Add a stub in case the IOAPIC device is not included but the APIC is.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/intc/ioapic-stub.c | 29 +++++++++++++++++++++++++++++
> .gitlab-ci.d/buildtest.yml | 2 +-
> hw/intc/meson.build | 2 +-
> target/i386/Kconfig | 1 +
> 4 files changed, 32 insertions(+), 2 deletions(-)
> create mode 100644 hw/intc/ioapic-stub.c
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 02/13] s390_flic: add migration-enabled property
2024-05-09 17:00 ` [PATCH 02/13] s390_flic: add migration-enabled property Paolo Bonzini
2024-05-10 5:06 ` Thomas Huth
@ 2024-05-16 14:42 ` Marc Hartmayer
2024-05-17 5:47 ` Thomas Huth
1 sibling, 1 reply; 31+ messages in thread
From: Marc Hartmayer @ 2024-05-16 14:42 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel; +Cc: thuth
On Thu, May 09, 2024 at 07:00 PM +0200, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Instead of mucking with css_migration_enabled(), add a property specific to
> the FLIC device, similar to what is done for TYPE_S390_STATTRIB.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> include/hw/s390x/s390_flic.h | 1 +
> hw/intc/s390_flic.c | 6 +++++-
> hw/s390x/s390-virtio-ccw.c | 1 +
> 3 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
> index 3907a13d076..bcb081def58 100644
> --- a/include/hw/s390x/s390_flic.h
> +++ b/include/hw/s390x/s390_flic.h
> @@ -47,6 +47,7 @@ struct S390FLICState {
> /* to limit AdapterRoutes.num_routes for compat */
> uint32_t adapter_routes_max_batch;
> bool ais_supported;
> + bool migration_enabled;
> };
>
>
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index f4a848460b8..7f930800877 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -405,6 +405,8 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
> static Property s390_flic_common_properties[] = {
> DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState,
> adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI),
> + DEFINE_PROP_BOOL("migration-enabled", S390FLICState,
> + migration_enabled, true),
> DEFINE_PROP_END_OF_LIST(),
> };
>
> @@ -457,7 +459,9 @@ type_init(qemu_s390_flic_register_types)
>
> static bool adapter_info_so_needed(void *opaque)
> {
> - return css_migration_enabled();
> + S390FLICState *fs = S390_FLIC_COMMON(opaque);
> +
> + return fs->migration_enabled;
> }
>
> const VMStateDescription vmstate_adapter_info_so = {
> diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
> index feabc173eb3..1383e47eeb5 100644
> --- a/hw/s390x/s390-virtio-ccw.c
> +++ b/hw/s390x/s390-virtio-ccw.c
> @@ -1174,6 +1174,7 @@ static void ccw_machine_2_9_class_options(MachineClass *mc)
> S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
> static GlobalProperty compat[] = {
> { TYPE_S390_STATTRIB, "migration-enabled", "off", },
> + { TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
> };
>
> ccw_machine_2_10_class_options(mc);
> --
> 2.45.0
>
>
This patch causes QEMU to crash when trying to save the domain state
(e.g. using libvirt)
$ cat dom.xml
<domain type='kvm'>
<name>bug</name>
<memory unit='KiB'>1048576</memory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='s390x' machine='s390-ccw-virtio-9.1'>hvm</type>
<kernel>/var/lib/libvirt/images/hades/vmlinux-s390x</kernel>
<initrd>/var/lib/libvirt/images/hades/ramdisk-s390x</initrd>
</os>
<devices>
<emulator>/usr/bin/qemu-system-s390x</emulator>
<console type='pty'>
<target type='sclp' port='0'/>
</console>
</devices>
</domain>
$ virsh create dom.xml
Domain 'bug' created from dom.xml
$ virsh save bug data
error: Failed to save domain 'bug' to data
error: operation failed: domain is not running
$ coredumpctl gdb
(gdb) bt
#0 object_dynamic_cast_assert (obj=0x2aa364aedd0, typename=typename@entry=0x2aa3491bd56 "s390-flic", file=file@entry=0x2aa34920c7a "/root/git/qemu/include/hw/s390x/s390_flic.h", line=line@entry=42, func=func@entry=0x2aa34a4b964 <__func__.14> "S390_FLIC_COMMON")
at ../qom/object.c:923
#1 0x000002aa3459b518 in S390_FLIC_COMMON (obj=<optimized out>) at /root/git/qemu/include/hw/s390x/s390_flic.h:42
#2 adapter_info_so_needed (opaque=<optimized out>) at ../hw/intc/s390_flic.c:462
#3 0x000002aa348b24dc in vmstate_section_needed (vmsd=0x2aa34c80fe0 <vmstate_adapter_info_so>, opaque=<optimized out>) at ../migration/vmstate.c:330
#4 vmstate_subsection_save (f=0x2aa36602bd0, vmsd=0x2aa34c80f78 <vmstate_adapter_info>, opaque=0x2aa364aedd0, vmdesc=0x0) at ../migration/vmstate.c:528
#5 vmstate_save_state_v (f=f@entry=0x2aa36602bd0, vmsd=0x2aa34c80f78 <vmstate_adapter_info>, opaque=opaque@entry=0x2aa364aedd0, vmdesc=vmdesc@entry=0x0, version_id=version_id@entry=1, errp=0x0) at ../migration/vmstate.c:443
#6 0x000002aa348b2886 in vmstate_save_state (f=0x2aa36602bd0, vmsd=<optimized out>, opaque=0x2aa364aedd0, vmdesc_id=0x0) at ../migration/vmstate.c:341
#7 vmstate_save_state_v (f=f@entry=0x2aa36602bd0, vmsd=0x2aa34c80e50 <vmstate_adapter_routes>, opaque=opaque@entry=0x2aa364aedd0, vmdesc=vmdesc@entry=0x0, version_id=version_id@entry=1, errp=0x0) at ../migration/vmstate.c:401
#8 0x000002aa348b2886 in vmstate_save_state (f=0x2aa36602bd0, vmsd=<optimized out>, opaque=0x2aa364aedd0, vmdesc_id=0x0) at ../migration/vmstate.c:341
#9 vmstate_save_state_v (f=0x2aa36602bd0, vmsd=0x2aa34c6cdf0 <vmstate_virtio_ccw_dev>, opaque=<optimized out>, vmdesc=0x0, version_id=version_id@entry=1, errp=0x0) at ../migration/vmstate.c:401
#10 0x000002aa348b2d7e in vmstate_save_state (f=<optimized out>, vmsd=<optimized out>, opaque=<optimized out>, vmdesc_id=<optimized out>) at ../migration/vmstate.c:341
#11 0x000002aa345c9726 in virtio_save (vdev=0x2aa364afe20, f=0x2aa36602bd0) at ../hw/virtio/virtio.c:2808
#12 0x000002aa348b23de in vmstate_save_state_v (f=f@entry=0x2aa36602bd0, vmsd=0x2aa34c80cd0 <vmstate_virtio_console>, opaque=<optimized out>, vmdesc=vmdesc@entry=0x2aa36602280, version_id=version_id@entry=3, errp=0x3ff73efb438) at ../migration/vmstate.c:408
#13 0x000002aa348b2dbe in vmstate_save_state_with_err (f=f@entry=0x2aa36602bd0, vmsd=<optimized out>, opaque=<optimized out>, vmdesc_id=vmdesc_id@entry=0x2aa36602280, errp=errp@entry=0x3ff73efb438) at ../migration/vmstate.c:347
#14 0x000002aa344993ce in vmstate_save (f=f@entry=0x2aa36602bd0, se=se@entry=0x2aa365cac80, vmdesc=vmdesc@entry=0x2aa36602280, errp=<optimized out>, errp@entry=0x3ff73efb438) at ../migration/savevm.c:1037
#15 0x000002aa3449cb80 in qemu_savevm_state_complete_precopy_non_iterable (f=f@entry=0x2aa36602bd0, in_postcopy=<optimized out>, in_postcopy@entry=false, inactivate_disks=false, inactivate_disks@entry=true) at ../migration/savevm.c:1554
#16 0x000002aa3449d15a in qemu_savevm_state_complete_precopy (f=0x2aa36602bd0, iterable_only=iterable_only@entry=false, inactivate_disks=false) at ../migration/savevm.c:1630
#17 0x000002aa3448ca00 in migration_completion_precopy (s=0x2aa3625d1f0, current_active_state=0x3ff73efb67c) at ../migration/migration.c:2710
#18 migration_completion (s=0x2aa3625d1f0) at ../migration/migration.c:2774
#19 migration_iteration_run (s=0x2aa3625d1f0) at ../migration/migration.c:3198
#20 migration_thread (opaque=opaque@entry=0x2aa3625d1f0) at ../migration/migration.c:3464
#21 0x000002aa3483bc12 in qemu_thread_start (args=<optimized out>) at ../util/qemu-thread-posix.c:541
#22 0x000003ff91bac3fa in start_thread () at /lib64/libc.so.6
#23 0x000003ff91c2bb18 in thread_start () at /lib64/libc.so.6
--
Kind regards / Beste Grüße
Marc Hartmayer
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Wolfgang Wendt
Geschäftsführung: David Faller
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 02/13] s390_flic: add migration-enabled property
2024-05-16 14:42 ` Marc Hartmayer
@ 2024-05-17 5:47 ` Thomas Huth
0 siblings, 0 replies; 31+ messages in thread
From: Thomas Huth @ 2024-05-17 5:47 UTC (permalink / raw)
To: Marc Hartmayer, Paolo Bonzini, qemu-devel; +Cc: qemu-s390x
On 16/05/2024 16.42, Marc Hartmayer wrote:
> On Thu, May 09, 2024 at 07:00 PM +0200, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Instead of mucking with css_migration_enabled(), add a property specific to
>> the FLIC device, similar to what is done for TYPE_S390_STATTRIB.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>> include/hw/s390x/s390_flic.h | 1 +
>> hw/intc/s390_flic.c | 6 +++++-
>> hw/s390x/s390-virtio-ccw.c | 1 +
>> 3 files changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
>> index 3907a13d076..bcb081def58 100644
>> --- a/include/hw/s390x/s390_flic.h
>> +++ b/include/hw/s390x/s390_flic.h
>> @@ -47,6 +47,7 @@ struct S390FLICState {
>> /* to limit AdapterRoutes.num_routes for compat */
>> uint32_t adapter_routes_max_batch;
>> bool ais_supported;
>> + bool migration_enabled;
>> };
>>
>>
>> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
>> index f4a848460b8..7f930800877 100644
>> --- a/hw/intc/s390_flic.c
>> +++ b/hw/intc/s390_flic.c
>> @@ -405,6 +405,8 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
>> static Property s390_flic_common_properties[] = {
>> DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState,
>> adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI),
>> + DEFINE_PROP_BOOL("migration-enabled", S390FLICState,
>> + migration_enabled, true),
>> DEFINE_PROP_END_OF_LIST(),
>> };
>>
>> @@ -457,7 +459,9 @@ type_init(qemu_s390_flic_register_types)
>>
>> static bool adapter_info_so_needed(void *opaque)
>> {
>> - return css_migration_enabled();
>> + S390FLICState *fs = S390_FLIC_COMMON(opaque);
>> +
>> + return fs->migration_enabled;
>> }
...
> This patch causes QEMU to crash when trying to save the domain state
> (e.g. using libvirt)
Oh, drat, that vmstate belongs to a ccw device, not to a flic device, so the
"opaque" pointer in adapter_info_so_needed points to the wrong structure.
I guess the easiest fix is:
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -459,7 +459,7 @@ type_init(qemu_s390_flic_register_types)
static bool adapter_info_so_needed(void *opaque)
{
- S390FLICState *fs = S390_FLIC_COMMON(opaque);
+ S390FLICState *fs = s390_get_flic();
return fs->migration_enabled;
}
I'll send it as a proper patch...
Thomas
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2024-05-17 5:48 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-09 17:00 [PATCH 00/13] fix --without-default-devices build and (mostly) tests Paolo Bonzini
2024-05-09 17:00 ` [PATCH 01/13] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
2024-05-10 4:59 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 02/13] s390_flic: add migration-enabled property Paolo Bonzini
2024-05-10 5:06 ` Thomas Huth
2024-05-16 14:42 ` Marc Hartmayer
2024-05-17 5:47 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 03/13] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
2024-05-10 5:37 ` Thomas Huth
2024-05-10 9:19 ` Paolo Bonzini
2024-05-09 17:00 ` [PATCH 04/13] s390x: select correct components for no-board build Paolo Bonzini
2024-05-10 5:11 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 05/13] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
2024-05-10 5:13 ` Thomas Huth
2024-05-09 17:00 ` [PATCH 06/13] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
2024-05-10 10:18 ` Philippe Mathieu-Daudé
2024-05-09 17:00 ` [PATCH 07/13] xen: register legacy backends via xen_backend_init Paolo Bonzini
2024-05-10 10:52 ` Philippe Mathieu-Daudé
2024-05-09 17:00 ` [PATCH 08/13] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
2024-05-10 12:15 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 09/13] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
2024-05-10 12:05 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 10/13] hw/i386: split x86.c in multiple parts Paolo Bonzini
2024-05-10 12:32 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 11/13] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
2024-05-10 12:37 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 12/13] i386: select correct components for no-board build Paolo Bonzini
2024-05-10 12:40 ` Zhao Liu
2024-05-09 17:00 ` [PATCH 13/13] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
2024-05-10 5:55 ` Thomas Huth
2024-05-10 9:14 ` Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).