* [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10
@ 2024-05-12 10:49 Paolo Bonzini
2024-05-12 10:49 ` [PULL 01/27] target/i386: remove PCOMMIT from TCG, deprecate property Paolo Bonzini
` (27 more replies)
0 siblings, 28 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel
The following changes since commit dafec285bdbfe415ac6823abdc510e0b92c3f094:
Merge tag 'pull-request-2024-05-10' of https://gitlab.com/thuth/qemu into staging (2024-05-10 09:41:35 +0200)
are available in the Git repository at:
https://gitlab.com/bonzini/qemu.git tags/for-upstream
for you to fetch changes up to 9b089d254a5623baef01f7d0ec37331c1155f1ce:
configs: disable emulators that require it if libfdt is not found (2024-05-10 15:45:15 +0200)
----------------------------------------------------------------
* target/i386: miscellaneous changes, mostly TCG-related
* fix --without-default-devices build
* fix --without-default-devices qtests on s390x and arm
----------------------------------------------------------------
Paolo Bonzini (27):
target/i386: remove PCOMMIT from TCG, deprecate property
target/i386: fix operand size for DATA16 REX.W POPCNT
target/i386: rdpkru/wrpkru are no-prefix instructions
target/i386: move prefetch and multi-byte UD/NOP to new decoder
target/i386: fix feature dependency for WAITPKG
tests/tcg: cover lzcnt/tzcnt/popcnt
configure: quote -D options that are passed through to meson
sh4: select correct components for no-board build
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
meson: pick libfdt from common_ss when building target-specific files
meson: move libfdt together with other dependencies
kconfig: allow compiling out QEMU device tree code per target
kconfig: express dependency of individual boards on libfdt
hw/xtensa: require libfdt
configs: disable emulators that require it if libfdt is not found
docs/about/deprecated.rst | 8 +
configure | 2 +-
configs/targets/aarch64-softmmu.mak | 1 +
configs/targets/arm-softmmu.mak | 1 +
configs/targets/i386-softmmu.mak | 1 -
configs/targets/loongarch64-softmmu.mak | 1 +
configs/targets/microblaze-softmmu.mak | 1 +
configs/targets/microblazeel-softmmu.mak | 1 +
configs/targets/mips64el-softmmu.mak | 1 -
configs/targets/or1k-softmmu.mak | 1 +
configs/targets/ppc-softmmu.mak | 1 -
configs/targets/ppc64-softmmu.mak | 1 +
configs/targets/riscv32-softmmu.mak | 1 +
configs/targets/riscv64-softmmu.mak | 1 +
configs/targets/rx-softmmu.mak | 1 +
configs/targets/x86_64-softmmu.mak | 1 -
meson.build | 100 +--
include/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 -
include/monitor/hmp.h | 1 +
include/sysemu/device_tree.h | 1 -
target/i386/cpu.h | 2 -
target/i386/tcg/decode-new.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 +-
hw/xtensa/xtfpga.c | 9 -
monitor/hmp-cmds.c | 17 +
system/device_tree-stub.c | 10 +
system/device_tree.c | 14 -
target/i386/cpu.c | 6 +-
target/i386/tcg/translate.c | 65 +-
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 +
tests/tcg/i386/test-i386.c | 25 +
target/i386/tcg/decode-new.c.inc | 24 +-
target/i386/tcg/emit.c.inc | 5 +
.gitlab-ci.d/buildtest.yml | 9 +-
Kconfig.host | 3 +
hw/arm/Kconfig | 5 +
hw/arm/meson.build | 2 +-
hw/core/Kconfig | 9 +-
hw/core/meson.build | 2 +-
hw/i386/Kconfig | 3 +-
hw/i386/meson.build | 7 +-
hw/intc/meson.build | 2 +-
hw/loongarch/Kconfig | 3 +-
hw/loongarch/meson.build | 2 +-
hw/mips/Kconfig | 3 +-
hw/mips/meson.build | 2 +-
hw/openrisc/Kconfig | 2 +
hw/openrisc/meson.build | 4 +-
hw/ppc/Kconfig | 15 +-
hw/ppc/meson.build | 4 +-
hw/riscv/Kconfig | 4 +
hw/riscv/meson.build | 2 +-
hw/rx/Kconfig | 3 +-
hw/sh4/meson.build | 2 +-
hw/xtensa/Kconfig | 3 +-
system/meson.build | 4 +-
target/arm/Kconfig | 2 +
target/i386/Kconfig | 1 +
target/microblaze/Kconfig | 1 +
target/openrisc/Kconfig | 1 +
target/riscv/Kconfig | 2 +
target/s390x/Kconfig | 2 +
target/sh4/Kconfig | 2 +
90 files changed, 1515 insertions(+), 1334 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
create mode 100644 system/device_tree-stub.c
--
2.45.0
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PULL 01/27] target/i386: remove PCOMMIT from TCG, deprecate property
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 02/27] target/i386: fix operand size for DATA16 REX.W POPCNT Paolo Bonzini
` (26 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
The PCOMMIT instruction was never included in any physical processor.
TCG implements it as a no-op instruction, but its utility is debatable
to say the least. Drop it from the decoder since it is only available
with "-cpu max", which does not guarantee migration compatibility
across versions, and deprecate the property just in case someone is
using it as "pcommit=off".
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
docs/about/deprecated.rst | 8 ++++++++
target/i386/cpu.h | 2 --
target/i386/cpu.c | 2 +-
target/i386/tcg/translate.c | 12 +-----------
4 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 5c3ca47801f..40585ca7d55 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -432,6 +432,14 @@ Backend ``memory`` (since 9.0)
CPU device properties
'''''''''''''''''''''
+``pcommit`` on x86 (since 9.1)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The PCOMMIT instruction was never included in any physical processor.
+It was implemented as a no-op instruction in TCG up to QEMU 9.0, but
+only with ``-cpu max`` (which does not guarantee migration compatibility
+across versions).
+
``pmu-num=n`` on RISC-V CPUs (since 8.2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 1e0d2c915f5..ccccb62fc35 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -816,8 +816,6 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define CPUID_7_0_EBX_SMAP (1U << 20)
/* AVX-512 Integer Fused Multiply Add */
#define CPUID_7_0_EBX_AVX512IFMA (1U << 21)
-/* Persistent Commit */
-#define CPUID_7_0_EBX_PCOMMIT (1U << 22)
/* Flush a Cache Line Optimized */
#define CPUID_7_0_EBX_CLFLUSHOPT (1U << 23)
/* Cache Line Write Back */
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1058b6803fd..79372de8c5a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -713,7 +713,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
#endif
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
- CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
+ CPUID_7_0_EBX_CLFLUSHOPT | \
CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE | \
CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_RDSEED | \
CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_KERNEL_FEATURES)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3842b294842..7d9f6b5c55b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4487,17 +4487,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
goto unknown_op;
- case 0xf8: /* sfence / pcommit */
- if (prefixes & PREFIX_DATA) {
- /* pcommit */
- if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
- || (prefixes & PREFIX_LOCK)) {
- goto illegal_op;
- }
- break;
- }
- /* fallthru */
- case 0xf9 ... 0xff: /* sfence */
+ case 0xf8 ... 0xff: /* sfence */
if (!(s->cpuid_features & CPUID_SSE)
|| (prefixes & PREFIX_LOCK)) {
goto illegal_op;
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 02/27] target/i386: fix operand size for DATA16 REX.W POPCNT
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
2024-05-12 10:49 ` [PULL 01/27] target/i386: remove PCOMMIT from TCG, deprecate property Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 03/27] target/i386: rdpkru/wrpkru are no-prefix instructions Paolo Bonzini
` (25 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Zhao Liu, Richard Henderson
According to the manual, 32-bit vs 64-bit is governed by REX.W
and REX ignores the 0x66 prefix. This can be confirmed with this
program:
#include <stdio.h>
int main()
{
int x = 0x12340000;
int y;
asm("popcntl %1, %0" : "=r" (y) : "r" (x)); printf("%x\n", y);
asm("mov $-1, %0; .byte 0x66; popcntl %1, %0" : "+r" (y) : "r" (x)); printf("%x\n", y);
asm("mov $-1, %0; .byte 0x66; popcntq %q1, %q0" : "+r" (y) : "r" (x)); printf("%x\n", y);
}
which prints 5/ffff0000/5 on real hardware and 5/ffff0000/ffff0000
on QEMU.
Cc: qemu-stable@nongnu.org
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 7d9f6b5c55b..5366dc32dd3 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -411,16 +411,6 @@ static inline MemOp mo_stacksize(DisasContext *s)
return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
}
-/* Select only size 64 else 32. Used for SSE operand sizes. */
-static inline MemOp mo_64_32(MemOp ot)
-{
-#ifdef TARGET_X86_64
- return ot == MO_64 ? MO_64 : MO_32;
-#else
- return MO_32;
-#endif
-}
-
/* Select size 8 if lsb of B is clear, else OT. Used for decoding
byte vs word opcodes. */
static inline MemOp mo_b_d(int b, MemOp ot)
@@ -4545,12 +4535,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
modrm = x86_ldub_code(env, s);
reg = ((modrm >> 3) & 7) | REX_R(s);
- if (s->prefix & PREFIX_DATA) {
- ot = MO_16;
- } else {
- ot = mo_64_32(dflag);
- }
-
+ ot = dflag;
gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
gen_extu(ot, s->T0);
tcg_gen_mov_tl(cpu_cc_src, s->T0);
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 03/27] target/i386: rdpkru/wrpkru are no-prefix instructions
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
2024-05-12 10:49 ` [PULL 01/27] target/i386: remove PCOMMIT from TCG, deprecate property Paolo Bonzini
2024-05-12 10:49 ` [PULL 02/27] target/i386: fix operand size for DATA16 REX.W POPCNT Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 04/27] target/i386: move prefetch and multi-byte UD/NOP to new decoder Paolo Bonzini
` (24 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Richard Henderson
Reject 0x66/0xf3/0xf2 in front of them.
Cc: qemu-stable@nongnu.org
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5366dc32dd3..3da4fdf64cc 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -3907,7 +3907,8 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
break;
case 0xee: /* rdpkru */
- if (prefixes & PREFIX_LOCK) {
+ if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
+ | PREFIX_REPZ | PREFIX_REPNZ)) {
goto illegal_op;
}
tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
@@ -3915,7 +3916,8 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64);
break;
case 0xef: /* wrpkru */
- if (prefixes & PREFIX_LOCK) {
+ if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
+ | PREFIX_REPZ | PREFIX_REPNZ)) {
goto illegal_op;
}
tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 04/27] target/i386: move prefetch and multi-byte UD/NOP to new decoder
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (2 preceding siblings ...)
2024-05-12 10:49 ` [PULL 03/27] target/i386: rdpkru/wrpkru are no-prefix instructions Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 05/27] target/i386: fix feature dependency for WAITPKG Paolo Bonzini
` (23 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Zhao Liu
These are trivial to add, and moving them to the new decoder fixes some
corner cases: raising #UD instead of an instruction fetch page fault for
the undefined opcodes, and incorrectly rejecting 0F 18 prefetches with
register operands (which are treated as reserved NOPs).
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 1 +
target/i386/tcg/translate.c | 30 ------------------------------
target/i386/tcg/decode-new.c.inc | 24 +++++++++++++++++++++---
target/i386/tcg/emit.c.inc | 5 +++++
4 files changed, 27 insertions(+), 33 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 2ea06b44787..51ef0e621b9 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -50,6 +50,7 @@ typedef enum X86OpType {
X86_TYPE_EM, /* modrm byte selects an ALU memory operand */
X86_TYPE_WM, /* modrm byte selects an XMM/YMM memory operand */
X86_TYPE_I_unsigned, /* Immediate, zero-extended */
+ X86_TYPE_nop, /* modrm operand decoded but not loaded into s->T{0,1} */
X86_TYPE_2op, /* 2-operand RMW instruction */
X86_TYPE_LoBits, /* encoded in bits 0-2 of the operand + REX.B */
X86_TYPE_0, /* Hard-coded GPRs (RAX..RDI) */
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 3da4fdf64cc..de87775016b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4019,25 +4019,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
set_cc_op(s, CC_OP_EFLAGS);
}
break;
- case 0x118:
- modrm = x86_ldub_code(env, s);
- mod = (modrm >> 6) & 3;
- op = (modrm >> 3) & 7;
- switch(op) {
- case 0: /* prefetchnta */
- case 1: /* prefetchnt0 */
- case 2: /* prefetchnt0 */
- case 3: /* prefetchnt0 */
- if (mod == 3)
- goto illegal_op;
- gen_nop_modrm(env, s, modrm);
- /* nothing more to do */
- break;
- default: /* nop (multi byte) */
- gen_nop_modrm(env, s, modrm);
- break;
- }
- break;
case 0x11a:
modrm = x86_ldub_code(env, s);
if (s->flags & HF_MPX_EN_MASK) {
@@ -4229,10 +4210,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
gen_nop_modrm(env, s, modrm);
break;
- case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
- modrm = x86_ldub_code(env, s);
- gen_nop_modrm(env, s, modrm);
- break;
case 0x120: /* mov reg, crN */
case 0x122: /* mov crN, reg */
@@ -4506,13 +4483,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
break;
- case 0x10d: /* 3DNow! prefetch(w) */
- modrm = x86_ldub_code(env, s);
- mod = (modrm >> 6) & 3;
- if (mod == 3)
- goto illegal_op;
- gen_nop_modrm(env, s, modrm);
- break;
case 0x1aa: /* rsm */
gen_svm_check_intercept(s, SVM_EXIT_RSM);
if (!(s->flags & HF_SMM_MASK))
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 0e1811399f8..141ab2bc560 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -55,6 +55,10 @@
* mask could be applied (and the original sign-extended value would be
* optimized away by TCG) in the emitter function.
*
+ * Finally, a "nop" operand type is used for multi-byte NOPs. It accepts
+ * any value of mod including 11b (unlike M) but it does not try to
+ * interpret the operand (like M).
+ *
* Vector operands
* ---------------
*
@@ -1056,6 +1060,16 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
[0xa1] = X86_OP_ENTRYw(POP, FS, w),
+ [0x0b] = X86_OP_ENTRY0(UD), /* UD2 */
+ [0x0d] = X86_OP_ENTRY1(NOP, M,v), /* 3DNow! prefetch */
+
+ [0x18] = X86_OP_ENTRY1(NOP, nop,v), /* prefetch/reserved NOP */
+ [0x19] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
+ [0x1c] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
+ [0x1d] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
+ [0x1e] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
+ [0x1f] = X86_OP_ENTRY1(NOP, nop,v), /* NOP/reserved NOP */
+
[0x28] = X86_OP_ENTRY3(MOVDQ, V,x, None,None, W,x, vex1 p_00_66), /* MOVAPS */
[0x29] = X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1 p_00_66), /* MOVAPS */
[0x2A] = X86_OP_GROUP0(0F2A),
@@ -1135,6 +1149,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0xb6] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, zextT0), /* MOVZX */
[0xb7] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, zextT0), /* MOVZX */
+ /* decoded as modrm, which is visible as a difference between page fault and #UD */
+ [0xb9] = X86_OP_ENTRYr(UD, nop,v), /* UD1 */
[0xbe] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, sextT0), /* MOVSX */
[0xbf] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, sextT0), /* MOVSX */
@@ -1206,7 +1222,7 @@ static const X86OpEntry opcodes_0F[256] = {
[0xfc] = X86_OP_ENTRY3(PADDB, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
[0xfd] = X86_OP_ENTRY3(PADDW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
[0xfe] = X86_OP_ENTRY3(PADDD, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- /* 0xff = UD0 */
+ [0xff] = X86_OP_ENTRYr(UD, nop,v), /* UD0 */
};
static void do_decode_0F(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
@@ -1852,6 +1868,8 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
if ((modrm >> 6) == 3) {
return false;
}
+ /* fall through */
+ case X86_TYPE_nop: /* modrm operand decoded but not fetched */
get_modrm:
decode_modrm(s, env, decode, op, type);
break;
@@ -2397,8 +2415,8 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
switch (b) {
case 0x00 ... 0x03: /* mostly privileged instructions */
case 0x05 ... 0x09:
- case 0x0d: /* 3DNow! prefetch */
- case 0x18 ... 0x23: /* prefetch, MPX, mov from/to CR and DR */
+ case 0x1a ... 0x1b: /* MPX */
+ case 0x20 ... 0x23: /* mov from/to CR and DR */
case 0x30 ... 0x35: /* more privileged instructions */
case 0xa2 ... 0xa5: /* CPUID, BT, SHLD */
case 0xaa ... 0xae: /* RSM, SHRD, grp15 */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 58f255873ff..2dee33dd487 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -3517,6 +3517,11 @@ static void gen_SUB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_SUBB + ot);
}
+static void gen_UD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+{
+ gen_illegal_opcode(s);
+}
+
static void gen_VAESIMC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
{
assert(!s->vex_l);
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 05/27] target/i386: fix feature dependency for WAITPKG
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (3 preceding siblings ...)
2024-05-12 10:49 ` [PULL 04/27] target/i386: move prefetch and multi-byte UD/NOP to new decoder Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 06/27] tests/tcg: cover lzcnt/tzcnt/popcnt Paolo Bonzini
` (22 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Zhao Liu
The VMX feature bit depends on general availability of WAITPKG,
not the other way round.
Fixes: 33cc88261c3 ("target/i386: add support for VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE", 2023-08-28)
Cc: qemu-stable@nongnu.org
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 79372de8c5a..cfe7c92d6bc 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1551,8 +1551,8 @@ static FeatureDep feature_dependencies[] = {
.to = { FEAT_SVM, ~0ull },
},
{
- .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
- .to = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
+ .from = { FEAT_7_0_ECX, CPUID_7_0_ECX_WAITPKG },
+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
},
};
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 06/27] tests/tcg: cover lzcnt/tzcnt/popcnt
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (4 preceding siblings ...)
2024-05-12 10:49 ` [PULL 05/27] target/i386: fix feature dependency for WAITPKG Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 07/27] configure: quote -D options that are passed through to meson Paolo Bonzini
` (21 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Zhao Liu
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
tests/tcg/i386/test-i386.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
index 864c4e620d5..ce3bf74b5a8 100644
--- a/tests/tcg/i386/test-i386.c
+++ b/tests/tcg/i386/test-i386.c
@@ -715,6 +715,30 @@ void test_mul(void)
printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
}
+void test_xcnt(void)
+{
+ TEST_BSX(tzcntw, "w", 0);
+ TEST_BSX(tzcntw, "w", 0x12340128);
+ TEST_BSX(lzcntw, "w", 0);
+ TEST_BSX(lzcntw, "w", 0x12340128);
+ TEST_BSX(popcntw, "w", 0);
+ TEST_BSX(popcntw, "w", 0x12340128);
+ TEST_BSX(tzcntl, "k", 0);
+ TEST_BSX(tzcntl, "k", 0x00340128);
+ TEST_BSX(lzcntl, "k", 0);
+ TEST_BSX(lzcntl, "k", 0x00340128);
+ TEST_BSX(popcntl, "k", 0);
+ TEST_BSX(popcntl, "k", 0x00340128);
+#if defined(__x86_64__)
+ TEST_BSX(tzcntq, "", 0);
+ TEST_BSX(tzcntq, "", 0x003401281234);
+ TEST_BSX(lzcntq, "", 0);
+ TEST_BSX(lzcntq, "", 0x003401281234);
+ TEST_BSX(popcntq, "", 0);
+ TEST_BSX(popcntq, "", 0x003401281234);
+#endif
+}
+
void test_bsx(void)
{
TEST_BSX(bsrw, "w", 0);
@@ -2162,6 +2186,7 @@ int main(int argc, char **argv)
func();
}
test_bsx();
+ test_xcnt();
test_mul();
test_jcc();
test_loop();
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 07/27] configure: quote -D options that are passed through to meson
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (5 preceding siblings ...)
2024-05-12 10:49 ` [PULL 06/27] tests/tcg: cover lzcnt/tzcnt/popcnt Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 08/27] sh4: select correct components for no-board build Paolo Bonzini
` (20 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Thomas Huth
Ensure that they go through unmodified, instead of removing one layer
of quoting.
-D is a pretty specialized option and most options that can have spaces
do not need it (for example, c_args is covered by --extra-cflags).
Therefore it's unlikely that this causes actual trouble. However,
a somewhat realistic failure case would be with -Dpkg_config_path
and a pkg-config directory that contains spaces.
Cc: qemu-stable@nongnu.org
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configure | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure b/configure
index 1dca3d94c04..330664786dc 100755
--- a/configure
+++ b/configure
@@ -762,7 +762,7 @@ for opt do
--*) meson_option_parse "$opt" "$optarg"
;;
# Pass through -Dxxxx options to meson
- -D*) meson_options="$meson_options $opt"
+ -D*) meson_option_add "$opt"
;;
esac
done
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 08/27] sh4: select correct components for no-board build
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (6 preceding siblings ...)
2024-05-12 10:49 ` [PULL 07/27] configure: quote -D options that are passed through to meson Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 09/27] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
` (19 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Alex Bennée
Acked-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
.gitlab-ci.d/buildtest.yml | 5 +++--
hw/sh4/meson.build | 2 +-
target/sh4/Kconfig | 2 ++
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 9836d81c24d..786c8f92090 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
# Check our reduced build configurations
# requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
# mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, s390x, sh4, sh4eb, x86_64
+# does not build without boards: i386, s390x, x86_64
build-without-defaults:
extends: .native_build_job_template
needs:
@@ -665,7 +665,8 @@ build-without-defaults:
--disable-qom-cast-debug
--disable-strip
TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
- mips-softmmu mips64-softmmu mipsel-softmmu sparc-softmmu
+ mips-softmmu mips64-softmmu mipsel-softmmu
+ sh4-softmmu sh4eb-softmmu sparc-softmmu
sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
hexagon-linux-user i386-linux-user s390x-linux-user
MAKE_CHECK_ARGS: check
diff --git a/hw/sh4/meson.build b/hw/sh4/meson.build
index 424d5674dea..70e814c3a28 100644
--- a/hw/sh4/meson.build
+++ b/hw/sh4/meson.build
@@ -1,5 +1,5 @@
sh4_ss = ss.source_set()
-sh4_ss.add(files(
+sh4_ss.add(when: 'CONFIG_SH7750', if_true: files(
'sh7750.c',
'sh7750_regnames.c',
))
diff --git a/target/sh4/Kconfig b/target/sh4/Kconfig
index 2397c860280..93b92f1e480 100644
--- a/target/sh4/Kconfig
+++ b/target/sh4/Kconfig
@@ -1,2 +1,4 @@
config SH4
bool
+ # needed for sh_intc_get_pending_vector
+ select SH_INTC
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 09/27] s390x: move s390_cpu_addr2state to target/s390x/sigp.c
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (7 preceding siblings ...)
2024-05-12 10:49 ` [PULL 08/27] sh4: select correct components for no-board build Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 10/27] s390_flic: add migration-enabled property Paolo Bonzini
` (18 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Thomas Huth
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>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20240509170044.190795-2-pbonzini@redhat.com>
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 2afaf45ce60..42628fc45d2 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -50,22 +50,6 @@
static Error *pv_mig_blocker;
-S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
-{
- static MachineState *ms;
-
- if (!ms) {
- ms = MACHINE(qdev_get_machine());
- g_assert(ms->possible_cpus);
- }
-
- /* CPU address corresponds to the core_id and the index */
- if (cpu_addr >= ms->possible_cpus->len) {
- return NULL;
- }
- return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
-}
-
static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
Error **errp)
{
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index 9dd977349ab..ad0ad61177d 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "s390x-internal.h"
+#include "hw/boards.h"
#include "sysemu/hw_accel.h"
#include "sysemu/runstate.h"
#include "exec/address-spaces.h"
@@ -435,6 +436,22 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
return SIGP_CC_STATUS_STORED;
}
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
+{
+ static MachineState *ms;
+
+ if (!ms) {
+ ms = MACHINE(qdev_get_machine());
+ g_assert(ms->possible_cpus);
+ }
+
+ /* CPU address corresponds to the core_id and the index */
+ if (cpu_addr >= ms->possible_cpus->len) {
+ return NULL;
+ }
+ return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
+}
+
int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
{
uint64_t *status_reg = &env->regs[r1];
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 10/27] s390_flic: add migration-enabled property
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (8 preceding siblings ...)
2024-05-12 10:49 ` [PULL 09/27] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 11/27] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
` (17 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Thomas Huth
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>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20240509170044.190795-3-pbonzini@redhat.com>
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 42628fc45d2..756b4f40aed 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -1182,6 +1182,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] 29+ messages in thread
* [PULL 11/27] s390: move css_migration_enabled from machine to css.c
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (9 preceding siblings ...)
2024-05-12 10:49 ` [PULL 10/27] s390_flic: add migration-enabled property Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 12/27] s390x: select correct components for no-board build Paolo Bonzini
` (16 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel
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>
Message-ID: <20240509170044.190795-4-pbonzini@redhat.com>
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 7605d06bff1..996864a34e2 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -46,7 +46,6 @@ struct S390CcwMachineClass {
/*< public >*/
bool ri_allowed;
bool cpu_model_allowed;
- bool css_migration_enabled;
bool hpage_1m_allowed;
int max_threads;
};
@@ -58,10 +57,4 @@ bool cpu_model_allowed(void);
/* 1M huge page mappings allowed by the machine */
bool hpage_1m_allowed(void);
-/**
- * Returns true if (vmstate based) migration of the channel subsystem
- * is enabled, false if it is disabled.
- */
-bool css_migration_enabled(void);
-
#endif
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 295530963a6..b2d5327dbf4 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -23,6 +23,8 @@
#include "hw/s390x/s390-virtio-ccw.h"
#include "hw/s390x/s390-ccw.h"
+bool css_migration_enabled = true;
+
typedef struct CrwContainer {
CRW crw;
QTAILQ_ENTRY(CrwContainer) sibling;
@@ -180,7 +182,7 @@ static const VMStateDescription vmstate_orb = {
static bool vmstate_schdev_orb_needed(void *opaque)
{
- return css_migration_enabled();
+ return css_migration_enabled;
}
static const VMStateDescription vmstate_schdev_orb = {
@@ -388,7 +390,7 @@ static int subch_dev_post_load(void *opaque, int version_id)
css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s);
}
- if (css_migration_enabled()) {
+ if (css_migration_enabled) {
/* No compat voodoo to do ;) */
return 0;
}
@@ -412,7 +414,9 @@ static int subch_dev_post_load(void *opaque, int version_id)
void css_register_vmstate(void)
{
- vmstate_register(NULL, 0, &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 756b4f40aed..3d0bc3e7f2e 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -283,11 +283,9 @@ static void ccw_init(MachineState *machine)
s390_enable_css_support(s390_cpu_addr2state(0));
ret = css_create_css_image(VIRTUAL_CSSID, true);
-
assert(ret == 0);
- if (css_migration_enabled()) {
- css_register_vmstate();
- }
+
+ css_register_vmstate();
/* Create VirtIO network adapters */
s390_create_virtio_net(BUS(css_bus), mc->default_nic);
@@ -749,7 +747,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
s390mc->ri_allowed = true;
s390mc->cpu_model_allowed = true;
- s390mc->css_migration_enabled = true;
s390mc->hpage_1m_allowed = true;
s390mc->max_threads = 1;
mc->init = ccw_init;
@@ -819,11 +816,6 @@ static const TypeInfo ccw_machine_info = {
},
};
-bool css_migration_enabled(void)
-{
- return get_machine_class()->css_migration_enabled;
-}
-
#define DEFINE_CCW_MACHINE(suffix, verstr, latest) \
static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \
void *data) \
@@ -1179,7 +1171,6 @@ static void ccw_machine_2_9_instance_options(MachineState *machine)
static void ccw_machine_2_9_class_options(MachineClass *mc)
{
- S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
static GlobalProperty compat[] = {
{ TYPE_S390_STATTRIB, "migration-enabled", "off", },
{ TYPE_S390_FLIC_COMMON, "migration-enabled", "off", },
@@ -1188,7 +1179,7 @@ static void ccw_machine_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] 29+ messages in thread
* [PULL 12/27] s390x: select correct components for no-board build
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (10 preceding siblings ...)
2024-05-12 10:49 ` [PULL 11/27] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 13/27] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
` (15 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Thomas Huth
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20240509170044.190795-5-pbonzini@redhat.com>
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 786c8f92090..8ca3e0586c7 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -650,7 +650,7 @@ build-tci:
# Check our reduced build configurations
# requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
# mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
-# does not build without boards: i386, s390x, x86_64
+# does not build without boards: i386, x86_64
build-without-defaults:
extends: .native_build_job_template
needs:
@@ -666,7 +666,7 @@ build-without-defaults:
--disable-strip
TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
mips-softmmu mips64-softmmu mipsel-softmmu
- sh4-softmmu sh4eb-softmmu sparc-softmmu
+ s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
hexagon-linux-user i386-linux-user s390x-linux-user
MAKE_CHECK_ARGS: check
diff --git a/target/s390x/Kconfig b/target/s390x/Kconfig
index 72da48136c6..d886be48b47 100644
--- a/target/s390x/Kconfig
+++ b/target/s390x/Kconfig
@@ -1,2 +1,4 @@
config S390X
bool
+ select PCI
+ select S390_FLIC
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 13/27] tests/qtest: s390x: fix operation in a build without any boards or devices
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (11 preceding siblings ...)
2024-05-12 10:49 ` [PULL 12/27] s390x: select correct components for no-board build Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 14/27] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
` (14 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Thomas Huth
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>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20240509170044.190795-6-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 14/27] xen: initialize legacy backends from xen_bus_init()
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (12 preceding siblings ...)
2024-05-12 10:49 ` [PULL 13/27] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 15/27] xen: register legacy backends via xen_backend_init Paolo Bonzini
` (13 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
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>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20240509170044.190795-7-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 15/27] xen: register legacy backends via xen_backend_init
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (13 preceding siblings ...)
2024-05-12 10:49 ` [PULL 14/27] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 16/27] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
` (12 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
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>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20240509170044.190795-8-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 16/27] i386: correctly select code in hw/i386 that depends on other components
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (14 preceding siblings ...)
2024-05-12 10:49 ` [PULL 15/27] xen: register legacy backends via xen_backend_init Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 17/27] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
` (11 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Zhao Liu
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>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240509170044.190795-9-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 17/27] i386: pc: remove unnecessary MachineClass overrides
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (15 preceding siblings ...)
2024-05-12 10:49 ` [PULL 16/27] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 18/27] hw/i386: split x86.c in multiple parts Paolo Bonzini
` (10 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Zhao Liu
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>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240509170044.190795-10-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 18/27] hw/i386: split x86.c in multiple parts
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (16 preceding siblings ...)
2024-05-12 10:49 ` [PULL 17/27] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 19/27] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
` (9 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Zhao Liu
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>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240509170044.190795-11-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 19/27] hw/i386: move rtc-reset-reinjection command out of hw/rtc
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (17 preceding siblings ...)
2024-05-12 10:49 ` [PULL 18/27] hw/i386: split x86.c in multiple parts Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 20/27] i386: select correct components for no-board build Paolo Bonzini
` (8 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Zhao Liu
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>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240509170044.190795-12-pbonzini@redhat.com>
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] 29+ messages in thread
* [PULL 20/27] i386: select correct components for no-board build
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (18 preceding siblings ...)
2024-05-12 10:49 ` [PULL 19/27] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 21/27] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
` (7 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Zhao Liu
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>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240509170044.190795-13-pbonzini@redhat.com>
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 8ca3e0586c7..7af5c1ce8ad 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] 29+ messages in thread
* [PULL 21/27] tests/qtest: arm: fix operation in a build without any boards or devices
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (19 preceding siblings ...)
2024-05-12 10:49 ` [PULL 20/27] i386: select correct components for no-board build Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 22/27] meson: pick libfdt from common_ss when building target-specific files Paolo Bonzini
` (6 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Thomas Huth
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>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20240509170044.190795-14-pbonzini@redhat.com>
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 7a1345f80f8..e8d3555f56b 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -781,6 +781,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] 29+ messages in thread
* [PULL 22/27] meson: pick libfdt from common_ss when building target-specific files
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (20 preceding siblings ...)
2024-05-12 10:49 ` [PULL 21/27] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 23/27] meson: move libfdt together with other dependencies Paolo Bonzini
` (5 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Avoid having to list dependencies such as libfdt twice, both on common_ss
and specific_ss. Instead, just take all the dependencies in common_ss
and allow the target-specific libqemu-*.fa library to use them.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 14 +++++++++++---
hw/arm/meson.build | 2 +-
hw/loongarch/meson.build | 2 +-
hw/mips/meson.build | 2 +-
hw/openrisc/meson.build | 4 ++--
hw/ppc/meson.build | 4 +---
hw/riscv/meson.build | 2 +-
7 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/meson.build b/meson.build
index 83ae4347c7f..ab1f44b25c2 100644
--- a/meson.build
+++ b/meson.build
@@ -3867,15 +3867,23 @@ foreach target : target_dirs
target_common = common_ss.apply(config_target, strict: false)
objects = common_all.extract_objects(target_common.sources())
- deps = target_common.dependencies()
+ arch_deps += target_common.dependencies()
target_specific = specific_ss.apply(config_target, strict: false)
arch_srcs += target_specific.sources()
arch_deps += target_specific.dependencies()
+ # allow using headers from the dependencies but do not include the sources,
+ # because this emulator only needs those in "objects". For external
+ # dependencies, the full dependency is included below in the executable.
+ lib_deps = []
+ foreach dep : arch_deps
+ lib_deps += dep.partial_dependency(compile_args: true, includes: true)
+ endforeach
+
lib = static_library('qemu-' + target,
sources: arch_srcs + genh,
- dependencies: arch_deps,
+ dependencies: lib_deps,
objects: objects,
include_directories: target_inc,
c_args: c_args,
@@ -3923,7 +3931,7 @@ foreach target : target_dirs
emulator = executable(exe_name, exe['sources'],
install: true,
c_args: c_args,
- dependencies: arch_deps + deps + exe['dependencies'],
+ dependencies: arch_deps + exe['dependencies'],
objects: lib.extract_all_objects(recursive: true),
link_depends: [block_syms, qemu_syms],
link_args: link_args,
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 6808135c1f7..aefde0c69a3 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -1,5 +1,5 @@
arm_ss = ss.source_set()
-arm_ss.add(files('boot.c'), fdt)
+arm_ss.add(files('boot.c'))
arm_ss.add(when: 'CONFIG_ARM_VIRT', if_true: files('virt.c'))
arm_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
arm_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic_boards.c'))
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index d306d82c2ee..bce7ebac97e 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -3,7 +3,7 @@ loongarch_ss.add(files(
'fw_cfg.c',
'boot.c',
))
-loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('virt.c'), fdt])
+loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: files('virt.c'))
loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
hw_arch += {'loongarch': loongarch_ss}
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index f06d88f3430..ca37c42d900 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -9,7 +9,7 @@ if 'CONFIG_TCG' in config_all_accel
mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c'))
mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
-mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: [files('boston.c'), fdt])
+mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: files('boston.c'))
endif
hw_arch += {'mips': mips_ss}
diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build
index 2dbc6365bb7..82f1f0ef1cc 100644
--- a/hw/openrisc/meson.build
+++ b/hw/openrisc/meson.build
@@ -1,7 +1,7 @@
openrisc_ss = ss.source_set()
openrisc_ss.add(files('cputimer.c'))
openrisc_ss.add(files('boot.c'))
-openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), fdt])
-openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt])
+openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: files('openrisc_sim.c'))
+openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: files('virt.c'))
hw_arch += {'openrisc': openrisc_ss}
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index d096636ee7f..3ebbf329bcc 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -3,9 +3,7 @@ ppc_ss.add(files(
'ppc.c',
'ppc_booke.c',
))
-ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: [files(
- 'fdt.c',
-), fdt])
+ppc_ss.add(when: 'CONFIG_FDT_PPC', if_true: files('fdt.c'))
ppc_ss.add(when: 'CONFIG_FW_CFG_PPC', if_true: files('fw_cfg.c'))
# IBM pSeries (sPAPR)
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 2f7ee81be3c..f872674093a 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -1,5 +1,5 @@
riscv_ss = ss.source_set()
-riscv_ss.add(files('boot.c'), fdt)
+riscv_ss.add(files('boot.c'))
riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c'))
riscv_ss.add(files('riscv_hart.c'))
riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c'))
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 23/27] meson: move libfdt together with other dependencies
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (21 preceding siblings ...)
2024-05-12 10:49 ` [PULL 22/27] meson: pick libfdt from common_ss when building target-specific files Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 24/27] kconfig: allow compiling out QEMU device tree code per target Paolo Bonzini
` (4 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Move the libfdt detection code together with other dependencies instead
of keeping it with subprojects. This has the disadvantage of performing
the detection even if no target requires libfdt; but it has the advantage
that Kconfig will be able to observe the availability of the library.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 79 ++++++++++++++++++++++++++---------------------------
1 file changed, 38 insertions(+), 41 deletions(-)
diff --git a/meson.build b/meson.build
index ab1f44b25c2..dd4a28f8f8f 100644
--- a/meson.build
+++ b/meson.build
@@ -1858,6 +1858,34 @@ if numa.found() and not cc.links('''
endif
endif
+fdt = not_found
+fdt_opt = get_option('fdt')
+if fdt_opt == 'enabled' and get_option('wrap_mode') == 'nodownload'
+ fdt_opt = 'system'
+endif
+if fdt_opt in ['enabled', 'system'] or (fdt_opt == 'auto' and have_system)
+ fdt = cc.find_library('fdt', required: fdt_opt == 'system')
+ if fdt.found() and cc.links('''
+ #include <libfdt.h>
+ #include <libfdt_env.h>
+ int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
+ dependencies: fdt)
+ fdt_opt = 'system'
+ elif fdt_opt != 'system'
+ fdt_opt = get_option('wrap_mode') == 'nodownload' ? 'disabled' : 'internal'
+ fdt = not_found
+ else
+ error('system libfdt is too old (1.5.1 or newer required)')
+ endif
+endif
+if fdt_opt == 'internal'
+ assert(not fdt.found())
+ libfdt_proj = subproject('dtc', required: true,
+ default_options: ['tools=false', 'yaml=disabled',
+ 'python=disabled', 'default_library=static'])
+ fdt = libfdt_proj.get_variable('libfdt_dep')
+endif
+
rdma = not_found
if not get_option('rdma').auto() or have_system
libumad = cc.find_library('ibumad', required: get_option('rdma'))
@@ -2199,6 +2227,7 @@ config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
config_host_data.set('CONFIG_CAPSTONE', capstone.found())
config_host_data.set('CONFIG_COCOA', cocoa.found())
config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
+config_host_data.set('CONFIG_FDT', fdt.found())
config_host_data.set('CONFIG_FUZZ', get_option('fuzzing'))
config_host_data.set('CONFIG_GCOV', get_option('b_coverage'))
config_host_data.set('CONFIG_LIBUDEV', libudev.found())
@@ -3024,14 +3053,16 @@ foreach target : target_dirs
error('No accelerator available for target @0@'.format(target))
endif
- actual_target_dirs += target
config_target += keyval.load('configs/targets' / target + '.mak')
config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
- if 'TARGET_NEED_FDT' in config_target
+ if 'TARGET_NEED_FDT' in config_target and not fdt.found()
fdt_required += target
+ continue
endif
+ actual_target_dirs += target
+
# Add default keys
if 'TARGET_BASE_ARCH' not in config_target
config_target += {'TARGET_BASE_ARCH': config_target['TARGET_ARCH']}
@@ -3119,6 +3150,10 @@ genh += custom_target('config-poison.h',
command: [find_program('scripts/make-config-poison.sh'),
target_configs_h])
+if fdt_required.length() > 0
+ error('fdt disabled but required by targets ' + ', '.join(fdt_required))
+endif
+
###############
# Subprojects #
###############
@@ -3129,44 +3164,6 @@ if have_system and vfio_user_server_allowed
libvfio_user_dep = libvfio_user_proj.get_variable('libvfio_user_dep')
endif
-fdt = not_found
-fdt_opt = get_option('fdt')
-if fdt_required.length() > 0 or fdt_opt == 'enabled'
- if fdt_opt == 'disabled'
- error('fdt disabled but required by targets ' + ', '.join(fdt_required))
- endif
-
- if fdt_opt in ['enabled', 'auto', 'system']
- if get_option('wrap_mode') == 'nodownload'
- fdt_opt = 'system'
- endif
- fdt = cc.find_library('fdt', required: fdt_opt == 'system')
- if fdt.found() and cc.links('''
- #include <libfdt.h>
- #include <libfdt_env.h>
- int main(void) { fdt_find_max_phandle(NULL, NULL); return 0; }''',
- dependencies: fdt)
- fdt_opt = 'system'
- elif fdt_opt == 'system'
- error('system libfdt requested, but it is too old (1.5.1 or newer required)')
- else
- fdt_opt = 'internal'
- fdt = not_found
- endif
- endif
- if not fdt.found()
- assert(fdt_opt == 'internal')
- libfdt_proj = subproject('dtc', required: true,
- default_options: ['tools=false', 'yaml=disabled',
- 'python=disabled', 'default_library=static'])
- fdt = libfdt_proj.get_variable('libfdt_dep')
- endif
-else
- fdt_opt = 'disabled'
-endif
-
-config_host_data.set('CONFIG_FDT', fdt.found())
-
vhost_user = not_found
if host_os == 'linux' and have_vhost_user
libvhost_user = subproject('libvhost-user')
@@ -4417,7 +4414,7 @@ summary_info += {'Linux AIO support': libaio}
summary_info += {'Linux io_uring support': linux_io_uring}
summary_info += {'ATTR/XATTR support': libattr}
summary_info += {'RDMA support': rdma}
-summary_info += {'fdt support': fdt_opt == 'disabled' ? false : fdt_opt}
+summary_info += {'fdt support': fdt_opt == 'internal' ? 'internal' : fdt}
summary_info += {'libcap-ng support': libcap_ng}
summary_info += {'bpf support': libbpf}
summary_info += {'rbd support': rbd}
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 24/27] kconfig: allow compiling out QEMU device tree code per target
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (22 preceding siblings ...)
2024-05-12 10:49 ` [PULL 23/27] meson: move libfdt together with other dependencies Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 25/27] kconfig: express dependency of individual boards on libfdt Paolo Bonzini
` (3 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel
Introduce a new Kconfig symbol, CONFIG_DEVICE_TREE, that specifies whether
to include the common device tree code in system/device_tree.c and to
link to libfdt. For now, include it unconditionally if libfdt is
available.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 1 +
include/monitor/hmp.h | 1 +
include/sysemu/device_tree.h | 1 -
monitor/hmp-cmds.c | 17 +++++++++++++++++
system/device_tree-stub.c | 10 ++++++++++
system/device_tree.c | 14 --------------
Kconfig.host | 4 ++++
hw/core/Kconfig | 9 ++++++++-
hw/core/meson.build | 2 +-
system/meson.build | 4 +++-
10 files changed, 45 insertions(+), 18 deletions(-)
create mode 100644 system/device_tree-stub.c
diff --git a/meson.build b/meson.build
index dd4a28f8f8f..8b90ea6cf70 100644
--- a/meson.build
+++ b/meson.build
@@ -2989,6 +2989,7 @@ host_kconfig = \
(have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \
(opengl.found() ? ['CONFIG_OPENGL=y'] : []) + \
(x11.found() ? ['CONFIG_X11=y'] : []) + \
+ (fdt.found() ? ['CONFIG_FDT=y'] : []) + \
(have_vhost_user ? ['CONFIG_VHOST_USER=y'] : []) + \
(have_vhost_vdpa ? ['CONFIG_VHOST_VDPA=y'] : []) + \
(have_vhost_kernel ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index f4cf8f6717d..954f3c83ad9 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -180,5 +180,6 @@ void hmp_ioport_write(Monitor *mon, const QDict *qdict);
void hmp_boot_set(Monitor *mon, const QDict *qdict);
void hmp_info_mtree(Monitor *mon, const QDict *qdict);
void hmp_info_cryptodev(Monitor *mon, const QDict *qdict);
+void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
#endif
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index 8eab3959341..eb601522f88 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -134,7 +134,6 @@ int qemu_fdt_add_path(void *fdt, const char *path);
} while (0)
void qemu_fdt_dumpdtb(void *fdt, int size);
-void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
/**
* qemu_fdt_setprop_sized_cells_from_array:
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 871898ac46b..ea79148ee85 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -22,6 +22,7 @@
#include "monitor/monitor-internal.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-control.h"
+#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qmp/qdict.h"
#include "qemu/cutils.h"
@@ -443,3 +444,19 @@ void hmp_info_mtree(Monitor *mon, const QDict *qdict)
mtree_info(flatview, dispatch_tree, owner, disabled);
}
+
+#if defined(CONFIG_FDT)
+void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
+{
+ const char *filename = qdict_get_str(qdict, "filename");
+ Error *local_err = NULL;
+
+ qmp_dumpdtb(filename, &local_err);
+
+ if (hmp_handle_error(mon, local_err)) {
+ return;
+ }
+
+ monitor_printf(mon, "dtb dumped to %s", filename);
+}
+#endif
diff --git a/system/device_tree-stub.c b/system/device_tree-stub.c
new file mode 100644
index 00000000000..bddda6fa37a
--- /dev/null
+++ b/system/device_tree-stub.c
@@ -0,0 +1,10 @@
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-machine.h"
+
+#ifdef CONFIG_FDT
+void qmp_dumpdtb(const char *filename, Error **errp)
+{
+ error_setg(errp, "This machine doesn't have a FDT");
+}
+#endif
diff --git a/system/device_tree.c b/system/device_tree.c
index eb5166ca360..2e38259d34f 100644
--- a/system/device_tree.c
+++ b/system/device_tree.c
@@ -668,20 +668,6 @@ void qmp_dumpdtb(const char *filename, Error **errp)
}
}
-void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
-{
- const char *filename = qdict_get_str(qdict, "filename");
- Error *local_err = NULL;
-
- qmp_dumpdtb(filename, &local_err);
-
- if (hmp_handle_error(mon, local_err)) {
- return;
- }
-
- info_report("dtb dumped to %s", filename);
-}
-
void qemu_fdt_randomize_seeds(void *fdt)
{
int noffset, poffset, len;
diff --git a/Kconfig.host b/Kconfig.host
index f6a2a131e6c..a0d4a52131e 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -23,6 +23,10 @@ config IVSHMEM
config TPM
bool
+config FDT
+ bool
+ select DEVICE_TREE
+
config VHOST_USER
bool
diff --git a/hw/core/Kconfig b/hw/core/Kconfig
index 9397503656d..24411f59306 100644
--- a/hw/core/Kconfig
+++ b/hw/core/Kconfig
@@ -4,8 +4,14 @@ config EMPTY_SLOT
config PTIMER
bool
+config DEVICE_TREE
+ bool
+ # fail the build if libfdt not found
+ depends on FDT
+
config FITLOADER
bool
+ depends on DEVICE_TREE
config GENERIC_LOADER
bool
@@ -14,13 +20,14 @@ config GENERIC_LOADER
config GUEST_LOADER
bool
default y
- depends on TCG
+ depends on TCG && DEVICE_TREE
config OR_IRQ
bool
config PLATFORM_BUS
bool
+ depends on DEVICE_TREE
config REGISTER
bool
diff --git a/hw/core/meson.build b/hw/core/meson.build
index f20d4143f7a..a3d9bab9f42 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -16,7 +16,7 @@ common_ss.add(files('cpu-common.c'))
common_ss.add(files('machine-smp.c'))
system_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
system_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
-system_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
+system_ss.add(when: 'CONFIG_GUEST_LOADER', if_true: files('guest-loader.c'))
system_ss.add(when: 'CONFIG_OR_IRQ', if_true: files('or-irq.c'))
system_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('platform-bus.c'))
system_ss.add(when: 'CONFIG_PTIMER', if_true: files('ptimer.c'))
diff --git a/system/meson.build b/system/meson.build
index 25e21172505..a296270cb00 100644
--- a/system/meson.build
+++ b/system/meson.build
@@ -32,7 +32,9 @@ if have_tpm
endif
system_ss.add(when: seccomp, if_true: files('qemu-seccomp.c'))
-system_ss.add(when: fdt, if_true: files('device_tree.c'))
+system_ss.add(when: 'CONFIG_DEVICE_TREE',
+ if_true: [fdt, files('device_tree.c')],
+ if_false: files('device_tree-stub.c'))
if host_os == 'linux'
system_ss.add(files('async-teardown.c'))
endif
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 25/27] kconfig: express dependency of individual boards on libfdt
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (23 preceding siblings ...)
2024-05-12 10:49 ` [PULL 24/27] kconfig: allow compiling out QEMU device tree code per target Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 26/27] hw/xtensa: require libfdt Paolo Bonzini
` (2 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Now that boards are enabled by default and the "CONFIG_FOO=y"
entries are gone from configs/devices/, there cannot be any more
a conflicts between the default contents of configs/devices/
and a failed "depends on" clause.
With this change, each individual board or target can express
whether it needs FDT. It can then include the common code in the
build via "select DEVICE_TREE", which will also as tell meson to link
with libfdt.
This allows building non-microvm x86 emulators without having
libfdt available.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
Kconfig.host | 1 -
hw/arm/Kconfig | 5 +++++
hw/i386/Kconfig | 3 ++-
hw/loongarch/Kconfig | 3 ++-
hw/mips/Kconfig | 3 ++-
hw/openrisc/Kconfig | 2 ++
hw/ppc/Kconfig | 15 ++++++++-------
hw/riscv/Kconfig | 4 ++++
hw/rx/Kconfig | 3 ++-
hw/xtensa/Kconfig | 1 +
target/arm/Kconfig | 2 ++
target/microblaze/Kconfig | 1 +
target/openrisc/Kconfig | 1 +
target/riscv/Kconfig | 2 ++
14 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/Kconfig.host b/Kconfig.host
index a0d4a52131e..17f405004b3 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -25,7 +25,6 @@ config TPM
config FDT
bool
- select DEVICE_TREE
config VHOST_USER
bool
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 98c264ed219..8b97683a45e 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -15,6 +15,7 @@ config ARM_VIRT
select ACPI
select ARM_SMMUV3
select GPIO_KEY
+ select DEVICE_TREE
select FW_CFG_DMA
select PCI_EXPRESS
select PCI_EXPRESS_GENERIC_BRIDGE
@@ -265,6 +266,7 @@ config SBSA_REF
default y
depends on TCG && AARCH64
imply PCI_DEVICES
+ select DEVICE_TREE
select AHCI
select ARM_SMMUV3
select GPIO_KEY
@@ -347,6 +349,7 @@ config VEXPRESS
bool
default y
depends on TCG && ARM
+ select DEVICE_TREE
select A9MPCORE
select A15MPCORE
select ARM_MPTIMER
@@ -492,6 +495,7 @@ config XLNX_ZYNQMP_ARM
select CPU_CLUSTER
select DDC
select DPCD
+ select DEVICE_TREE
select SDHCI
select SSI
select SSI_M25P80
@@ -509,6 +513,7 @@ config XLNX_VERSAL
depends on TCG && AARCH64
select ARM_GIC
select CPU_CLUSTER
+ select DEVICE_TREE
select PL011
select CADENCE
select VIRTIO_MMIO
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index 40b1e445808..f4a33b6c082 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -115,7 +115,8 @@ config Q35
config MICROVM
bool
default y
- depends on I386
+ depends on I386 && FDT
+ select DEVICE_TREE
select SERIAL_ISA # for serial_hds_isa_init()
select ISA_BUS
select APIC
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index ad77502445a..90a0dba9d59 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -1,7 +1,8 @@
config LOONGARCH_VIRT
bool
default y
- depends on LOONGARCH64
+ depends on LOONGARCH64 && FDT
+ select DEVICE_TREE
select PCI
select PCI_EXPRESS_GENERIC_BRIDGE
imply VIRTIO_VGA
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 9bccb363eb9..a7f26edebe8 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -80,9 +80,10 @@ config MIPS_CPS
config MIPS_BOSTON
bool
default y
- depends on MIPS64 && !TARGET_BIG_ENDIAN
+ depends on MIPS64 && !TARGET_BIG_ENDIAN && FDT
imply PCI_DEVICES
imply TEST_DEVICES
+ select DEVICE_TREE
select FITLOADER
select MIPS_CPS
select PCI_EXPRESS_XILINX
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
index 9c9015e0a5d..76b953c62c2 100644
--- a/hw/openrisc/Kconfig
+++ b/hw/openrisc/Kconfig
@@ -2,6 +2,7 @@ config OR1K_SIM
bool
default y
depends on OPENRISC
+ select DEVICE_TREE
select SERIAL
select OPENCORES_ETH
select OMPIC
@@ -14,6 +15,7 @@ config OR1K_VIRT
imply PCI_DEVICES
imply VIRTIO_VGA
imply TEST_DEVICES
+ select DEVICE_TREE
select PCI
select PCI_EXPRESS_GENERIC_BRIDGE
select GOLDFISH_RTC
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index 78f83e78ce5..347212f4dba 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -1,7 +1,7 @@
config PSERIES
bool
default y
- depends on PPC64
+ depends on PPC64 && FDT
imply USB_OHCI_PCI
imply PCI_DEVICES
imply TEST_DEVICES
@@ -26,7 +26,7 @@ config SPAPR_RNG
config POWERNV
bool
default y
- depends on PPC64
+ depends on PPC64 && FDT
imply PCI_DEVICES
imply TEST_DEVICES
select ISA_IPMI_BT
@@ -52,7 +52,7 @@ config PPC405
config PPC440
bool
default y
- depends on PPC
+ depends on PPC && FDT
imply PCI_DEVICES
imply TEST_DEVICES
imply E1000_PCI
@@ -71,7 +71,7 @@ config PPC4XX
config SAM460EX
bool
default y
- depends on PPC
+ depends on PPC && FDT
select PFLASH_CFI01
select IDE_SII3112
select M41T80
@@ -168,19 +168,19 @@ config E500
config E500PLAT
bool
default y
- depends on PPC
+ depends on PPC && FDT
select E500
config MPC8544DS
bool
default y
- depends on PPC
+ depends on PPC && FDT
select E500
config VIRTEX
bool
default y
- depends on PPC
+ depends on PPC && FDT
select PPC4XX
select PFLASH_CFI01
select SERIAL
@@ -193,6 +193,7 @@ config FW_CFG_PPC
bool
config FDT_PPC
+ select DEVICE_TREE
bool
config VOF
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 5f5f9e31bb0..a2030e3a6ff 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -12,6 +12,7 @@ config MICROCHIP_PFSOC
depends on RISCV64
select CADENCE_SDHCI
select CPU_CLUSTER
+ select DEVICE_TREE
select MCHP_PFSOC_DMC
select MCHP_PFSOC_IOSCB
select MCHP_PFSOC_MMUART
@@ -37,6 +38,7 @@ config RISCV_VIRT
imply VIRTIO_VGA
imply TEST_DEVICES
imply TPM_TIS_SYSBUS
+ select DEVICE_TREE
select RISCV_NUMA
select GOLDFISH_RTC
select PCI
@@ -82,6 +84,7 @@ config SIFIVE_U
depends on RISCV32 || RISCV64
select CADENCE
select CPU_CLUSTER
+ select DEVICE_TREE
select RISCV_ACLINT
select SIFIVE_GPIO
select SIFIVE_PDMA
@@ -99,6 +102,7 @@ config SPIKE
bool
default y
depends on RISCV32 || RISCV64
+ select DEVICE_TREE
select RISCV_NUMA
select HTIF
select RISCV_ACLINT
diff --git a/hw/rx/Kconfig b/hw/rx/Kconfig
index b2fa2b7eec3..aa9242d1ef6 100644
--- a/hw/rx/Kconfig
+++ b/hw/rx/Kconfig
@@ -8,5 +8,6 @@ config RX62N_MCU
config RX_GDBSIM
bool
default y
- depends on RX
+ depends on RX && FDT
+ select DEVICE_TREE
select RX62N_MCU
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
index 443b415c2ba..8ea283a7a3b 100644
--- a/hw/xtensa/Kconfig
+++ b/hw/xtensa/Kconfig
@@ -15,6 +15,7 @@ config XTENSA_XTFPGA
bool
default y
depends on XTENSA
+ imply DEVICE_TREE
select OPENCORES_ETH
select PFLASH_CFI01
select SERIAL
diff --git a/target/arm/Kconfig b/target/arm/Kconfig
index 5847c5a74a7..7f8a2217ae1 100644
--- a/target/arm/Kconfig
+++ b/target/arm/Kconfig
@@ -6,6 +6,8 @@ config ARM
# translate.c v7m helpers under ARM_V7M.
select ARM_V7M if TCG
+ select DEVICE_TREE # needed by boot.c
+
config AARCH64
bool
select ARM
diff --git a/target/microblaze/Kconfig b/target/microblaze/Kconfig
index a5410d9218d..e91d58d88f2 100644
--- a/target/microblaze/Kconfig
+++ b/target/microblaze/Kconfig
@@ -1,2 +1,3 @@
config MICROBLAZE
bool
+ select DEVICE_TREE # needed by boot.c
diff --git a/target/openrisc/Kconfig b/target/openrisc/Kconfig
index e0da4ac1dfc..cd66c2e3b6c 100644
--- a/target/openrisc/Kconfig
+++ b/target/openrisc/Kconfig
@@ -1,2 +1,3 @@
config OPENRISC
bool
+ select DEVICE_TREE # needed by boot.c
diff --git a/target/riscv/Kconfig b/target/riscv/Kconfig
index adb7de3f37d..5f30df22f2f 100644
--- a/target/riscv/Kconfig
+++ b/target/riscv/Kconfig
@@ -1,7 +1,9 @@
config RISCV32
bool
select ARM_COMPATIBLE_SEMIHOSTING # for do_common_semihosting()
+ select DEVICE_TREE # needed by boot.c
config RISCV64
bool
select ARM_COMPATIBLE_SEMIHOSTING # for do_common_semihosting()
+ select DEVICE_TREE # needed by boot.c
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 26/27] hw/xtensa: require libfdt
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (24 preceding siblings ...)
2024-05-12 10:49 ` [PULL 25/27] kconfig: express dependency of individual boards on libfdt Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-12 10:49 ` [PULL 27/27] configs: disable emulators that require it if libfdt is not found Paolo Bonzini
2024-05-14 8:51 ` [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Richard Henderson
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
All other boards require libfdt if it can be used (including for example
i386/x86_64), so change the "imply" to "select" and always allow -dtb
in qemu-system-xtensa.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/xtensa/xtfpga.c | 9 ---------
hw/xtensa/Kconfig | 4 ++--
2 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index f49e6591dc2..955e8867a36 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -356,7 +356,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE,
strlen(kernel_cmdline) + 1, kernel_cmdline);
}
-#ifdef CONFIG_FDT
if (dtb_filename) {
int fdt_size;
void *fdt = load_device_tree(dtb_filename, &fdt_size);
@@ -373,14 +372,6 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4 * KiB);
g_free(fdt);
}
-#else
- if (dtb_filename) {
- error_report("could not load DTB '%s': "
- "FDT support is not configured in QEMU",
- dtb_filename);
- exit(EXIT_FAILURE);
- }
-#endif
if (initrd_filename) {
BpMemInfo initrd_location = { 0 };
int initrd_size = load_ramdisk(initrd_filename, cur_lowmem,
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
index 8ea283a7a3b..fc5c785cfac 100644
--- a/hw/xtensa/Kconfig
+++ b/hw/xtensa/Kconfig
@@ -14,8 +14,8 @@ config XTENSA_VIRT
config XTENSA_XTFPGA
bool
default y
- depends on XTENSA
- imply DEVICE_TREE
+ depends on XTENSA && FDT
+ select DEVICE_TREE
select OPENCORES_ETH
select PFLASH_CFI01
select SERIAL
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PULL 27/27] configs: disable emulators that require it if libfdt is not found
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (25 preceding siblings ...)
2024-05-12 10:49 ` [PULL 26/27] hw/xtensa: require libfdt Paolo Bonzini
@ 2024-05-12 10:49 ` Paolo Bonzini
2024-05-14 8:51 ` [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Richard Henderson
27 siblings, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2024-05-12 10:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Since boards can express their dependency on libfdt and
system/device_tree.c, only leave TARGET_NEED_FDT if the target has a
hard dependency.
Those emulators will be skipped if libfdt is disabled, or if it
is "auto" and not found and --disable-download is passed; unless
the target is mentioned explicitly in --target-list, in which case
the build will fail.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configs/targets/aarch64-softmmu.mak | 1 +
configs/targets/arm-softmmu.mak | 1 +
configs/targets/i386-softmmu.mak | 1 -
configs/targets/loongarch64-softmmu.mak | 1 +
configs/targets/microblaze-softmmu.mak | 1 +
configs/targets/microblazeel-softmmu.mak | 1 +
configs/targets/mips64el-softmmu.mak | 1 -
configs/targets/or1k-softmmu.mak | 1 +
configs/targets/ppc-softmmu.mak | 1 -
configs/targets/ppc64-softmmu.mak | 1 +
configs/targets/riscv32-softmmu.mak | 1 +
configs/targets/riscv64-softmmu.mak | 1 +
configs/targets/rx-softmmu.mak | 1 +
configs/targets/x86_64-softmmu.mak | 1 -
meson.build | 6 +++++-
.gitlab-ci.d/buildtest.yml | 8 ++++----
16 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/configs/targets/aarch64-softmmu.mak b/configs/targets/aarch64-softmmu.mak
index 83c22391a69..84cb32dc2f4 100644
--- a/configs/targets/aarch64-softmmu.mak
+++ b/configs/targets/aarch64-softmmu.mak
@@ -3,4 +3,5 @@ TARGET_BASE_ARCH=arm
TARGET_SUPPORTS_MTTCG=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml gdb-xml/aarch64-pauth.xml
+# needed by boot.c
TARGET_NEED_FDT=y
diff --git a/configs/targets/arm-softmmu.mak b/configs/targets/arm-softmmu.mak
index 92c8349b964..bf390b7a8de 100644
--- a/configs/targets/arm-softmmu.mak
+++ b/configs/targets/arm-softmmu.mak
@@ -1,4 +1,5 @@
TARGET_ARCH=arm
TARGET_SUPPORTS_MTTCG=y
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
+# needed by boot.c
TARGET_NEED_FDT=y
diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index d61b5076134..2ac69d5ba37 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,5 +1,4 @@
TARGET_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
-TARGET_NEED_FDT=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_XML_FILES= gdb-xml/i386-32bit.xml
diff --git a/configs/targets/loongarch64-softmmu.mak b/configs/targets/loongarch64-softmmu.mak
index f23780fdd89..84beb19b90a 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -2,4 +2,5 @@ TARGET_ARCH=loongarch64
TARGET_BASE_ARCH=loongarch
TARGET_SUPPORTS_MTTCG=y
TARGET_XML_FILES= gdb-xml/loongarch-base32.xml gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu.xml
+# all boards require libfdt
TARGET_NEED_FDT=y
diff --git a/configs/targets/microblaze-softmmu.mak b/configs/targets/microblaze-softmmu.mak
index e84c0cc7283..eea266d4f3d 100644
--- a/configs/targets/microblaze-softmmu.mak
+++ b/configs/targets/microblaze-softmmu.mak
@@ -1,5 +1,6 @@
TARGET_ARCH=microblaze
TARGET_BIG_ENDIAN=y
TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
TARGET_NEED_FDT=y
TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/microblazeel-softmmu.mak b/configs/targets/microblazeel-softmmu.mak
index 9b688036bd3..77b968acad3 100644
--- a/configs/targets/microblazeel-softmmu.mak
+++ b/configs/targets/microblazeel-softmmu.mak
@@ -1,4 +1,5 @@
TARGET_ARCH=microblaze
TARGET_SUPPORTS_MTTCG=y
+# needed by boot.c
TARGET_NEED_FDT=y
TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml
diff --git a/configs/targets/mips64el-softmmu.mak b/configs/targets/mips64el-softmmu.mak
index 8d9ab3ddc4b..3864daa7364 100644
--- a/configs/targets/mips64el-softmmu.mak
+++ b/configs/targets/mips64el-softmmu.mak
@@ -1,3 +1,2 @@
TARGET_ARCH=mips64
TARGET_BASE_ARCH=mips
-TARGET_NEED_FDT=y
diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak
index 432f855a30a..0341cb2a6b3 100644
--- a/configs/targets/or1k-softmmu.mak
+++ b/configs/targets/or1k-softmmu.mak
@@ -1,4 +1,5 @@
TARGET_ARCH=openrisc
TARGET_SUPPORTS_MTTCG=y
TARGET_BIG_ENDIAN=y
+# needed by boot.c and all boards
TARGET_NEED_FDT=y
diff --git a/configs/targets/ppc-softmmu.mak b/configs/targets/ppc-softmmu.mak
index f3ea9c98f75..53120dab41d 100644
--- a/configs/targets/ppc-softmmu.mak
+++ b/configs/targets/ppc-softmmu.mak
@@ -2,4 +2,3 @@ TARGET_ARCH=ppc
TARGET_BIG_ENDIAN=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_XML_FILES= gdb-xml/power-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml
-TARGET_NEED_FDT=y
diff --git a/configs/targets/ppc64-softmmu.mak b/configs/targets/ppc64-softmmu.mak
index 1db8d8381d0..40881d93968 100644
--- a/configs/targets/ppc64-softmmu.mak
+++ b/configs/targets/ppc64-softmmu.mak
@@ -4,4 +4,5 @@ TARGET_BIG_ENDIAN=y
TARGET_SUPPORTS_MTTCG=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_XML_FILES= gdb-xml/power64-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml gdb-xml/power-vsx.xml
+# all boards require libfdt
TARGET_NEED_FDT=y
diff --git a/configs/targets/riscv32-softmmu.mak b/configs/targets/riscv32-softmmu.mak
index d8b71cddcd4..338182d5b89 100644
--- a/configs/targets/riscv32-softmmu.mak
+++ b/configs/targets/riscv32-softmmu.mak
@@ -2,4 +2,5 @@ TARGET_ARCH=riscv32
TARGET_BASE_ARCH=riscv
TARGET_SUPPORTS_MTTCG=y
TARGET_XML_FILES= gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-32bit-virtual.xml
+# needed by boot.c
TARGET_NEED_FDT=y
diff --git a/configs/targets/riscv64-softmmu.mak b/configs/targets/riscv64-softmmu.mak
index 7c0e7eeb429..f688ffa7bce 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -2,4 +2,5 @@ TARGET_ARCH=riscv64
TARGET_BASE_ARCH=riscv
TARGET_SUPPORTS_MTTCG=y
TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+# needed by boot.c
TARGET_NEED_FDT=y
diff --git a/configs/targets/rx-softmmu.mak b/configs/targets/rx-softmmu.mak
index 0c458b2d07c..706bbe6062c 100644
--- a/configs/targets/rx-softmmu.mak
+++ b/configs/targets/rx-softmmu.mak
@@ -1,3 +1,4 @@
TARGET_ARCH=rx
TARGET_XML_FILES= gdb-xml/rx-core.xml
+# all boards require libfdt
TARGET_NEED_FDT=y
diff --git a/configs/targets/x86_64-softmmu.mak b/configs/targets/x86_64-softmmu.mak
index c5f882e5ba1..e12ac3dc59b 100644
--- a/configs/targets/x86_64-softmmu.mak
+++ b/configs/targets/x86_64-softmmu.mak
@@ -1,6 +1,5 @@
TARGET_ARCH=x86_64
TARGET_BASE_ARCH=i386
TARGET_SUPPORTS_MTTCG=y
-TARGET_NEED_FDT=y
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_XML_FILES= gdb-xml/i386-64bit.xml
diff --git a/meson.build b/meson.build
index 8b90ea6cf70..9c141925144 100644
--- a/meson.build
+++ b/meson.build
@@ -3058,7 +3058,11 @@ foreach target : target_dirs
config_target += { 'TARGET_' + config_target['TARGET_ARCH'].to_upper(): 'y' }
if 'TARGET_NEED_FDT' in config_target and not fdt.found()
- fdt_required += target
+ if default_targets
+ warning('Disabling ' + target + ' due to missing libfdt')
+ else
+ fdt_required += target
+ endif
continue
endif
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 7af5c1ce8ad..372404fc85f 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -648,8 +648,8 @@ build-tci:
- make check-tcg
# Check our reduced build configurations
-# requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
-# mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
+# requires libfdt: aarch64, arm, loongarch64, microblaze, microblazeel,
+# or1k, ppc64, riscv32, riscv64, rx
# fails qtest without boards: i386, x86_64
build-without-defaults:
extends: .native_build_job_template
@@ -665,8 +665,8 @@ build-without-defaults:
--disable-qom-cast-debug
--disable-strip
TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
- mips-softmmu mips64-softmmu mipsel-softmmu
- s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
+ mips-softmmu mips64-softmmu mipsel-softmmu mips64el-softmmu
+ ppc-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
--
2.45.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
` (26 preceding siblings ...)
2024-05-12 10:49 ` [PULL 27/27] configs: disable emulators that require it if libfdt is not found Paolo Bonzini
@ 2024-05-14 8:51 ` Richard Henderson
27 siblings, 0 replies; 29+ messages in thread
From: Richard Henderson @ 2024-05-14 8:51 UTC (permalink / raw)
To: qemu-devel
On 5/12/24 12:49, Paolo Bonzini wrote:
> The following changes since commit dafec285bdbfe415ac6823abdc510e0b92c3f094:
>
> Merge tag 'pull-request-2024-05-10' ofhttps://gitlab.com/thuth/qemu into staging (2024-05-10 09:41:35 +0200)
>
> are available in the Git repository at:
>
> https://gitlab.com/bonzini/qemu.git tags/for-upstream
>
> for you to fetch changes up to 9b089d254a5623baef01f7d0ec37331c1155f1ce:
>
> configs: disable emulators that require it if libfdt is not found (2024-05-10 15:45:15 +0200)
>
> ----------------------------------------------------------------
> * target/i386: miscellaneous changes, mostly TCG-related
> * fix --without-default-devices build
> * fix --without-default-devices qtests on s390x and arm
Applied, thanks. Please update https://wiki.qemu.org/ChangeLog/9.1 as appropriate.
r~
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2024-05-14 8:52 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-12 10:49 [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Paolo Bonzini
2024-05-12 10:49 ` [PULL 01/27] target/i386: remove PCOMMIT from TCG, deprecate property Paolo Bonzini
2024-05-12 10:49 ` [PULL 02/27] target/i386: fix operand size for DATA16 REX.W POPCNT Paolo Bonzini
2024-05-12 10:49 ` [PULL 03/27] target/i386: rdpkru/wrpkru are no-prefix instructions Paolo Bonzini
2024-05-12 10:49 ` [PULL 04/27] target/i386: move prefetch and multi-byte UD/NOP to new decoder Paolo Bonzini
2024-05-12 10:49 ` [PULL 05/27] target/i386: fix feature dependency for WAITPKG Paolo Bonzini
2024-05-12 10:49 ` [PULL 06/27] tests/tcg: cover lzcnt/tzcnt/popcnt Paolo Bonzini
2024-05-12 10:49 ` [PULL 07/27] configure: quote -D options that are passed through to meson Paolo Bonzini
2024-05-12 10:49 ` [PULL 08/27] sh4: select correct components for no-board build Paolo Bonzini
2024-05-12 10:49 ` [PULL 09/27] s390x: move s390_cpu_addr2state to target/s390x/sigp.c Paolo Bonzini
2024-05-12 10:49 ` [PULL 10/27] s390_flic: add migration-enabled property Paolo Bonzini
2024-05-12 10:49 ` [PULL 11/27] s390: move css_migration_enabled from machine to css.c Paolo Bonzini
2024-05-12 10:49 ` [PULL 12/27] s390x: select correct components for no-board build Paolo Bonzini
2024-05-12 10:49 ` [PULL 13/27] tests/qtest: s390x: fix operation in a build without any boards or devices Paolo Bonzini
2024-05-12 10:49 ` [PULL 14/27] xen: initialize legacy backends from xen_bus_init() Paolo Bonzini
2024-05-12 10:49 ` [PULL 15/27] xen: register legacy backends via xen_backend_init Paolo Bonzini
2024-05-12 10:49 ` [PULL 16/27] i386: correctly select code in hw/i386 that depends on other components Paolo Bonzini
2024-05-12 10:49 ` [PULL 17/27] i386: pc: remove unnecessary MachineClass overrides Paolo Bonzini
2024-05-12 10:49 ` [PULL 18/27] hw/i386: split x86.c in multiple parts Paolo Bonzini
2024-05-12 10:49 ` [PULL 19/27] hw/i386: move rtc-reset-reinjection command out of hw/rtc Paolo Bonzini
2024-05-12 10:49 ` [PULL 20/27] i386: select correct components for no-board build Paolo Bonzini
2024-05-12 10:49 ` [PULL 21/27] tests/qtest: arm: fix operation in a build without any boards or devices Paolo Bonzini
2024-05-12 10:49 ` [PULL 22/27] meson: pick libfdt from common_ss when building target-specific files Paolo Bonzini
2024-05-12 10:49 ` [PULL 23/27] meson: move libfdt together with other dependencies Paolo Bonzini
2024-05-12 10:49 ` [PULL 24/27] kconfig: allow compiling out QEMU device tree code per target Paolo Bonzini
2024-05-12 10:49 ` [PULL 25/27] kconfig: express dependency of individual boards on libfdt Paolo Bonzini
2024-05-12 10:49 ` [PULL 26/27] hw/xtensa: require libfdt Paolo Bonzini
2024-05-12 10:49 ` [PULL 27/27] configs: disable emulators that require it if libfdt is not found Paolo Bonzini
2024-05-14 8:51 ` [PULL 00/27] Build/arch cleanups, target/i386 fixes for 2024-05-10 Richard Henderson
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).