From f000bc74589247244943085b210cee32bac28c89 Mon Sep 17 00:00:00 2001 From: Ivan Shcherbakov Date: Sat, 14 May 2022 07:50:21 +0200 Subject: [PATCH 01/23] WHPX: fixed TPR/CR8 translation issues affecting VM debugging This patch fixes the following error that would occur when trying to resume a WHPX-accelerated VM from a breakpoint: qemu: WHPX: Failed to set interrupt state registers, hr=c0350005 The error arises from an incorrect CR8 value being passed to WHvSetVirtualProcessorRegisters() that doesn't match the value set via WHvSetVirtualProcessorInterruptControllerState2(). Signed-off-by: Ivan Shcherbakov Signed-off-by: Paolo Bonzini --- target/i386/whpx/whpx-all.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index 23ae639b23..b22a3314b4 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -373,6 +373,8 @@ static int whpx_set_tsc(CPUState *cpu) * * This mechanism is described in section 10.8.6.1 of Volume 3 of Intel 64 * and IA-32 Architectures Software Developer's Manual. + * + * The functions below translate the value of CR8 to TPR and vice versa. */ static uint64_t whpx_apic_tpr_to_cr8(uint64_t tpr) @@ -380,6 +382,11 @@ static uint64_t whpx_apic_tpr_to_cr8(uint64_t tpr) return tpr >> 4; } +static uint64_t whpx_cr8_to_apic_tpr(uint64_t cr8) +{ + return cr8 << 4; +} + static void whpx_set_registers(CPUState *cpu, int level) { struct whpx_state *whpx = &whpx_global; @@ -687,7 +694,7 @@ static void whpx_get_registers(CPUState *cpu) tpr = vcxt.values[idx++].Reg64; if (tpr != vcpu->tpr) { vcpu->tpr = tpr; - cpu_set_apic_tpr(x86_cpu->apic_state, tpr); + cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(tpr)); } /* 8 Debug Registers - Skipped */ @@ -1547,7 +1554,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu) } /* Sync the TPR to the CR8 if was modified during the intercept */ - tpr = cpu_get_apic_tpr(x86_cpu->apic_state); + tpr = whpx_apic_tpr_to_cr8(cpu_get_apic_tpr(x86_cpu->apic_state)); if (tpr != vcpu->tpr) { vcpu->tpr = tpr; reg_values[reg_count].Reg64 = tpr; @@ -1596,7 +1603,7 @@ static void whpx_vcpu_post_run(CPUState *cpu) if (vcpu->tpr != tpr) { vcpu->tpr = tpr; qemu_mutex_lock_iothread(); - cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr); + cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(vcpu->tpr)); qemu_mutex_unlock_iothread(); } From 580ea136eb37b9a059bdba9c20260dc825bcc2de Mon Sep 17 00:00:00 2001 From: Konstantin Kostiuk Date: Thu, 12 May 2022 18:49:06 +0300 Subject: [PATCH 02/23] qga-vss: Add auto generated headers to dependencies Signed-off-by: Konstantin Kostiuk Message-Id: <20220512154906.331399-1-kkostiuk@redhat.com> Signed-off-by: Paolo Bonzini --- qga/vss-win32/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qga/vss-win32/meson.build b/qga/vss-win32/meson.build index 26c5dd6e0e..9483ccd3b8 100644 --- a/qga/vss-win32/meson.build +++ b/qga/vss-win32/meson.build @@ -7,7 +7,7 @@ link_args = cc.get_supported_link_arguments([ qga_vss = shared_module( 'qga-vss', - ['requester.cpp', 'provider.cpp', 'install.cpp'], + ['requester.cpp', 'provider.cpp', 'install.cpp', genh], name_prefix: '', cpp_args: ['-Wno-unknown-pragmas', '-Wno-delete-non-virtual-dtor', '-Wno-non-virtual-dtor'], link_args: link_args, From 6c1d88c72bd740cc431a13a02145168cf87866fc Mon Sep 17 00:00:00 2001 From: Konstantin Kostiuk Date: Thu, 12 May 2022 18:49:09 +0300 Subject: [PATCH 03/23] qga-vss: Use the proper operator to free memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit volume_name_wchar is allocated by 'void* operator new [](long long unsigned int) Signed-off-by: Konstantin Kostiuk Reviewed-by: Marc-André Lureau Message-Id: <20220512154909.331481-1-kkostiuk@redhat.com> Signed-off-by: Paolo Bonzini --- qga/vss-win32/requester.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp index 4513324dd2..b371affeab 100644 --- a/qga/vss-win32/requester.cpp +++ b/qga/vss-win32/requester.cpp @@ -354,12 +354,12 @@ void requester_freeze(int *num_vols, void *mountpoints, ErrorSet *errset) if (FAILED(hr)) { err_set(errset, hr, "failed to add %S to snapshot set", volume_name_wchar); - delete volume_name_wchar; + delete[] volume_name_wchar; goto out; } num_mount_points++; - delete volume_name_wchar; + delete[] volume_name_wchar; } if (num_mount_points == 0) { From 6df39f5e583ca0f67bd934d1327f9ead2e3bd49c Mon Sep 17 00:00:00 2001 From: Robert Hoo Date: Mon, 14 Mar 2022 16:50:59 +0800 Subject: [PATCH 04/23] i386/cpu: Remove the deprecated cpu model 'Icelake-Client' Icelake, is the codename for Intel 3rd generation Xeon Scalable server processors. There isn't ever client variants. This "Icelake-Client" CPU model was added wrongly and imaginarily. It has been deprecated since v5.2, now it's time to remove it completely from code. Signed-off-by: Robert Hoo Reviewed-by: Igor Mammedov Message-Id: <1647247859-4947-1-git-send-email-robert.hu@linux.intel.com> Signed-off-by: Paolo Bonzini --- docs/about/deprecated.rst | 6 -- docs/about/removed-features.rst | 6 ++ target/i386/cpu.c | 122 -------------------------------- 3 files changed, 6 insertions(+), 128 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 896e5a97ab..44f52c172d 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -270,12 +270,6 @@ from Linux upstream kernel, declare it deprecated. System emulator CPUS -------------------- -``Icelake-Client`` CPU Model (since 5.2) -'''''''''''''''''''''''''''''''''''''''' - -``Icelake-Client`` CPU Models are deprecated. Use ``Icelake-Server`` CPU -Models instead. - MIPS ``I7200`` CPU Model (since 5.2) '''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 4a0b270296..ba78bc1a19 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -557,6 +557,12 @@ Support for this CPU was removed from the upstream Linux kernel, and there is no available upstream toolchain to build binaries for it. Removed without replacement. +x86 ``Icelake-Client`` CPU (removed in 7.1) +''''''''''''''''''''''''''''''''''''''''''' + +There isn't ever Icelake Client CPU, it is some wrong and imaginary one. +Use ``Icelake-Server`` instead. + System emulator machines ------------------------ diff --git a/target/i386/cpu.c b/target/i386/cpu.c index c4a17c93f6..6083e556f5 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3258,128 +3258,6 @@ static const X86CPUDefinition builtin_x86_defs[] = { { /* end of list */ } } }, - { - .name = "Icelake-Client", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 126, - .stepping = 0, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_8000_0008_EBX] = - CPUID_8000_0008_EBX_WBNOINVD, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP, - .features[FEAT_7_0_ECX] = - CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | - CPUID_7_0_ECX_AVX512_VBMI2 | CPUID_7_0_ECX_GFNI | - CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | - CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | - CPUID_7_0_ECX_AVX512_VPOPCNTDQ, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, - /* XSAVES is added in version 3 */ - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ - .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | - MSR_VMX_BASIC_TRUE_CTLS, - .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | - VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | - VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, - .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | - MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | - MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | - MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | - MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | - MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | - MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, - .features[FEAT_VMX_EXIT_CTLS] = - VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | - VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | - VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | - VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | - VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, - .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | - MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, - .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | - VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | - VMX_PIN_BASED_VMX_PREEMPTION_TIMER, - .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | - VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | - VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | - VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | - VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | - VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | - VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | - VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | - VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | - VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | - VMX_CPU_BASED_MONITOR_TRAP_FLAG | - VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, - .features[FEAT_VMX_SECONDARY_CTLS] = - VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | - VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | - VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | - VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | - VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | - VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | - VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, - .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Icelake)", - .versions = (X86CPUVersionDefinition[]) { - { - .version = 1, - .note = "deprecated" - }, - { - .version = 2, - .note = "no TSX, deprecated", - .alias = "Icelake-Client-noTSX", - .props = (PropValue[]) { - { "hle", "off" }, - { "rtm", "off" }, - { /* end of list */ } - }, - }, - { - .version = 3, - .note = "no TSX, XSAVES, deprecated", - .props = (PropValue[]) { - { "xsaves", "on" }, - { "vmx-xsaves", "on" }, - { /* end of list */ } - }, - }, - { /* end of list */ } - }, - .deprecation_note = "use Icelake-Server instead" - }, { .name = "Icelake-Server", .level = 0xd, From 18c22d7112a76fabeee5022a3bdd9e8c3a37c8d2 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:51 -0500 Subject: [PATCH 05/23] qdev-properties: Add a new macro with bitmask check for uint64_t property The DEFINE_PROP_UINT64_CHECKMASK maro applies certain mask check agaist user-supplied property value, reject the value if it violates the bitmask. Co-developed-by: Like Xu Signed-off-by: Like Xu Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-2-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- hw/core/qdev-properties.c | 19 +++++++++++++++++++ include/hw/qdev-properties.h | 12 ++++++++++++ 2 files changed, 31 insertions(+) diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index c34aac6ebc..357b8761b5 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = { .set_default_value = qdev_propinfo_set_default_value_int, }; +static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + Property *prop = opaque; + uint64_t *ptr = object_field_prop_ptr(obj, prop); + + visit_type_uint64(v, name, ptr, errp); + if (*ptr & ~prop->bitmask) { + error_setg(errp, "Property value for '%s' has bits outside mask '0x%" PRIx64 "'", + name, prop->bitmask); + } +} + +const PropertyInfo qdev_prop_uint64_checkmask = { + .name = "uint64", + .get = get_uint64, + .set = set_uint64_checkmask, +}; + /* --- string --- */ static void release_string(Object *obj, const char *name, void *opaque) diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index f7925f67d0..e1df08876c 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -17,6 +17,7 @@ struct Property { const PropertyInfo *info; ptrdiff_t offset; uint8_t bitnr; + uint64_t bitmask; bool set_default; union { int64_t i; @@ -54,6 +55,7 @@ extern const PropertyInfo qdev_prop_uint16; extern const PropertyInfo qdev_prop_uint32; extern const PropertyInfo qdev_prop_int32; extern const PropertyInfo qdev_prop_uint64; +extern const PropertyInfo qdev_prop_uint64_checkmask; extern const PropertyInfo qdev_prop_int64; extern const PropertyInfo qdev_prop_size; extern const PropertyInfo qdev_prop_string; @@ -103,6 +105,16 @@ extern const PropertyInfo qdev_prop_link; .set_default = true, \ .defval.u = (bool)_defval) +/** + * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value + * against corresponding bitmask, rejects the value if it violates. + * The default value is set in instance_init(). + */ +#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask) \ + DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \ + .bitmask = (_bitmask), \ + .set_default = false) + #define PROP_ARRAY_LEN_PREFIX "len-" /** From f06d8a18abc9d29d052f628eefd1d4a86c99fcea Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:52 -0500 Subject: [PATCH 06/23] target/i386: Add lbr-fmt vPMU option to support guest LBR The Last Branch Recording (LBR) is a performance monitor unit (PMU) feature on Intel processors which records a running trace of the most recent branches taken by the processor in the LBR stack. This option indicates the LBR format to enable for guest perf. The LBR feature is enabled if below conditions are met: 1) KVM is enabled and the PMU is enabled. 2) msr-based-feature IA32_PERF_CAPABILITIES is supporterd on KVM. 3) Supported returned value for lbr_fmt from above msr is non-zero. 4) Guest vcpu model does support FEAT_1_ECX.CPUID_EXT_PDCM. 5) User-provided lbr-fmt value doesn't violate its bitmask (0x3f). 6) Target guest LBR format matches that of host. Co-developed-by: Like Xu Signed-off-by: Like Xu Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-3-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++++ target/i386/cpu.h | 10 ++++++++++ 2 files changed, 50 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6083e556f5..856a8659e8 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6275,6 +6275,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) CPUX86State *env = &cpu->env; Error *local_err = NULL; static bool ht_warned; + unsigned requested_lbr_fmt; if (cpu->apic_id == UNASSIGNED_APIC_ID) { error_setg(errp, "apic-id property was not initialized properly"); @@ -6292,6 +6293,42 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) goto out; } + /* + * Override env->features[FEAT_PERF_CAPABILITIES].LBR_FMT + * with user-provided setting. + */ + if (cpu->lbr_fmt != ~PERF_CAP_LBR_FMT) { + if ((cpu->lbr_fmt & PERF_CAP_LBR_FMT) != cpu->lbr_fmt) { + error_setg(errp, "invalid lbr-fmt"); + return; + } + env->features[FEAT_PERF_CAPABILITIES] &= ~PERF_CAP_LBR_FMT; + env->features[FEAT_PERF_CAPABILITIES] |= cpu->lbr_fmt; + } + + /* + * vPMU LBR is supported when 1) KVM is enabled 2) Option pmu=on and + * 3)vPMU LBR format matches that of host setting. + */ + requested_lbr_fmt = + env->features[FEAT_PERF_CAPABILITIES] & PERF_CAP_LBR_FMT; + if (requested_lbr_fmt && kvm_enabled()) { + uint64_t host_perf_cap = + x86_cpu_get_supported_feature_word(FEAT_PERF_CAPABILITIES, false); + unsigned host_lbr_fmt = host_perf_cap & PERF_CAP_LBR_FMT; + + if (!cpu->enable_pmu) { + error_setg(errp, "vPMU: LBR is unsupported without pmu=on"); + return; + } + if (requested_lbr_fmt != host_lbr_fmt) { + error_setg(errp, "vPMU: the lbr-fmt value (0x%x) does not match " + "the host value (0x%x).", + requested_lbr_fmt, host_lbr_fmt); + return; + } + } + x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid); if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) { @@ -6644,6 +6681,8 @@ static void x86_cpu_initfn(Object *obj) object_property_add_alias(obj, "sse4_2", obj, "sse4.2"); object_property_add_alias(obj, "hv-apicv", obj, "hv-avic"); + cpu->lbr_fmt = ~PERF_CAP_LBR_FMT; + object_property_add_alias(obj, "lbr_fmt", obj, "lbr-fmt"); if (xcc->model) { x86_cpu_load_model(cpu, xcc->model); @@ -6798,6 +6837,7 @@ static Property x86_cpu_properties[] = { #endif DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID), DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), + DEFINE_PROP_UINT64_CHECKMASK("lbr-fmt", X86CPU, lbr_fmt, PERF_CAP_LBR_FMT), DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts, HYPERV_SPINLOCK_NEVER_NOTIFY), diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 9661f9fbd1..6730df5dbf 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -386,6 +386,7 @@ typedef enum X86Seg { #define ARCH_CAP_TSX_CTRL_MSR (1<<7) #define MSR_IA32_PERF_CAPABILITIES 0x345 +#define PERF_CAP_LBR_FMT 0x3f #define MSR_IA32_TSX_CTRL 0x122 #define MSR_IA32_TSCDEADLINE 0x6e0 @@ -1810,6 +1811,15 @@ struct ArchCPU { */ bool enable_pmu; + /* + * Enable LBR_FMT bits of IA32_PERF_CAPABILITIES MSR. + * This can't be initialized with a default because it doesn't have + * stable ABI support yet. It is only allowed to pass all LBR_FMT bits + * returned by kvm_arch_get_supported_msr_feature()(which depends on both + * host CPU and kernel capabilities) to the guest. + */ + uint64_t lbr_fmt; + /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is * disabled by default to avoid breaking migration between QEMU with * different LMCE configurations. From 5a778a5f820fdd907b95e93560637a61f6ea3c71 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:53 -0500 Subject: [PATCH 07/23] target/i386: Add kvm_get_one_msr helper When try to get one msr from KVM, I found there's no such kind of existing interface while kvm_put_one_msr() is there. So here comes the patch. It'll remove redundant preparation code before finally call KVM_GET_MSRS IOCTL. No functional change intended. Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-4-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/kvm/kvm.c | 46 ++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index c885763a5b..536cbe5fad 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -141,6 +141,7 @@ static struct kvm_msr_list *kvm_feature_msrs; #define BUS_LOCK_SLICE_TIME 1000000000ULL /* ns */ static RateLimit bus_lock_ratelimit_ctrl; +static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value); int kvm_has_pit_state2(void) { @@ -211,28 +212,21 @@ static int kvm_get_tsc(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; - struct { - struct kvm_msrs info; - struct kvm_msr_entry entries[1]; - } msr_data = {}; + uint64_t value; int ret; if (env->tsc_valid) { return 0; } - memset(&msr_data, 0, sizeof(msr_data)); - msr_data.info.nmsrs = 1; - msr_data.entries[0].index = MSR_IA32_TSC; env->tsc_valid = !runstate_is_running(); - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); + ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, &value); if (ret < 0) { return ret; } - assert(ret == 1); - env->tsc = msr_data.entries[0].data; + env->tsc = value; return 0; } @@ -1566,21 +1560,14 @@ static int hyperv_init_vcpu(X86CPU *cpu) * the kernel doesn't support setting vp_index; assert that its value * is in sync */ - struct { - struct kvm_msrs info; - struct kvm_msr_entry entries[1]; - } msr_data = { - .info.nmsrs = 1, - .entries[0].index = HV_X64_MSR_VP_INDEX, - }; + uint64_t value; - ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, &msr_data); + ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, &value); if (ret < 0) { return ret; } - assert(ret == 1); - if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) { + if (value != hyperv_vp_index(CPU(cpu))) { error_report("kernel's vp_index != QEMU's vp_index"); return -ENXIO; } @@ -2839,6 +2826,25 @@ static int kvm_put_one_msr(X86CPU *cpu, int index, uint64_t value) return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); } +static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value) +{ + int ret; + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data = { + .info.nmsrs = 1, + .entries[0].index = index, + }; + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); + if (ret < 0) { + return ret; + } + assert(ret == 1); + *value = msr_data.entries[0].data; + return ret; +} void kvm_put_apicbase(X86CPU *cpu, uint64_t value) { int ret; From 301e90675c3fed6cdc48682021a1ab42bc0e0d76 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:54 -0500 Subject: [PATCH 08/23] target/i386: Enable support for XSAVES based features There're some new features, including Arch LBR, depending on XSAVES/XRSTORS support, the new instructions will save/restore data based on feature bits enabled in XCR0 | XSS. This patch adds the basic support for related CPUID enumeration and meanwhile changes the name from FEAT_XSAVE_COMP_{LO|HI} to FEAT_XSAVE_XCR0_{LO|HI} to differentiate clearly the feature bits in XCR0 and those in XSS. Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-5-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 104 +++++++++++++++++++++++++++++++++++----------- target/i386/cpu.h | 14 ++++++- 2 files changed, 92 insertions(+), 26 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 856a8659e8..643536d05d 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -937,6 +937,34 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, .tcg_features = TCG_XSAVE_FEATURES, }, + [FEAT_XSAVE_XSS_LO] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .cpuid = { + .eax = 0xD, + .needs_ecx = true, + .ecx = 1, + .reg = R_ECX, + }, + }, + [FEAT_XSAVE_XSS_HI] = { + .type = CPUID_FEATURE_WORD, + .cpuid = { + .eax = 0xD, + .needs_ecx = true, + .ecx = 1, + .reg = R_EDX + }, + }, [FEAT_6_EAX] = { .type = CPUID_FEATURE_WORD, .feat_names = { @@ -952,7 +980,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .cpuid = { .eax = 6, .reg = R_EAX, }, .tcg_features = TCG_6_EAX_FEATURES, }, - [FEAT_XSAVE_COMP_LO] = { + [FEAT_XSAVE_XCR0_LO] = { .type = CPUID_FEATURE_WORD, .cpuid = { .eax = 0xD, @@ -965,7 +993,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK, }, - [FEAT_XSAVE_COMP_HI] = { + [FEAT_XSAVE_XCR0_HI] = { .type = CPUID_FEATURE_WORD, .cpuid = { .eax = 0xD, @@ -1382,6 +1410,9 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { }; #undef REGISTER +/* CPUID feature bits available in XSS */ +#define CPUID_XSTATE_XSS_MASK (0) + ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { [XSTATE_FP_BIT] = { /* x87 FP state component is always enabled if XSAVE is supported */ @@ -1424,15 +1455,18 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { }, }; -static uint32_t xsave_area_size(uint64_t mask) +static uint32_t xsave_area_size(uint64_t mask, bool compacted) { + uint64_t ret = x86_ext_save_areas[0].size; + const ExtSaveArea *esa; + uint32_t offset = 0; int i; - uint64_t ret = 0; - for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) { - const ExtSaveArea *esa = &x86_ext_save_areas[i]; + for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) { + esa = &x86_ext_save_areas[i]; if ((mask >> i) & 1) { - ret = MAX(ret, esa->offset + esa->size); + offset = compacted ? ret : esa->offset; + ret = MAX(ret, offset + esa->size); } } return ret; @@ -1443,10 +1477,10 @@ static inline bool accel_uses_host_cpuid(void) return kvm_enabled() || hvf_enabled(); } -static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu) +static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu) { - return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 | - cpu->env.features[FEAT_XSAVE_COMP_LO]; + return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 | + cpu->env.features[FEAT_XSAVE_XCR0_LO]; } /* Return name of 32-bit register, from a R_* constant */ @@ -1458,6 +1492,12 @@ static const char *get_register_name_32(unsigned int reg) return x86_reg_info_32[reg].name; } +static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu) +{ + return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 | + cpu->env.features[FEAT_XSAVE_XSS_LO]; +} + /* * Returns the set of feature flags that are supported and migratable by * QEMU, for a given FeatureWord. @@ -4511,8 +4551,8 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) /* XSAVE components are automatically enabled by other features, * so return the original feature name instead */ - if (w == FEAT_XSAVE_COMP_LO || w == FEAT_XSAVE_COMP_HI) { - int comp = (w == FEAT_XSAVE_COMP_HI) ? bitnr + 32 : bitnr; + if (w == FEAT_XSAVE_XCR0_LO || w == FEAT_XSAVE_XCR0_HI) { + int comp = (w == FEAT_XSAVE_XCR0_HI) ? bitnr + 32 : bitnr; if (comp < ARRAY_SIZE(x86_ext_save_areas) && x86_ext_save_areas[comp].bits) { @@ -5408,25 +5448,36 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, } if (count == 0) { - *ecx = xsave_area_size(x86_cpu_xsave_components(cpu)); - *eax = env->features[FEAT_XSAVE_COMP_LO]; - *edx = env->features[FEAT_XSAVE_COMP_HI]; + *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu), false); + *eax = env->features[FEAT_XSAVE_XCR0_LO]; + *edx = env->features[FEAT_XSAVE_XCR0_HI]; /* * The initial value of xcr0 and ebx == 0, On host without kvm * commit 412a3c41(e.g., CentOS 6), the ebx's value always == 0 * even through guest update xcr0, this will crash some legacy guest * (e.g., CentOS 6), So set ebx == ecx to workaroud it. */ - *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0); + *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0, false); } else if (count == 1) { + uint64_t xstate = x86_cpu_xsave_xcr0_components(cpu) | + x86_cpu_xsave_xss_components(cpu); + *eax = env->features[FEAT_XSAVE]; + *ebx = xsave_area_size(xstate, true); + *ecx = env->features[FEAT_XSAVE_XSS_LO]; + *edx = env->features[FEAT_XSAVE_XSS_HI]; } else if (count < ARRAY_SIZE(x86_ext_save_areas)) { - if ((x86_cpu_xsave_components(cpu) >> count) & 1) { - const ExtSaveArea *esa = &x86_ext_save_areas[count]; + const ExtSaveArea *esa = &x86_ext_save_areas[count]; + + if (x86_cpu_xsave_xcr0_components(cpu) & (1ULL << count)) { *eax = esa->size; *ebx = esa->offset; *ecx = esa->ecx & (ESA_FEATURE_ALIGN64_MASK | ESA_FEATURE_XFD_MASK); + } else if (x86_cpu_xsave_xss_components(cpu) & (1ULL << count)) { + *eax = esa->size; + *ebx = 0; + *ecx = 1; } } break; @@ -5477,8 +5528,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, } else { *eax &= env->features[FEAT_SGX_12_1_EAX]; *ebx &= 0; /* ebx reserve */ - *ecx &= env->features[FEAT_XSAVE_COMP_LO]; - *edx &= env->features[FEAT_XSAVE_COMP_HI]; + *ecx &= env->features[FEAT_XSAVE_XSS_LO]; + *edx &= env->features[FEAT_XSAVE_XSS_HI]; /* FP and SSE are always allowed regardless of XSAVE/XCR0. */ *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK; @@ -5874,6 +5925,9 @@ static void x86_cpu_reset(DeviceState *dev) } for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) { const ExtSaveArea *esa = &x86_ext_save_areas[i]; + if (!((1 << i) & CPUID_XSTATE_XCR0_MASK)) { + continue; + } if (env->features[esa->feature] & esa->bits) { xcr0 |= 1ull << i; } @@ -5988,8 +6042,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) static bool request_perm; if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { - env->features[FEAT_XSAVE_COMP_LO] = 0; - env->features[FEAT_XSAVE_COMP_HI] = 0; + env->features[FEAT_XSAVE_XCR0_LO] = 0; + env->features[FEAT_XSAVE_XCR0_HI] = 0; return; } @@ -6007,8 +6061,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) request_perm = true; } - env->features[FEAT_XSAVE_COMP_LO] = mask; - env->features[FEAT_XSAVE_COMP_HI] = mask >> 32; + env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK; + env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32; + env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK; + env->features[FEAT_XSAVE_XSS_HI] = mask >> 32; } /***** Steps involved on loading and filtering CPUID data diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 6730df5dbf..453b80eae2 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -568,6 +568,14 @@ typedef enum X86Seg { #define ESA_FEATURE_XFD_MASK (1U << ESA_FEATURE_XFD_BIT) +/* CPUID feature bits available in XCR0 */ +#define CPUID_XSTATE_XCR0_MASK (XSTATE_FP_MASK | XSTATE_SSE_MASK | \ + XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \ + XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \ + XSTATE_ZMM_Hi256_MASK | \ + XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK | \ + XSTATE_XTILE_CFG_MASK | XSTATE_XTILE_DATA_MASK) + /* CPUID feature words */ typedef enum FeatureWord { FEAT_1_EDX, /* CPUID[1].EDX */ @@ -586,8 +594,8 @@ typedef enum FeatureWord { FEAT_SVM, /* CPUID[8000_000A].EDX */ FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */ FEAT_6_EAX, /* CPUID[6].EAX */ - FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ - FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_XSAVE_XCR0_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ + FEAT_XSAVE_XCR0_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ FEAT_ARCH_CAPABILITIES, FEAT_CORE_CAPABILITY, FEAT_PERF_CAPABILITIES, @@ -604,6 +612,8 @@ typedef enum FeatureWord { FEAT_SGX_12_0_EAX, /* CPUID[EAX=0x12,ECX=0].EAX (SGX) */ FEAT_SGX_12_0_EBX, /* CPUID[EAX=0x12,ECX=0].EBX (SGX MISCSELECT[31:0]) */ FEAT_SGX_12_1_EAX, /* CPUID[EAX=0x12,ECX=1].EAX (SGX ATTRIBUTES[31:0]) */ + FEAT_XSAVE_XSS_LO, /* CPUID[EAX=0xd,ECX=1].ECX */ + FEAT_XSAVE_XSS_HI, /* CPUID[EAX=0xd,ECX=1].EDX */ FEATURE_WORDS, } FeatureWord; From 10f0abcb3b8a74a4db1412e844b9192dc9768e94 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:55 -0500 Subject: [PATCH 09/23] target/i386: Add XSAVES support for Arch LBR Define Arch LBR bit in XSS and save/restore structure for XSAVE area size calculation. Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-6-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 6 +++++- target/i386/cpu.h | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 643536d05d..1816c37852 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1411,7 +1411,7 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { #undef REGISTER /* CPUID feature bits available in XSS */ -#define CPUID_XSTATE_XSS_MASK (0) +#define CPUID_XSTATE_XSS_MASK (XSTATE_ARCH_LBR_MASK) ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { [XSTATE_FP_BIT] = { @@ -1445,6 +1445,10 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { [XSTATE_PKRU_BIT] = { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, .size = sizeof(XSavePKRU) }, + [XSTATE_ARCH_LBR_BIT] = { + .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_ARCH_LBR, + .offset = 0 /*supervisor mode component, offset = 0 */, + .size = sizeof(XSavesArchLBR) }, [XSTATE_XTILE_CFG_BIT] = { .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE, .size = sizeof(XSaveXTILECFG), diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 453b80eae2..dba92936a2 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -544,6 +544,7 @@ typedef enum X86Seg { #define XSTATE_ZMM_Hi256_BIT 6 #define XSTATE_Hi16_ZMM_BIT 7 #define XSTATE_PKRU_BIT 9 +#define XSTATE_ARCH_LBR_BIT 15 #define XSTATE_XTILE_CFG_BIT 17 #define XSTATE_XTILE_DATA_BIT 18 @@ -556,6 +557,7 @@ typedef enum X86Seg { #define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT) #define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT) #define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT) +#define XSTATE_ARCH_LBR_MASK (1ULL << XSTATE_ARCH_LBR_BIT) #define XSTATE_XTILE_CFG_MASK (1ULL << XSTATE_XTILE_CFG_BIT) #define XSTATE_XTILE_DATA_MASK (1ULL << XSTATE_XTILE_DATA_BIT) @@ -870,6 +872,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, #define CPUID_7_0_EDX_SERIALIZE (1U << 14) /* TSX Suspend Load Address Tracking instruction */ #define CPUID_7_0_EDX_TSX_LDTRK (1U << 16) +/* Architectural LBRs */ +#define CPUID_7_0_EDX_ARCH_LBR (1U << 19) /* AVX512_FP16 instruction */ #define CPUID_7_0_EDX_AVX512_FP16 (1U << 23) /* AMX tile (two-dimensional register) */ @@ -1376,6 +1380,24 @@ typedef struct XSaveXTILEDATA { uint8_t xtiledata[8][1024]; } XSaveXTILEDATA; +typedef struct { + uint64_t from; + uint64_t to; + uint64_t info; +} LBREntry; + +#define ARCH_LBR_NR_ENTRIES 32 + +/* Ext. save area 19: Supervisor mode Arch LBR state */ +typedef struct XSavesArchLBR { + uint64_t lbr_ctl; + uint64_t lbr_depth; + uint64_t ler_from; + uint64_t ler_to; + uint64_t ler_info; + LBREntry lbr_records[ARCH_LBR_NR_ENTRIES]; +} XSavesArchLBR; + QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); @@ -1385,6 +1407,7 @@ QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400); QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); QEMU_BUILD_BUG_ON(sizeof(XSaveXTILECFG) != 0x40); QEMU_BUILD_BUG_ON(sizeof(XSaveXTILEDATA) != 0x2000); +QEMU_BUILD_BUG_ON(sizeof(XSavesArchLBR) != 0x328); typedef struct ExtSaveArea { uint32_t feature, bits; From 12703d4e7523a7841764200e1a7838736495da10 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:56 -0500 Subject: [PATCH 10/23] target/i386: Add MSR access interface for Arch LBR In the first generation of Arch LBR, the max support Arch LBR depth is 32, both host and guest use the value to set depth MSR. This can simplify the implementation of patch given the side-effect of mismatch of host/guest depth MSR: XRSTORS will reset all recording MSRs to 0s if the saved depth mismatches MSR_ARCH_LBR_DEPTH. In most of the cases Arch LBR is not in active status, so check the control bit before save/restore the big chunck of Arch LBR MSRs. Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-7-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 10 +++++++ target/i386/kvm/kvm.c | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index dba92936a2..0d528ac58f 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -391,6 +391,11 @@ typedef enum X86Seg { #define MSR_IA32_TSX_CTRL 0x122 #define MSR_IA32_TSCDEADLINE 0x6e0 #define MSR_IA32_PKRS 0x6e1 +#define MSR_ARCH_LBR_CTL 0x000014ce +#define MSR_ARCH_LBR_DEPTH 0x000014cf +#define MSR_ARCH_LBR_FROM_0 0x00001500 +#define MSR_ARCH_LBR_TO_0 0x00001600 +#define MSR_ARCH_LBR_INFO_0 0x00001200 #define FEATURE_CONTROL_LOCKED (1<<0) #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1ULL << 1) @@ -1650,6 +1655,11 @@ typedef struct CPUArchState { uint64_t msr_xfd; uint64_t msr_xfd_err; + /* Per-VCPU Arch LBR MSRs */ + uint64_t msr_lbr_ctl; + uint64_t msr_lbr_depth; + LBREntry lbr_records[ARCH_LBR_NR_ENTRIES]; + /* exception/interrupt handling */ int error_code; int exception_is_int; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 536cbe5fad..a9ee8eebd7 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -3367,6 +3367,38 @@ static int kvm_put_msrs(X86CPU *cpu, int level) env->msr_xfd_err); } + if (kvm_enabled() && cpu->enable_pmu && + (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) { + uint64_t depth; + int i, ret; + + /* + * Only migrate Arch LBR states when: 1) Arch LBR is enabled + * for migrated vcpu. 2) the host Arch LBR depth equals that + * of source guest's, this is to avoid mismatch of guest/host + * config for the msr hence avoid unexpected misbehavior. + */ + ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, &depth); + + if (ret == 1 && (env->msr_lbr_ctl & 0x1) && !!depth && + depth == env->msr_lbr_depth) { + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, env->msr_lbr_ctl); + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, env->msr_lbr_depth); + + for (i = 0; i < ARCH_LBR_NR_ENTRIES; i++) { + if (!env->lbr_records[i].from) { + continue; + } + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_FROM_0 + i, + env->lbr_records[i].from); + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_TO_0 + i, + env->lbr_records[i].to); + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_INFO_0 + i, + env->lbr_records[i].info); + } + } + } + /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see * kvm_put_msr_feature_control. */ } @@ -3767,6 +3799,26 @@ static int kvm_get_msrs(X86CPU *cpu) kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0); } + if (kvm_enabled() && cpu->enable_pmu && + (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) { + uint64_t ctl, depth; + int i, ret2; + + ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_CTL, &ctl); + ret2 = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, &depth); + if (ret == 1 && ret2 == 1 && (ctl & 0x1) && + depth == ARCH_LBR_NR_ENTRIES) { + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, 0); + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, 0); + + for (i = 0; i < ARCH_LBR_NR_ENTRIES; i++) { + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_FROM_0 + i, 0); + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_TO_0 + i, 0); + kvm_msr_entry_add(cpu, MSR_ARCH_LBR_INFO_0 + i, 0); + } + } + } + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; @@ -4072,6 +4124,21 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_IA32_XFD_ERR: env->msr_xfd_err = msrs[i].data; break; + case MSR_ARCH_LBR_CTL: + env->msr_lbr_ctl = msrs[i].data; + break; + case MSR_ARCH_LBR_DEPTH: + env->msr_lbr_depth = msrs[i].data; + break; + case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31: + env->lbr_records[index - MSR_ARCH_LBR_FROM_0].from = msrs[i].data; + break; + case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31: + env->lbr_records[index - MSR_ARCH_LBR_TO_0].to = msrs[i].data; + break; + case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31: + env->lbr_records[index - MSR_ARCH_LBR_INFO_0].info = msrs[i].data; + break; } } From f2e7c2fc8945943699f745c405be82ac7e698275 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:57 -0500 Subject: [PATCH 11/23] target/i386: Enable Arch LBR migration states in vmstate The Arch LBR record MSRs and control MSRs will be migrated to destination guest if the vcpus were running with Arch LBR active. Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-8-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/machine.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/target/i386/machine.c b/target/i386/machine.c index 7c54bada81..cecd476e98 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -136,6 +136,22 @@ static const VMStateDescription vmstate_mtrr_var = { #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) +static const VMStateDescription vmstate_lbr_records_var = { + .name = "lbr_records_var", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64(from, LBREntry), + VMSTATE_UINT64(to, LBREntry), + VMSTATE_UINT64(info, LBREntry), + VMSTATE_END_OF_LIST() + } +}; + +#define VMSTATE_LBR_VARS(_field, _state, _n, _v) \ + VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_lbr_records_var, \ + LBREntry) + typedef struct x86_FPReg_tmp { FPReg *parent; uint64_t tmp_mant; @@ -1525,6 +1541,27 @@ static const VMStateDescription vmstate_amx_xtile = { }; #endif +static bool arch_lbr_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return !!(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR); +} + +static const VMStateDescription vmstate_arch_lbr = { + .name = "cpu/arch_lbr", + .version_id = 1, + .minimum_version_id = 1, + .needed = arch_lbr_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64(env.msr_lbr_ctl, X86CPU), + VMSTATE_UINT64(env.msr_lbr_depth, X86CPU), + VMSTATE_LBR_VARS(env.lbr_records, X86CPU, ARCH_LBR_NR_ENTRIES, 1), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_x86_cpu = { .name = "cpu", .version_id = 12, @@ -1668,6 +1705,7 @@ const VMStateDescription vmstate_x86_cpu = { #ifdef TARGET_X86_64 &vmstate_amx_xtile, #endif + &vmstate_arch_lbr, NULL } }; From d19d6ffa07100f5015dc1c708d6c811354a13d7f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 29 Apr 2022 20:52:52 +0200 Subject: [PATCH 12/23] target/i386: introduce helper to access supported CPUID Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 1816c37852..dcc770ecea 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4944,6 +4944,28 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, return r; } +static void x86_cpu_get_supported_cpuid(uint32_t func, uint32_t index, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + if (kvm_enabled()) { + *eax = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_EAX); + *ebx = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_EBX); + *ecx = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_ECX); + *edx = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_EDX); + } else if (hvf_enabled()) { + *eax = hvf_get_supported_cpuid(func, index, R_EAX); + *ebx = hvf_get_supported_cpuid(func, index, R_EBX); + *ecx = hvf_get_supported_cpuid(func, index, R_ECX); + *edx = hvf_get_supported_cpuid(func, index, R_EDX); + } else { + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + } +} + static void x86_cpu_get_cache_cpuid(uint32_t func, uint32_t index, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) @@ -5359,18 +5381,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0xA: /* Architectural Performance Monitoring Leaf */ - if (kvm_enabled() && cpu->enable_pmu) { - KVMState *s = cs->kvm_state; - - *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); - *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); - *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX); - *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX); - } else if (hvf_enabled() && cpu->enable_pmu) { - *eax = hvf_get_supported_cpuid(0xA, count, R_EAX); - *ebx = hvf_get_supported_cpuid(0xA, count, R_EBX); - *ecx = hvf_get_supported_cpuid(0xA, count, R_ECX); - *edx = hvf_get_supported_cpuid(0xA, count, R_EDX); + if (accel_uses_host_cpuid() && cpu->enable_pmu) { + x86_cpu_get_supported_cpuid(0xA, count, eax, ebx, ecx, edx); } else { *eax = 0; *ebx = 0; @@ -5521,10 +5533,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, * supports. Features can be further restricted by userspace, but not * made more permissive. */ - *eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EAX); - *ebx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EBX); - *ecx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_ECX); - *edx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EDX); + x86_cpu_get_supported_cpuid(0x12, index, eax, ebx, ecx, edx); if (count == 0) { *eax &= env->features[FEAT_SGX_12_0_EAX]; From c3c67679f65903b7d1fe25da8fc4e163878ab2b9 Mon Sep 17 00:00:00 2001 From: Yang Weijiang Date: Tue, 15 Feb 2022 14:52:58 -0500 Subject: [PATCH 13/23] target/i386: Support Arch LBR in CPUID enumeration If CPUID.(EAX=07H, ECX=0):EDX[19] is set to 1, the processor supports Architectural LBRs. In this case, CPUID leaf 01CH indicates details of the Architectural LBRs capabilities. XSAVE support for Architectural LBRs is enumerated in CPUID.(EAX=0DH, ECX=0FH). Signed-off-by: Yang Weijiang Message-Id: <20220215195258.29149-9-weijiang.yang@intel.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index dcc770ecea..35c3475e6c 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -855,7 +855,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "fsrm", NULL, NULL, NULL, "avx512-vp2intersect", NULL, "md-clear", NULL, NULL, NULL, "serialize", NULL, - "tsx-ldtrk", NULL, NULL /* pconfig */, NULL, + "tsx-ldtrk", NULL, NULL /* pconfig */, "arch-lbr", NULL, NULL, "amx-bf16", "avx512-fp16", "amx-tile", "amx-int8", "spec-ctrl", "stibp", NULL, "arch-capabilities", "core-capability", "ssbd", @@ -5420,6 +5420,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, assert(!(*eax & ~0x1f)); *ebx &= 0xffff; /* The count doesn't need to be reliable. */ break; + case 0x1C: + if (accel_uses_host_cpuid() && cpu->enable_pmu && + (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) { + x86_cpu_get_supported_cpuid(0x1C, 0, eax, ebx, ecx, edx); + *edx = 0; + } + break; case 0x1F: /* V2 Extended Topology Enumeration Leaf */ if (env->nr_dies < 2) { @@ -5482,6 +5489,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ebx = xsave_area_size(xstate, true); *ecx = env->features[FEAT_XSAVE_XSS_LO]; *edx = env->features[FEAT_XSAVE_XSS_HI]; + if (kvm_enabled() && cpu->enable_pmu && + (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR) && + (*eax & CPUID_XSAVE_XSAVES)) { + *ecx |= XSTATE_ARCH_LBR_MASK; + } else { + *ecx &= ~XSTATE_ARCH_LBR_MASK; + } + } else if (count == 0xf && + accel_uses_host_cpuid() && cpu->enable_pmu && + (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) { + x86_cpu_get_supported_cpuid(0xD, count, eax, ebx, ecx, edx); } else if (count < ARRAY_SIZE(x86_ext_save_areas)) { const ExtSaveArea *esa = &x86_ext_save_areas[count]; From 0310641c06dd5f7ea031b2b6170cb2edc63e4cea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 9 May 2022 11:42:23 +0200 Subject: [PATCH 14/23] crypto: make loaded property read-only The ``loaded=on`` option in the command line or QMP ``object-add`` either had no effect (if ``loaded`` was the last option) or caused options to be effectively ignored as if they were not given. The property is therefore useless and was deprecated in 6.0; make it read-only now. The patch is best reviewed with "-b". Signed-off-by: Paolo Bonzini --- crypto/secret_common.c | 84 ++++++++++++++------------------- crypto/tlscredsanon.c | 20 ++------ crypto/tlscredspsk.c | 20 ++------ crypto/tlscredsx509.c | 20 ++------ docs/about/deprecated.rst | 10 ---- docs/about/removed-features.rst | 9 ++++ 6 files changed, 56 insertions(+), 107 deletions(-) diff --git a/crypto/secret_common.c b/crypto/secret_common.c index 714a15d5e5..3441c44ca8 100644 --- a/crypto/secret_common.c +++ b/crypto/secret_common.c @@ -138,36 +138,44 @@ static void qcrypto_secret_decode(const uint8_t *input, static void -qcrypto_secret_prop_set_loaded(Object *obj, - bool value, - Error **errp) +qcrypto_secret_complete(UserCreatable *uc, Error **errp) { - QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); + QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(uc); QCryptoSecretCommonClass *sec_class - = QCRYPTO_SECRET_COMMON_GET_CLASS(obj); + = QCRYPTO_SECRET_COMMON_GET_CLASS(uc); - if (value) { - Error *local_err = NULL; - uint8_t *input = NULL; - size_t inputlen = 0; - uint8_t *output = NULL; - size_t outputlen = 0; + Error *local_err = NULL; + uint8_t *input = NULL; + size_t inputlen = 0; + uint8_t *output = NULL; + size_t outputlen = 0; - if (sec_class->load_data) { - sec_class->load_data(secret, &input, &inputlen, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - } else { - error_setg(errp, "%s provides no 'load_data' method'", - object_get_typename(obj)); + if (sec_class->load_data) { + sec_class->load_data(secret, &input, &inputlen, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } + } else { + error_setg(errp, "%s provides no 'load_data' method'", + object_get_typename(OBJECT(uc))); + return; + } - if (secret->keyid) { - qcrypto_secret_decrypt(secret, input, inputlen, - &output, &outputlen, &local_err); + if (secret->keyid) { + qcrypto_secret_decrypt(secret, input, inputlen, + &output, &outputlen, &local_err); + g_free(input); + if (local_err) { + error_propagate(errp, local_err); + return; + } + input = output; + inputlen = outputlen; + } else { + if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { + qcrypto_secret_decode(input, inputlen, + &output, &outputlen, &local_err); g_free(input); if (local_err) { error_propagate(errp, local_err); @@ -175,26 +183,11 @@ qcrypto_secret_prop_set_loaded(Object *obj, } input = output; inputlen = outputlen; - } else { - if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { - qcrypto_secret_decode(input, inputlen, - &output, &outputlen, &local_err); - g_free(input); - if (local_err) { - error_propagate(errp, local_err); - return; - } - input = output; - inputlen = outputlen; - } } - - secret->rawdata = input; - secret->rawlen = inputlen; - } else if (secret->rawdata) { - error_setg(errp, "Cannot unload secret"); - return; } + + secret->rawdata = input; + secret->rawlen = inputlen; } @@ -268,13 +261,6 @@ qcrypto_secret_prop_get_keyid(Object *obj, } -static void -qcrypto_secret_complete(UserCreatable *uc, Error **errp) -{ - object_property_set_bool(OBJECT(uc), "loaded", true, errp); -} - - static void qcrypto_secret_finalize(Object *obj) { @@ -294,7 +280,7 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, "loaded", qcrypto_secret_prop_get_loaded, - qcrypto_secret_prop_set_loaded); + NULL); object_class_property_add_enum(oc, "format", "QCryptoSecretFormat", &QCryptoSecretFormat_lookup, diff --git a/crypto/tlscredsanon.c b/crypto/tlscredsanon.c index 6fb83639ec..c0d23a0ef3 100644 --- a/crypto/tlscredsanon.c +++ b/crypto/tlscredsanon.c @@ -119,16 +119,11 @@ qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED) static void -qcrypto_tls_creds_anon_prop_set_loaded(Object *obj, - bool value, - Error **errp) +qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp) { - QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj); + QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(uc); - qcrypto_tls_creds_anon_unload(creds); - if (value) { - qcrypto_tls_creds_anon_load(creds, errp); - } + qcrypto_tls_creds_anon_load(creds, errp); } @@ -163,13 +158,6 @@ qcrypto_tls_creds_anon_prop_get_loaded(Object *obj G_GNUC_UNUSED, #endif /* ! CONFIG_GNUTLS */ -static void -qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp) -{ - object_property_set_bool(OBJECT(uc), "loaded", true, errp); -} - - static void qcrypto_tls_creds_anon_finalize(Object *obj) { @@ -188,7 +176,7 @@ qcrypto_tls_creds_anon_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, "loaded", qcrypto_tls_creds_anon_prop_get_loaded, - qcrypto_tls_creds_anon_prop_set_loaded); + NULL); } diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c index 752f2d92be..a4f9891274 100644 --- a/crypto/tlscredspsk.c +++ b/crypto/tlscredspsk.c @@ -188,16 +188,11 @@ qcrypto_tls_creds_psk_unload(QCryptoTLSCredsPSK *creds G_GNUC_UNUSED) static void -qcrypto_tls_creds_psk_prop_set_loaded(Object *obj, - bool value, - Error **errp) +qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp) { - QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj); + QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(uc); - qcrypto_tls_creds_psk_unload(creds); - if (value) { - qcrypto_tls_creds_psk_load(creds, errp); - } + qcrypto_tls_creds_psk_load(creds, errp); } @@ -232,13 +227,6 @@ qcrypto_tls_creds_psk_prop_get_loaded(Object *obj G_GNUC_UNUSED, #endif /* ! CONFIG_GNUTLS */ -static void -qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp) -{ - object_property_set_bool(OBJECT(uc), "loaded", true, errp); -} - - static void qcrypto_tls_creds_psk_finalize(Object *obj) { @@ -276,7 +264,7 @@ qcrypto_tls_creds_psk_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, "loaded", qcrypto_tls_creds_psk_prop_get_loaded, - qcrypto_tls_creds_psk_prop_set_loaded); + NULL); object_class_property_add_str(oc, "username", qcrypto_tls_creds_psk_prop_get_username, qcrypto_tls_creds_psk_prop_set_username); diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c index 32948a6bdc..d14313925d 100644 --- a/crypto/tlscredsx509.c +++ b/crypto/tlscredsx509.c @@ -687,16 +687,11 @@ qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED) static void -qcrypto_tls_creds_x509_prop_set_loaded(Object *obj, - bool value, - Error **errp) +qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp) { - QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); + QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(uc); - qcrypto_tls_creds_x509_unload(creds); - if (value) { - qcrypto_tls_creds_x509_load(creds, errp); - } + qcrypto_tls_creds_x509_load(creds, errp); } @@ -814,13 +809,6 @@ qcrypto_tls_creds_x509_reload(QCryptoTLSCreds *creds, Error **errp) #endif /* ! CONFIG_GNUTLS */ -static void -qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp) -{ - object_property_set_bool(OBJECT(uc), "loaded", true, errp); -} - - static void qcrypto_tls_creds_x509_init(Object *obj) { @@ -852,7 +840,7 @@ qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, "loaded", qcrypto_tls_creds_x509_prop_get_loaded, - qcrypto_tls_creds_x509_prop_set_loaded); + NULL); object_class_property_add_bool(oc, "sanity-check", qcrypto_tls_creds_x509_prop_get_sanity, qcrypto_tls_creds_x509_prop_set_sanity); diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 44f52c172d..2a022f2300 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -99,16 +99,6 @@ other options have been processed. This will either have no effect (if ``opened`` was the last option) or cause errors. The property is therefore useless and should not be specified. -``loaded`` property of ``secret`` and ``secret_keyring`` objects (since 6.0) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -The only effect of specifying ``loaded=on`` in the command line or QMP -``object-add`` is that the secret is loaded immediately, possibly before all -other options have been processed. This will either have no effect (if -``loaded`` was the last option) or cause options to be effectively ignored as -if they were not given. The property is therefore useless and should not be -specified. - ``-display sdl,window_close=...`` (since 6.1) ''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index ba78bc1a19..81ceeb9000 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -355,6 +355,15 @@ The ``-writeconfig`` option was not able to serialize the entire contents of the QEMU command line. It is thus considered a failed experiment and removed without a replacement. +``loaded`` property of ``secret`` and ``secret_keyring`` objects (removed in 7.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``loaded=on`` option in the command line or QMP ``object-add`` either had +no effect (if ``loaded`` was the last option) or caused options to be +effectively ignored as if they were not given. The property is therefore +useless and should simply be removed. + + QEMU Machine Protocol (QMP) commands ------------------------------------ From 6e577937485080f2dcebc6a3e5a4a9e8db841762 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 9 May 2022 11:46:03 +0200 Subject: [PATCH 15/23] rng: make opened property read-only The ``opened=on`` option in the command line or QMP ``object-add`` either had no effect (if ``opened`` was the last option) or caused errors. The property is therefore useless and was deprecated in 6.0; make it read-only now. Signed-off-by: Paolo Bonzini --- backends/rng.c | 18 ++---------------- docs/about/deprecated.rst | 9 --------- docs/about/removed-features.rst | 6 ++++++ 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/backends/rng.c b/backends/rng.c index 3757b04485..6c7bf64426 100644 --- a/backends/rng.c +++ b/backends/rng.c @@ -48,24 +48,10 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp) static void rng_backend_complete(UserCreatable *uc, Error **errp) { - object_property_set_bool(OBJECT(uc), "opened", true, errp); -} - -static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp) -{ - RngBackend *s = RNG_BACKEND(obj); + RngBackend *s = RNG_BACKEND(uc); RngBackendClass *k = RNG_BACKEND_GET_CLASS(s); Error *local_err = NULL; - if (value == s->opened) { - return; - } - - if (!value && s->opened) { - error_setg(errp, QERR_PERMISSION_DENIED); - return; - } - if (k->opened) { k->opened(s, &local_err); if (local_err) { @@ -122,7 +108,7 @@ static void rng_backend_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, "opened", rng_backend_prop_get_opened, - rng_backend_prop_set_opened); + NULL); } static const TypeInfo rng_backend_info = { diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 2a022f2300..1f961b9e6e 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -90,15 +90,6 @@ the process listing. This is replaced by the new ``password-secret`` option which lets the password be securely provided on the command line using a ``secret`` object instance. -``opened`` property of ``rng-*`` objects (since 6.0) -'''''''''''''''''''''''''''''''''''''''''''''''''''' - -The only effect of specifying ``opened=on`` in the command line or QMP -``object-add`` is that the device is opened immediately, possibly before all -other options have been processed. This will either have no effect (if -``opened`` was the last option) or cause errors. The property is therefore -useless and should not be specified. - ``-display sdl,window_close=...`` (since 6.1) ''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 81ceeb9000..69498efd51 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -363,6 +363,12 @@ no effect (if ``loaded`` was the last option) or caused options to be effectively ignored as if they were not given. The property is therefore useless and should simply be removed. +``opened`` property of ``rng-*`` objects (removed in 7.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The ``opened=on`` option in the command line or QMP ``object-add`` either had +no effect (if ``opened`` was the last option) or caused errors. The property +is therefore useless and should simply be removed. QEMU Machine Protocol (QMP) commands ------------------------------------ From 9c50b8aae2b411b253edaee77d76d297e5fa2fab Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Apr 2022 12:04:47 +0200 Subject: [PATCH 16/23] soundhw: remove ability to create multiple soundcards The usefulness of enabling a dozen soundcards is dubious. Simplify the code by allowing a single instance of -soundhw, with no support for parsing either comma-separated values or 'soundhw all'. Signed-off-by: Paolo Bonzini --- hw/audio/soundhw.c | 88 +++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 56 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index f7d94d7dfa..097501fee1 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -25,6 +25,7 @@ #include "qemu/option.h" #include "qemu/help_option.h" #include "qemu/error-report.h" +#include "qapi/error.h" #include "qom/object.h" #include "hw/isa/isa.h" #include "hw/pci/pci.h" @@ -34,7 +35,6 @@ struct soundhw { const char *name; const char *descr; const char *typename; - int enabled; int isa; int (*init_pci) (PCIBus *bus); }; @@ -64,10 +64,16 @@ void deprecated_register_soundhw(const char *name, const char *descr, soundhw_count++; } +static struct soundhw *selected = NULL; + void select_soundhw(const char *optarg) { struct soundhw *c; + if (selected) { + error_setg(&error_fatal, "only one -soundhw option is allowed"); + } + if (is_help_option(optarg)) { show_valid_cards: @@ -84,44 +90,15 @@ void select_soundhw(const char *optarg) exit(!is_help_option(optarg)); } else { - size_t l; - const char *p; - char *e; - int bad_card = 0; - - if (!strcmp(optarg, "all")) { - for (c = soundhw; c->name; ++c) { - c->enabled = 1; + for (c = soundhw; c->name; ++c) { + if (g_str_equal(c->name, optarg)) { + selected = c; + break; } - return; } - p = optarg; - while (*p) { - e = strchr(p, ','); - l = !e ? strlen(p) : (size_t) (e - p); - - for (c = soundhw; c->name; ++c) { - if (!strncmp(c->name, p, l) && !c->name[l]) { - c->enabled = 1; - break; - } - } - - if (!c->name) { - if (l > 80) { - error_report("Unknown sound card name (too big to show)"); - } - else { - error_report("Unknown sound card name `%.*s'", - (int) l, p); - } - bad_card = 1; - } - p += l + (e != NULL); - } - - if (bad_card) { + if (!c->name) { + error_report("Unknown sound card name `%s'", optarg); goto show_valid_cards; } } @@ -129,30 +106,29 @@ void select_soundhw(const char *optarg) void soundhw_init(void) { - struct soundhw *c; + struct soundhw *c = selected; ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL); PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL); - for (c = soundhw; c->name; ++c) { - if (c->enabled) { - if (c->typename) { - warn_report("'-soundhw %s' is deprecated, " - "please use '-device %s' instead", - c->name, c->typename); - if (c->isa) { - isa_create_simple(isa_bus, c->typename); - } else { - pci_create_simple(pci_bus, -1, c->typename); - } - } else { - assert(!c->isa); - if (!pci_bus) { - error_report("PCI bus not available for %s", c->name); - exit(1); - } - c->init_pci(pci_bus); - } + if (!c) { + return; + } + if (c->typename) { + warn_report("'-soundhw %s' is deprecated, " + "please use '-device %s' instead", + c->name, c->typename); + if (c->isa) { + isa_create_simple(isa_bus, c->typename); + } else { + pci_create_simple(pci_bus, -1, c->typename); } + } else { + assert(!c->isa); + if (!pci_bus) { + error_report("PCI bus not available for %s", c->name); + exit(1); + } + c->init_pci(pci_bus); } } From eef5fdf3d57dccc25505179f717adf636764ba02 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Apr 2022 12:26:48 +0200 Subject: [PATCH 17/23] soundhw: extract soundhw help to a separate function Signed-off-by: Paolo Bonzini --- hw/audio/soundhw.c | 33 +++++++++++++++++++-------------- include/hw/audio/soundhw.h | 1 + 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index 097501fee1..0fb64bdc8f 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -64,6 +64,21 @@ void deprecated_register_soundhw(const char *name, const char *descr, soundhw_count++; } +void show_valid_soundhw(void) +{ + struct soundhw *c; + + if (soundhw_count) { + printf("Valid sound card names (comma separated):\n"); + for (c = soundhw; c->name; ++c) { + printf ("%-11s %s\n", c->name, c->descr); + } + } else { + printf("Machine has no user-selectable audio hardware " + "(it may or may not have always-present audio hardware).\n"); + } +} + static struct soundhw *selected = NULL; void select_soundhw(const char *optarg) @@ -75,19 +90,8 @@ void select_soundhw(const char *optarg) } if (is_help_option(optarg)) { - show_valid_cards: - - if (soundhw_count) { - printf("Valid sound card names (comma separated):\n"); - for (c = soundhw; c->name; ++c) { - printf ("%-11s %s\n", c->name, c->descr); - } - printf("\n-soundhw all will enable all of the above\n"); - } else { - printf("Machine has no user-selectable audio hardware " - "(it may or may not have always-present audio hardware).\n"); - } - exit(!is_help_option(optarg)); + show_valid_soundhw(); + exit(0); } else { for (c = soundhw; c->name; ++c) { @@ -99,7 +103,8 @@ void select_soundhw(const char *optarg) if (!c->name) { error_report("Unknown sound card name `%s'", optarg); - goto show_valid_cards; + show_valid_soundhw(); + exit(1); } } } diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h index e68685fcda..dec5c0cdca 100644 --- a/include/hw/audio/soundhw.h +++ b/include/hw/audio/soundhw.h @@ -7,6 +7,7 @@ void deprecated_register_soundhw(const char *name, const char *descr, int isa, const char *typename); void soundhw_init(void); +void show_valid_soundhw(void); void select_soundhw(const char *optarg); #endif From bf521c5655f7f821603d921e6de77e4e05fa44b9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Apr 2022 12:06:59 +0200 Subject: [PATCH 18/23] soundhw: unify initialization for ISA and PCI soundhw Use qdev_new instead of distinguishing isa_create_simple/pci_create_simple. Signed-off-by: Paolo Bonzini --- hw/audio/soundhw.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index 0fb64bdc8f..a1558dab3a 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -114,25 +114,30 @@ void soundhw_init(void) struct soundhw *c = selected; ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL); PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL); + BusState *bus; if (!c) { return; } - if (c->typename) { - warn_report("'-soundhw %s' is deprecated, " - "please use '-device %s' instead", - c->name, c->typename); - if (c->isa) { - isa_create_simple(isa_bus, c->typename); - } else { - pci_create_simple(pci_bus, -1, c->typename); + if (c->isa) { + if (!isa_bus) { + error_report("ISA bus not available for %s", c->name); + exit(1); } + bus = BUS(isa_bus); } else { - assert(!c->isa); if (!pci_bus) { error_report("PCI bus not available for %s", c->name); exit(1); } + bus = BUS(pci_bus); + } + + if (c->typename) { + DeviceState *dev = qdev_new(c->typename); + qdev_realize_and_unref(dev, bus, &error_fatal); + } else { + assert(!c->isa); c->init_pci(pci_bus); } } From 67aaa96ae451913ffd25766dc59341fe6b63619d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Apr 2022 13:15:23 +0200 Subject: [PATCH 19/23] soundhw: move help handling to vl.c This will allow processing "-audio model=help" even if the backend part of the option is missing. Signed-off-by: Paolo Bonzini --- hw/audio/soundhw.c | 24 +++++++++--------------- softmmu/vl.c | 4 ++++ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index a1558dab3a..ebbd0958ba 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -89,23 +89,17 @@ void select_soundhw(const char *optarg) error_setg(&error_fatal, "only one -soundhw option is allowed"); } - if (is_help_option(optarg)) { - show_valid_soundhw(); - exit(0); + for (c = soundhw; c->name; ++c) { + if (g_str_equal(c->name, optarg)) { + selected = c; + break; + } } - else { - for (c = soundhw; c->name; ++c) { - if (g_str_equal(c->name, optarg)) { - selected = c; - break; - } - } - if (!c->name) { - error_report("Unknown sound card name `%s'", optarg); - show_valid_soundhw(); - exit(1); - } + if (!c->name) { + error_report("Unknown sound card name `%s'", optarg); + show_valid_soundhw(); + exit(1); } } diff --git a/softmmu/vl.c b/softmmu/vl.c index 817d515783..0363cbd9b4 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2931,6 +2931,10 @@ void qemu_init(int argc, char **argv, char **envp) audio_parse_option(optarg); break; case QEMU_OPTION_soundhw: + if (is_help_option(optarg)) { + show_valid_soundhw(); + exit(0); + } select_soundhw (optarg); break; case QEMU_OPTION_h: From 039a68373c4544ff94871f945a733928b6dcfe93 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Apr 2022 12:27:46 +0200 Subject: [PATCH 20/23] introduce -audio as a replacement for -soundhw -audio is used like "-audio pa,model=sb16". It is almost as simple as -soundhw, but it reuses the -audiodev parsing machinery and attaches an audiodev to the newly-created device. The main 'feature' is that it knows about adding the codec device for model=intel-hda, and adding the audiodev to the codec device. In the future, it could be extended to support default models or builtin devices, just like -nic, or even a default backend. For now, keep it simple. Signed-off-by: Paolo Bonzini --- audio/audio.c | 8 +++++- audio/audio.h | 1 + docs/about/deprecated.rst | 9 ------ docs/about/removed-features.rst | 7 +++++ hw/audio/intel-hda.c | 5 ++-- hw/audio/soundhw.c | 12 +++++--- include/hw/audio/soundhw.h | 4 +-- qemu-options.hx | 51 ++++++++++++++++----------------- softmmu/vl.c | 28 ++++++++++++++++-- 9 files changed, 76 insertions(+), 49 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 9e91a5a4f2..a02f3ce5c6 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2099,13 +2099,19 @@ static void audio_validate_opts(Audiodev *dev, Error **errp) void audio_parse_option(const char *opt) { - AudiodevListEntry *e; Audiodev *dev = NULL; Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal); visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_free(v); + audio_define(dev); +} + +void audio_define(Audiodev *dev) +{ + AudiodevListEntry *e; + audio_validate_opts(dev, &error_fatal); e = g_new0(AudiodevListEntry, 1); diff --git a/audio/audio.h b/audio/audio.h index 3d5ecdecd5..b5e17cd218 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -168,6 +168,7 @@ void audio_sample_to_uint64(const void *samples, int pos, void audio_sample_from_uint64(void *samples, int pos, uint64_t left, uint64_t right); +void audio_define(Audiodev *audio); void audio_parse_option(const char *opt); void audio_init_audiodevs(void); void audio_legacy_help(void); diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 1f961b9e6e..a92ae0f162 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -39,15 +39,6 @@ should specify an ``audiodev=`` property. Additionally, when using vnc, you should specify an ``audiodev=`` property if you plan to transmit audio through the VNC protocol. -Creating sound card devices using ``-soundhw`` (since 5.1) -'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Sound card devices should be created using ``-device`` instead. The -names are the same for most devices. The exceptions are ``hda`` which -needs two devices (``-device intel-hda -device hda-duplex``) and -``pcspk`` which can be activated using ``-machine -pcspk-audiodev=``. - ``-chardev`` backend aliases ``tty`` and ``parport`` (since 6.0) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 69498efd51..eb76974347 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -654,6 +654,13 @@ tripped up the CI testing and was suspected to be quite broken. For that reason the maintainers strongly suspected no one actually used it. +Creating sound card devices using ``-soundhw`` (removed in 7.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Sound card devices should be created using ``-device`` or ``-audio``. +The exception is ``pcspk`` which can be activated using ``-machine +pcspk-audiodev=``. + TCG introspection features -------------------------- diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index bc77e3d8c9..f38117057b 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -1311,17 +1311,16 @@ static const TypeInfo hda_codec_device_type_info = { * create intel hda controller with codec attached to it, * so '-soundhw hda' works. */ -static int intel_hda_and_codec_init(PCIBus *bus) +static int intel_hda_and_codec_init(PCIBus *bus, const char *audiodev) { DeviceState *controller; BusState *hdabus; DeviceState *codec; - warn_report("'-soundhw hda' is deprecated, " - "please use '-device intel-hda -device hda-duplex' instead"); controller = DEVICE(pci_create_simple(bus, -1, "intel-hda")); hdabus = QLIST_FIRST(&controller->child_bus); codec = qdev_new("hda-duplex"); + qdev_prop_set_string(codec, "audiodev", audiodev); qdev_realize_and_unref(codec, hdabus, &error_fatal); return 0; } diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index ebbd0958ba..94d9463e42 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "qom/object.h" +#include "hw/qdev-properties.h" #include "hw/isa/isa.h" #include "hw/pci/pci.h" #include "hw/audio/soundhw.h" @@ -36,14 +37,14 @@ struct soundhw { const char *descr; const char *typename; int isa; - int (*init_pci) (PCIBus *bus); + int (*init_pci) (PCIBus *bus, const char *audiodev); }; static struct soundhw soundhw[9]; static int soundhw_count; void pci_register_soundhw(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus)) + int (*init_pci)(PCIBus *bus, const char *audiodev)) { assert(soundhw_count < ARRAY_SIZE(soundhw) - 1); soundhw[soundhw_count].name = name; @@ -80,8 +81,9 @@ void show_valid_soundhw(void) } static struct soundhw *selected = NULL; +static const char *audiodev_id; -void select_soundhw(const char *optarg) +void select_soundhw(const char *optarg, const char *audiodev) { struct soundhw *c; @@ -92,6 +94,7 @@ void select_soundhw(const char *optarg) for (c = soundhw; c->name; ++c) { if (g_str_equal(c->name, optarg)) { selected = c; + audiodev_id = audiodev; break; } } @@ -129,10 +132,11 @@ void soundhw_init(void) if (c->typename) { DeviceState *dev = qdev_new(c->typename); + qdev_prop_set_string(dev, "audiodev", audiodev_id); qdev_realize_and_unref(dev, bus, &error_fatal); } else { assert(!c->isa); - c->init_pci(pci_bus); + c->init_pci(pci_bus, audiodev_id); } } diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h index dec5c0cdca..270717a06a 100644 --- a/include/hw/audio/soundhw.h +++ b/include/hw/audio/soundhw.h @@ -2,12 +2,12 @@ #define HW_SOUNDHW_H void pci_register_soundhw(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus)); + int (*init_pci)(PCIBus *bus, const char *audiodev)); void deprecated_register_soundhw(const char *name, const char *descr, int isa, const char *typename); void soundhw_init(void); void show_valid_soundhw(void); -void select_soundhw(const char *optarg); +void select_soundhw(const char *optarg, const char *audiodev); #endif diff --git a/qemu-options.hx b/qemu-options.hx index 796229c433..60d2d728d6 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -661,6 +661,30 @@ SRST (deprecated) environment variables. ERST +DEF("audio", HAS_ARG, QEMU_OPTION_audio, + "-audio [driver=]driver,model=value[,prop[=value][,...]]\n" + " specifies the audio backend and device to use;\n" + " apart from 'model', options are the same as for -audiodev.\n" + " use '-audio model=help' to show possible devices.\n", + QEMU_ARCH_ALL) +SRST +``-audio [driver=]driver,model=value[,prop[=value][,...]]`` + This option is a shortcut for configuring both the guest audio + hardware and the host audio backend in one go. + The host backend options are the same as with the corresponding + ``-audiodev`` options below. The guest hardware model can be set with + ``model=modelname``. Use ``model=help`` to list the available device + types. + + The following two example do exactly the same, to show how ``-audio`` + can be used to shorten the command line length: + + .. parsed-literal:: + + |qemu_system| -audiodev pa,id=pa -device sb16,audiodev=pa + |qemu_system| -audio pa,model=sb16 +ERST + DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, "-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n" " specifies the audio backend to use\n" @@ -892,33 +916,6 @@ SRST ``qemu.wav``. ERST -DEF("soundhw", HAS_ARG, QEMU_OPTION_soundhw, - "-soundhw c1,... enable audio support\n" - " and only specified sound cards (comma separated list)\n" - " use '-soundhw help' to get the list of supported cards\n" - " use '-soundhw all' to enable all of them\n", QEMU_ARCH_ALL) -SRST -``-soundhw card1[,card2,...] or -soundhw all`` - Enable audio and selected sound hardware. Use 'help' to print all - available sound hardware. For example: - - .. parsed-literal:: - - |qemu_system_x86| -soundhw sb16,adlib disk.img - |qemu_system_x86| -soundhw es1370 disk.img - |qemu_system_x86| -soundhw ac97 disk.img - |qemu_system_x86| -soundhw hda disk.img - |qemu_system_x86| -soundhw all disk.img - |qemu_system_x86| -soundhw help - - Note that Linux's i810\_audio OSS kernel (for AC97) module might - require manually specifying clocking. - - :: - - modprobe i810_audio clocking=48000 -ERST - DEF("device", HAS_ARG, QEMU_OPTION_device, "-device driver[,prop[=value][,...]]\n" " add device (based on driver)\n" diff --git a/softmmu/vl.c b/softmmu/vl.c index 0363cbd9b4..219b23a573 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -116,6 +116,8 @@ #include "crypto/init.h" #include "sysemu/replay.h" #include "qapi/qapi-events-run-state.h" +#include "qapi/qapi-types-audio.h" +#include "qapi/qapi-visit-audio.h" #include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-compat.h" #include "qapi/qapi-visit-ui.h" @@ -2930,13 +2932,33 @@ void qemu_init(int argc, char **argv, char **envp) case QEMU_OPTION_audiodev: audio_parse_option(optarg); break; - case QEMU_OPTION_soundhw: - if (is_help_option(optarg)) { + case QEMU_OPTION_audio: { + QDict *dict = keyval_parse(optarg, "driver", NULL, &error_fatal); + char *model; + Audiodev *dev = NULL; + Visitor *v; + + if (!qdict_haskey(dict, "id")) { + qdict_put_str(dict, "id", "audiodev0"); + } + if (!qdict_haskey(dict, "model")) { + error_setg(&error_fatal, "Parameter 'model' is missing"); + } + model = g_strdup(qdict_get_str(dict, "model")); + qdict_del(dict, "model"); + if (is_help_option(model)) { show_valid_soundhw(); exit(0); } - select_soundhw (optarg); + v = qobject_input_visitor_new_keyval(QOBJECT(dict)); + qobject_unref(dict); + visit_type_Audiodev(v, NULL, &dev, &error_fatal); + visit_free(v); + audio_define(dev); + select_soundhw(model, dev->id); + g_free(model); break; + } case QEMU_OPTION_h: help(0); break; From 40b3ea76425435ee18395d619e4b3f8f652e25b0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 May 2022 18:06:29 +0200 Subject: [PATCH 21/23] build: remove useless dependency qemu-plugins.symbols is now processed in Meson. Signed-off-by: Paolo Bonzini --- Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile b/Makefile index e5fd1ebdf6..b842dbccdb 100644 --- a/Makefile +++ b/Makefile @@ -165,10 +165,7 @@ ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),) endif endif -# Force configure to re-run if the API symbols are updated ifeq ($(CONFIG_PLUGIN),y) -config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols - .PHONY: plugins plugins: $(call quiet-command,\ From 008f6f20a544cbffe6152aacb69b2774978b49e0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 May 2022 18:06:37 +0200 Subject: [PATCH 22/23] configure: remove another dead variable Signed-off-by: Paolo Bonzini --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index c8b5b99532..dda25f05bf 100755 --- a/configure +++ b/configure @@ -1992,7 +1992,6 @@ fi if test "$static" = "yes" ; then echo "CONFIG_STATIC=y" >> $config_host_mak fi -qemu_version=$(head $source_path/VERSION) echo "SRC_PATH=$source_path" >> $config_host_mak echo "TARGET_DIRS=$target_list" >> $config_host_mak if test "$modules" = "yes"; then From 8eccdb9eb84615291faef1257d5779ebfef7a0d0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 May 2022 11:37:57 +0200 Subject: [PATCH 23/23] configure: remove duplicate help messages These messages are already emitted by scripts/meson-parse-buildoptions.sh. Signed-off-by: Paolo Bonzini --- configure | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configure b/configure index dda25f05bf..0cc8c876f7 100755 --- a/configure +++ b/configure @@ -1043,10 +1043,6 @@ Advanced options (experts only): --enable-tsan enable thread sanitizer --disable-werror disable compilation abort on warning --disable-stack-protector disable compiler-provided stack protection - --audio-drv-list=LIST set audio drivers to try if -audiodev is not used - --block-drv-whitelist=L Same as --block-drv-rw-whitelist=L - --with-trace-file=NAME Full PATH,NAME of file to store traces - Default:trace- --cpu=CPU Build for host CPU [$cpu] --with-coroutine=BACKEND coroutine backend. Supported options: ucontext, sigaltstack, windows