From 78be258c0eeba3d5613c37888889e84f2ba9bd94 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 3 Jul 2024 13:42:49 +0200 Subject: [PATCH 01/13] target/i386: add sha512, sm3, sm4 feature bits SHA512, SM3, SM4 (CPUID[EAX=7,ECX=1).EAX bits 0 to 2) is supported by Clearwater Forest processor, add it to QEMU as it does not need any specific enablement. See https://lore.kernel.org/kvm/20241105054825.870939-1-tao1.su@linux.intel.com/ for reference. Reviewed-by: Tao Su Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 58c96eafea..3725dbbc4b 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1116,7 +1116,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { [FEAT_7_1_EAX] = { .type = CPUID_FEATURE_WORD, .feat_names = { - NULL, NULL, NULL, NULL, + "sha512", "sm3", "sm4", NULL, "avx-vnni", "avx512-bf16", NULL, "cmpccxadd", NULL, NULL, "fzrm", "fsrs", "fsrc", NULL, NULL, NULL, From 520c0bb2be47275961ec83bbc95205c7be064589 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Mon, 4 Nov 2024 14:21:02 -0800 Subject: [PATCH 02/13] target/i386/hvf: fix clang compilation warning ../target/i386/hvf/x86_cpuid.c:35:28: error: a function declaration without a prototype is deprecated in all versions of C Fixes: 7cac7aa7040a823c585f1578a38f28e83c8bf3e1 Signed-off-by: Pierrick Bouvier Link: https://lore.kernel.org/r/20241104222102.1522688-1-pierrick.bouvier@linaro.org Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_cpuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index 3a116548a3..492e8bfc80 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -32,7 +32,7 @@ static bool cached_xcr0; static uint64_t supported_xcr0; -static void cache_host_xcr0() +static void cache_host_xcr0(void) { if (cached_xcr0) { return; From 700784bfc65496551e15ccebff5ac30b6d13f492 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 6 Nov 2024 16:21:39 +0100 Subject: [PATCH 03/13] rust: add meson_version to all subprojects Otherwise, newer releases of meson complain. Reviewed-by: Pierrick Bouvier Signed-off-by: Paolo Bonzini --- subprojects/packagefiles/arbitrary-int-1-rs/meson.build | 1 + subprojects/packagefiles/bilge-0.2-rs/meson.build | 1 + subprojects/packagefiles/bilge-impl-0.2-rs/meson.build | 1 + subprojects/packagefiles/either-1-rs/meson.build | 1 + subprojects/packagefiles/itertools-0.11-rs/meson.build | 1 + subprojects/packagefiles/proc-macro-error-1-rs/meson.build | 1 + subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build | 1 + subprojects/packagefiles/proc-macro2-1-rs/meson.build | 1 + subprojects/packagefiles/quote-1-rs/meson.build | 1 + subprojects/packagefiles/syn-2-rs/meson.build | 1 + subprojects/packagefiles/unicode-ident-1-rs/meson.build | 1 + 11 files changed, 11 insertions(+) diff --git a/subprojects/packagefiles/arbitrary-int-1-rs/meson.build b/subprojects/packagefiles/arbitrary-int-1-rs/meson.build index 34a189cbae..cff3f62ce7 100644 --- a/subprojects/packagefiles/arbitrary-int-1-rs/meson.build +++ b/subprojects/packagefiles/arbitrary-int-1-rs/meson.build @@ -1,4 +1,5 @@ project('arbitrary-int-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.2.7', license: 'MIT', default_options: []) diff --git a/subprojects/packagefiles/bilge-0.2-rs/meson.build b/subprojects/packagefiles/bilge-0.2-rs/meson.build index a6ed4a8f0c..e69bac91b4 100644 --- a/subprojects/packagefiles/bilge-0.2-rs/meson.build +++ b/subprojects/packagefiles/bilge-0.2-rs/meson.build @@ -1,6 +1,7 @@ project( 'bilge-0.2-rs', 'rust', + meson_version: '>=1.5.0', version : '0.2.0', license : 'MIT or Apache-2.0', ) diff --git a/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build b/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build index 80243c7024..f8f3486fc0 100644 --- a/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build +++ b/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build @@ -1,4 +1,5 @@ project('bilge-impl-0.2-rs', 'rust', + meson_version: '>=1.5.0', version: '0.2.0', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/either-1-rs/meson.build b/subprojects/packagefiles/either-1-rs/meson.build index a5842eb3a6..608e64e31f 100644 --- a/subprojects/packagefiles/either-1-rs/meson.build +++ b/subprojects/packagefiles/either-1-rs/meson.build @@ -1,4 +1,5 @@ project('either-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.12.0', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/itertools-0.11-rs/meson.build b/subprojects/packagefiles/itertools-0.11-rs/meson.build index 13d2d27019..30982a4ee7 100644 --- a/subprojects/packagefiles/itertools-0.11-rs/meson.build +++ b/subprojects/packagefiles/itertools-0.11-rs/meson.build @@ -1,4 +1,5 @@ project('itertools-0.11-rs', 'rust', + meson_version: '>=1.5.0', version: '0.11.0', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/proc-macro-error-1-rs/meson.build b/subprojects/packagefiles/proc-macro-error-1-rs/meson.build index 38ea7b89d3..ae27a69686 100644 --- a/subprojects/packagefiles/proc-macro-error-1-rs/meson.build +++ b/subprojects/packagefiles/proc-macro-error-1-rs/meson.build @@ -1,4 +1,5 @@ project('proc-macro-error-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.0.4', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build b/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build index d900c54cfd..3281b26433 100644 --- a/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build +++ b/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build @@ -1,4 +1,5 @@ project('proc-macro-error-attr-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.12.0', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/proc-macro2-1-rs/meson.build b/subprojects/packagefiles/proc-macro2-1-rs/meson.build index 8e601b50cc..f9c8675eba 100644 --- a/subprojects/packagefiles/proc-macro2-1-rs/meson.build +++ b/subprojects/packagefiles/proc-macro2-1-rs/meson.build @@ -1,4 +1,5 @@ project('proc-macro2-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.0.84', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/quote-1-rs/meson.build b/subprojects/packagefiles/quote-1-rs/meson.build index d36609bd3c..7f7792569b 100644 --- a/subprojects/packagefiles/quote-1-rs/meson.build +++ b/subprojects/packagefiles/quote-1-rs/meson.build @@ -1,4 +1,5 @@ project('quote-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.12.0', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/syn-2-rs/meson.build b/subprojects/packagefiles/syn-2-rs/meson.build index 9f56ce1c24..2c62cf7e1b 100644 --- a/subprojects/packagefiles/syn-2-rs/meson.build +++ b/subprojects/packagefiles/syn-2-rs/meson.build @@ -1,4 +1,5 @@ project('syn-2-rs', 'rust', + meson_version: '>=1.5.0', version: '2.0.66', license: 'MIT OR Apache-2.0', default_options: []) diff --git a/subprojects/packagefiles/unicode-ident-1-rs/meson.build b/subprojects/packagefiles/unicode-ident-1-rs/meson.build index 54f2376854..9d76ebbd1a 100644 --- a/subprojects/packagefiles/unicode-ident-1-rs/meson.build +++ b/subprojects/packagefiles/unicode-ident-1-rs/meson.build @@ -1,4 +1,5 @@ project('unicode-ident-1-rs', 'rust', + meson_version: '>=1.5.0', version: '1.0.12', license: '(MIT OR Apache-2.0) AND Unicode-DFS-2016', default_options: []) From 8fa11a4df344f58375eb26b3b65004345f21ef37 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 6 Nov 2024 15:43:29 +0000 Subject: [PATCH 04/13] target/i386: Fix legacy page table walk Commit b56617bbcb4 ("target/i386: Walk NPT in guest real mode") added logic to run the page table walker even in real mode if we are in NPT mode. That function then determined whether real mode or paging is active based on whether the pg_mode variable was 0. Unfortunately pg_mode is 0 in two situations: 1) Paging is disabled (real mode) 2) Paging is in 2-level paging mode (32bit without PAE) That means the walker now assumed that 2-level paging mode was real mode, breaking NetBSD as well as Windows XP. To fix that, this patch adds a new PG flag to pg_mode which indicates whether paging is active at all and uses that to determine whether we are in real mode or not. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2654 Fixes: b56617bbcb4 ("target/i386: Walk NPT in guest real mode") Signed-off-by: Alexander Graf Reported-by: Mark Cave-Ayland Link: https://lore.kernel.org/r/20241106154329.67218-1-graf@amazon.com Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 1 + target/i386/tcg/seg_helper.c | 2 +- target/i386/tcg/sysemu/excp_helper.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index b65eedb617..4c239a6970 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -346,6 +346,7 @@ typedef enum X86Seg { #define PG_MODE_PKE (1 << 17) #define PG_MODE_PKS (1 << 18) #define PG_MODE_SMEP (1 << 19) +#define PG_MODE_PG (1 << 20) #define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */ #define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c index 02ae6a0d1f..71962113fb 100644 --- a/target/i386/tcg/seg_helper.c +++ b/target/i386/tcg/seg_helper.c @@ -94,7 +94,7 @@ static uint32_t popl(StackAccess *sa) int get_pg_mode(CPUX86State *env) { - int pg_mode = 0; + int pg_mode = PG_MODE_PG; if (!(env->cr[0] & CR0_PG_MASK)) { return 0; } diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index da187c8792..02d3486421 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -298,7 +298,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, /* combine pde and pte nx, user and rw protections */ ptep &= pte ^ PG_NX_MASK; page_size = 4096; - } else if (pg_mode) { + } else if (pg_mode & PG_MODE_PG) { /* * Page table level 2 */ From 619d144751e6685b24ded9029fe9c484c0494c30 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 5 Nov 2024 13:53:55 +0100 Subject: [PATCH 05/13] eif: cope with huge section offsets Check for overflow to avoid that fseek() receives a sign-extended value. Cc: Dorjoy Chowdhury Signed-off-by: Paolo Bonzini --- hw/core/eif.c | 4 ++++ include/qemu/osdep.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/hw/core/eif.c b/hw/core/eif.c index 7f3b2edc9a..61329aacfe 100644 --- a/hw/core/eif.c +++ b/hw/core/eif.c @@ -466,6 +466,10 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd, EifSectionHeader hdr; uint16_t section_type; + if (eif_header.section_offsets[i] > OFF_MAX) { + error_setg(errp, "Invalid EIF image. Section offset out of bounds"); + goto cleanup; + } if (fseek(f, eif_header.section_offsets[i], SEEK_SET) != 0) { error_setg_errno(errp, errno, "Failed to offset to %" PRIu64 " in EIF file", eif_header.section_offsets[i]); diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index fe7c3c5f67..fdff07fd99 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -297,6 +297,10 @@ void QEMU_ERROR("code path is reachable") #error building with G_DISABLE_ASSERT is not supported #endif +#ifndef OFF_MAX +#define OFF_MAX (sizeof (off_t) == 8 ? INT64_MAX : INT32_MAX) +#endif + #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif From b7e55bd9d06d193cc55d2c46bb2864d71b1db1d3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 5 Nov 2024 13:57:59 +0100 Subject: [PATCH 06/13] eif: cope with huge section sizes Check for overflow as well as allocation failure. Resolves Coverity CID 1564859. Reviewed-by: Pierrick Bouvier Reviewed-by: Dorjoy Chowdhury Signed-off-by: Paolo Bonzini --- hw/core/eif.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/hw/core/eif.c b/hw/core/eif.c index 61329aacfe..a7128b71ce 100644 --- a/hw/core/eif.c +++ b/hw/core/eif.c @@ -119,6 +119,10 @@ static bool read_eif_header(FILE *f, EifHeader *header, uint32_t *crc, for (int i = 0; i < MAX_SECTIONS; ++i) { header->section_sizes[i] = be64_to_cpu(header->section_sizes[i]); + if (header->section_sizes[i] > SSIZE_MAX) { + error_setg(errp, "Invalid EIF image. Section size out of bounds"); + return false; + } } header->unused = be32_to_cpu(header->unused); @@ -278,7 +282,12 @@ static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size, struct cbor_load_result result; bool ret = false; - sig = g_malloc(size); + sig = g_try_malloc(size); + if (!sig) { + error_setg(errp, "Out of memory reading signature section"); + goto cleanup; + } + got = fread(sig, 1, size, eif); if ((uint64_t) got != size) { error_setg(errp, "Failed to read EIF signature section data"); @@ -320,7 +329,12 @@ static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size, error_setg(errp, "Invalid signature CBOR"); goto cleanup; } - cert = g_malloc(len); + cert = g_try_malloc(len); + if (!cert) { + error_setg(errp, "Out of memory reading signature section"); + goto cleanup; + } + for (int i = 0; i < len; ++i) { cbor_item_t *tmp = cbor_array_get(pair->value, i); if (!tmp) { @@ -503,7 +517,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd, goto cleanup; } - ptr = g_malloc(hdr.section_size); + ptr = g_try_malloc(hdr.section_size); + if (!ptr) { + error_setg(errp, "Out of memory reading kernel section"); + goto cleanup; + } iov_ptr = g_malloc(sizeof(struct iovec)); iov_ptr->iov_base = ptr; @@ -528,7 +546,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd, goto cleanup; } size = hdr.section_size; - *cmdline = g_malloc(size + 1); + *cmdline = g_try_malloc(size + 1); + if (!*cmdline) { + error_setg(errp, "Out of memory reading command line section"); + goto cleanup; + } if (!read_eif_cmdline(f, size, *cmdline, &crc, errp)) { goto cleanup; } @@ -567,7 +589,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd, } } - ptr = g_malloc(hdr.section_size); + ptr = g_try_malloc(hdr.section_size); + if (!ptr) { + error_setg(errp, "Out of memory reading initrd section"); + goto cleanup; + } iov_ptr = g_malloc(sizeof(struct iovec)); iov_ptr->iov_base = ptr; @@ -606,7 +632,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd, uint8_t *buf; size_t got; uint64_t size = hdr.section_size; - buf = g_malloc(size); + buf = g_try_malloc(size); + if (!buf) { + error_setg(errp, "Out of memory reading unknown section"); + goto cleanup; + } got = fread(buf, 1, size, f); if ((uint64_t) got != size) { g_free(buf); @@ -662,7 +692,11 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd, goto cleanup; } - ptr = g_malloc(machine_initrd_size); + ptr = g_try_malloc(machine_initrd_size); + if (!ptr) { + error_setg(errp, "Out of memory reading initrd file"); + goto cleanup; + } iov_ptr = g_malloc(sizeof(struct iovec)); iov_ptr->iov_base = ptr; From 0e27f3a5d0cbc0099ba8dcd7ff78e7f80d0c4f15 Mon Sep 17 00:00:00 2001 From: Phil Dennis-Jordan Date: Tue, 5 Nov 2024 16:57:56 +0100 Subject: [PATCH 07/13] i386/hvf: Integrates x2APIC support with hvf accel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for x2APIC mode was recently introduced in the software emulated APIC implementation for TCG. Enabling it when using macOS’s hvf accelerator is useful and significantly helps performance, as Qemu currently uses the emulated APIC when running on hvf as well. This change wires up the read & write operations for the MSR VM exits and allow-lists the CPUID flag in the x86 hvf runtime. Signed-off-by: Phil Dennis-Jordan Link: https://lore.kernel.org/r/20241105155800.5461-2-phil@philjordan.eu Reviewed-by: Roman Bolshakov Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_cpuid.c | 2 +- target/i386/hvf/x86_emu.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index 492e8bfc80..3f16b0f363 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -77,7 +77,7 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 | CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE | - CPUID_EXT_POPCNT | CPUID_EXT_AES | + CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_X2APIC | (supported_xcr0 ? CPUID_EXT_XSAVE : 0) | CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND; ecx |= CPUID_EXT_HYPERVISOR; diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 38c782b8e3..be675bcfb7 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -663,6 +663,15 @@ static void exec_lods(CPUX86State *env, struct x86_decode *decode) env->eip += decode->len; } +static void raise_exception(CPUX86State *env, int exception_index, + int error_code) +{ + env->exception_nr = exception_index; + env->error_code = error_code; + env->has_error_code = true; + env->exception_injected = 1; +} + void simulate_rdmsr(CPUX86State *env) { X86CPU *cpu = env_archcpu(env); @@ -677,6 +686,17 @@ void simulate_rdmsr(CPUX86State *env) case MSR_IA32_APICBASE: val = cpu_get_apic_base(cpu->apic_state); break; + case MSR_APIC_START ... MSR_APIC_END: { + int ret; + int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; + + ret = apic_msr_read(index, &val); + if (ret < 0) { + raise_exception(env, EXCP0D_GPF, 0); + } + + break; + } case MSR_IA32_UCODE_REV: val = cpu->ucode_rev; break; @@ -777,6 +797,17 @@ void simulate_wrmsr(CPUX86State *env) case MSR_IA32_APICBASE: cpu_set_apic_base(cpu->apic_state, data); break; + case MSR_APIC_START ... MSR_APIC_END: { + int ret; + int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; + + ret = apic_msr_write(index, data); + if (ret < 0) { + raise_exception(env, EXCP0D_GPF, 0); + } + + break; + } case MSR_FSBASE: wvmcs(cs->accel->fd, VMCS_GUEST_FS_BASE, data); break; From e3150028fffb808452078ead055fc6a4d50a63e9 Mon Sep 17 00:00:00 2001 From: Phil Dennis-Jordan Date: Tue, 5 Nov 2024 16:57:57 +0100 Subject: [PATCH 08/13] i386/hvf: Fix for UB in handling CPUID function 0xD The handling for CPUID function 0xD (supported XSAVE features) was improved in a recent patch. Unfortunately, this appears to have introduced undefined behaviour for cases where ecx > 30, as the result of (1 << idx) is undefined if idx > 30. Per Intel SDM section 13.2, the behaviour for ecx values up to and including 62 are specified. This change therefore specifically sets all registers returned by the CPUID instruction to 0 for 63 and higher. Furthermore, the bit shift uses uint64_t, where behaviour for the entire range of 2..62 is safe and correct. Signed-off-by: Phil Dennis-Jordan Link: https://lore.kernel.org/r/20241105155800.5461-3-phil@philjordan.eu Reviewed-by: Roman Bolshakov Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_cpuid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index 3f16b0f363..af9ee17a11 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -119,8 +119,8 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, eax = 0; break; case 0xD: - if (!supported_xcr0 || - (idx > 1 && !(supported_xcr0 & (1 << idx)))) { + if (!supported_xcr0 || idx >= 63 || + (idx > 1 && !(supported_xcr0 & (UINT64_C(1) << idx)))) { eax = ebx = ecx = edx = 0; break; } From 3a75ba650c4b4fc11c29f77c57fc30fd282c5ae9 Mon Sep 17 00:00:00 2001 From: Phil Dennis-Jordan Date: Tue, 5 Nov 2024 16:57:58 +0100 Subject: [PATCH 09/13] i386/hvf: Fixes startup memory leak (vmcs caps) The hvf_caps data structure only exists once as part of the hvf accelerator state, but it is initialised during vCPU initialisation. This change therefore adds a check to ensure memory for it is only allocated once. Signed-off-by: Phil Dennis-Jordan Link: https://lore.kernel.org/r/20241105155800.5461-4-phil@philjordan.eu Reviewed-by: Roman Bolshakov Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 68dc5d9cf7..8527bce6ee 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -239,7 +239,9 @@ int hvf_arch_init_vcpu(CPUState *cpu) init_emu(); init_decoder(); - hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1); + if (hvf_state->hvf_caps == NULL) { + hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1); + } env->hvf_mmio_buf = g_new(char, 4096); if (x86cpu->vmware_cpuid_freq) { From 04858f95fa4b318bb662e046ab090179a1eeeebb Mon Sep 17 00:00:00 2001 From: Phil Dennis-Jordan Date: Tue, 5 Nov 2024 16:57:59 +0100 Subject: [PATCH 10/13] i386/hvf: Raise exception on error setting APICBASE When setting the APICBASE MSR to an illegal value, the APIC implementation will return an error. This change forwards that report to the guest as an exception rather than ignoring it when using the hvf accelerator. Signed-off-by: Phil Dennis-Jordan Link: https://lore.kernel.org/r/20241105155800.5461-5-phil@philjordan.eu Reviewed-by: Roman Bolshakov Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_emu.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index be675bcfb7..015f760acb 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -794,9 +794,16 @@ void simulate_wrmsr(CPUX86State *env) switch (msr) { case MSR_IA32_TSC: break; - case MSR_IA32_APICBASE: - cpu_set_apic_base(cpu->apic_state, data); + case MSR_IA32_APICBASE: { + int r; + + r = cpu_set_apic_base(cpu->apic_state, data); + if (r < 0) { + raise_exception(env, EXCP0D_GPF, 0); + } + break; + } case MSR_APIC_START ... MSR_APIC_END: { int ret; int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; From b659ef9d358a692f941f1f46e7abef29231960d1 Mon Sep 17 00:00:00 2001 From: Phil Dennis-Jordan Date: Tue, 5 Nov 2024 16:58:00 +0100 Subject: [PATCH 11/13] i386/hvf: Removes duplicate/shadowed variables in hvf_vcpu_exec Pointers to the x86 CPU state already exist at the function scope, no need to re-obtain them in individual exit reason cases. Signed-off-by: Phil Dennis-Jordan Link: https://lore.kernel.org/r/20241105155800.5461-6-phil@philjordan.eu Reviewed-by: Roman Bolshakov Signed-off-by: Paolo Bonzini --- target/i386/hvf/hvf.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 8527bce6ee..c5d025d557 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -586,8 +586,6 @@ int hvf_vcpu_exec(CPUState *cpu) break; } case EXIT_REASON_XSETBV: { - X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env = &x86_cpu->env; uint32_t eax = (uint32_t)rreg(cpu->accel->fd, HV_X86_RAX); uint32_t ecx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RCX); uint32_t edx = (uint32_t)rreg(cpu->accel->fd, HV_X86_RDX); @@ -644,7 +642,6 @@ int hvf_vcpu_exec(CPUState *cpu) break; } case 8: { - X86CPU *x86_cpu = X86_CPU(cpu); if (exit_qual & 0x10) { RRX(env, reg) = cpu_get_apic_tpr(x86_cpu->apic_state); } else { From 88dd060db96d0764543974f53eb45bee3432c99f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 6 Nov 2024 12:38:37 +0100 Subject: [PATCH 12/13] rust: qemu-api-macros: always process subprojects before dependencies Avoid looking for Rust dependencies via cmake. Reviewed-by: Junjie Mao Signed-off-by: Paolo Bonzini --- rust/qemu-api-macros/meson.build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/qemu-api-macros/meson.build b/rust/qemu-api-macros/meson.build index 24325dea5c..6f94a4bb3c 100644 --- a/rust/qemu-api-macros/meson.build +++ b/rust/qemu-api-macros/meson.build @@ -1,3 +1,7 @@ +subproject('proc-macro2-1-rs', required: true) +subproject('quote-1-rs', required: true) +subproject('syn-2-rs', required: true) + quote_dep = dependency('quote-1-rs', native: true) syn_dep = dependency('syn-2-rs', native: true) proc_macro2_dep = dependency('proc-macro2-1-rs', native: true) From bd0e501e1a4813fa36a4cf9842aaf430323a03c3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 5 Nov 2024 17:18:13 +0000 Subject: [PATCH 13/13] hw/i386/pc: Don't try to init PCI NICs if there is no PCI bus The 'isapc' machine type has no PCI bus, but pc_nic_init() still calls pci_init_nic_devices() passing it a NULL bus pointer. This causes the clang sanitizer to complain: $ ./build/clang/qemu-system-i386 -M isapc ../../hw/pci/pci.c:1866:39: runtime error: member access within null pointer of type 'PCIBus' (aka 'struct PCIBus') SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../hw/pci/pci.c:1866:39 in This is because pci_init_nic_devices() does &bus->qbus which is undefined behaviour on a NULL pointer even though we're not actually dereferencing the pointer. (We don't actually crash as a result, so if you aren't running a sanitizer build then there are no user-visible effects.) Make pc_nic_init() avoid trying to initialize PCI NICs on a non-PCI system. Cc: qemu-stable@nongnu.org Fixes: 8d39f9ba14d64 ("hw/i386/pc: use qemu_get_nic_info() and pci_init_nic_devices()") Signed-off-by: Peter Maydell Link: https://lore.kernel.org/r/20241105171813.3031969-1-peter.maydell@linaro.org Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 830614d930..f9147fecbd 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1252,7 +1252,9 @@ void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus) } /* Anything remaining should be a PCI NIC */ - pci_init_nic_devices(pci_bus, mc->default_nic); + if (pci_bus) { + pci_init_nic_devices(pci_bus, mc->default_nic); + } rom_reset_order_override(); }