diff --git a/chardev/spice.c b/chardev/spice.c index 3ffb3fdc0d..bbffef4913 100644 --- a/chardev/spice.c +++ b/chardev/spice.c @@ -382,6 +382,7 @@ static const TypeInfo char_spicevmc_type_info = { .parent = TYPE_CHARDEV_SPICE, .class_init = char_spicevmc_class_init, }; +module_obj(TYPE_CHARDEV_SPICEVMC); static void char_spiceport_class_init(ObjectClass *oc, void *data) { diff --git a/configure b/configure index b5965b159f..0005cd140d 100755 --- a/configure +++ b/configure @@ -305,14 +305,14 @@ virtiofsd="auto" virtfs="auto" libudev="auto" mpath="auto" -vnc="enabled" +vnc="auto" sparse="auto" vde="$default_feature" vnc_sasl="auto" vnc_jpeg="auto" vnc_png="auto" xkbcommon="auto" -xen="$default_feature" +xen=${default_feature:+disabled} xen_ctrl_version="$default_feature" xen_pci_passthrough="auto" linux_aio="$default_feature" @@ -322,6 +322,7 @@ attr="auto" xfs="$default_feature" tcg="enabled" membarrier="$default_feature" +vhost_kernel="$default_feature" vhost_net="$default_feature" vhost_crypto="$default_feature" vhost_scsi="$default_feature" @@ -329,6 +330,7 @@ vhost_vsock="$default_feature" vhost_user="no" vhost_user_blk_server="auto" vhost_user_fs="$default_feature" +vhost_vdpa="$default_feature" bpf="auto" kvm="auto" hax="auto" @@ -3273,18 +3275,6 @@ if ! compile_prog "$glib_cflags" "$glib_libs" ; then "build target" fi -# Silence clang 3.5.0 warnings about glib attribute __alloc_size__ usage -cat > $TMPC << EOF -#include -int main(void) { return 0; } -EOF -if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then - if cc_has_warning_flag "-Wno-unknown-attributes"; then - glib_cflags="-Wno-unknown-attributes $glib_cflags" - CONFIGURE_CFLAGS="-Wno-unknown-attributes $CONFIGURE_CFLAGS" - fi -fi - # Silence clang warnings triggered by glib < 2.57.2 cat > $TMPC << EOF #include @@ -5221,7 +5211,7 @@ if test "$skip_meson" = no; then -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \ -Dvhost_user_blk_server=$vhost_user_blk_server -Dmultiprocess=$multiprocess \ -Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi -Dbpf=$bpf\ - $(if test "$default_features" = no; then echo "-Dauto_features=disabled"; fi) \ + $(if test "$default_feature" = no; then echo "-Dauto_features=disabled"; fi) \ -Dtcg_interpreter=$tcg_interpreter \ $cross_arg \ "$PWD" "$source_path" diff --git a/hw/usb/meson.build b/hw/usb/meson.build index 3ca6127937..de853d780d 100644 --- a/hw/usb/meson.build +++ b/hw/usb/meson.build @@ -72,7 +72,7 @@ if usbredir.found() endif # usb pass-through -if config_host.has_key('CONFIG_USB_LIBUSB') +if libusb.found() usbhost_ss = ss.source_set() usbhost_ss.add(when: ['CONFIG_USB', libusb], if_true: files('host-libusb.c')) diff --git a/meson.build b/meson.build index 2f377098d7..df5094e563 100644 --- a/meson.build +++ b/meson.build @@ -930,7 +930,7 @@ vnc = not_found png = not_found jpeg = not_found sasl = not_found -if get_option('vnc').enabled() +if not get_option('vnc').disabled() vnc = declare_dependency() # dummy dependency png = dependency('libpng', required: get_option('vnc_png'), method: 'pkg-config', kwargs: static_kwargs) @@ -2335,9 +2335,9 @@ foreach d, list : modules # https://github.com/mesonbuild/meson/pull/8900 modinfo_files += custom_target(d + '-' + m + '.modinfo', output: d + '-' + m + '.modinfo', - input: module_ss.sources(), + input: module_ss.sources() + genh, capture: true, - command: [modinfo_collect, '@INPUT@']) + command: [modinfo_collect, module_ss.sources()]) endif else if d == 'block' diff --git a/softmmu/vl.c b/softmmu/vl.c index 4df1496101..f4d8630fc6 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2126,6 +2126,7 @@ static void qemu_create_machine(QDict *qdict) QDict *default_opts = keyval_parse(machine_class->default_machine_opts, NULL, NULL, &error_abort); + qemu_apply_legacy_machine_options(default_opts); object_set_properties_from_keyval(OBJECT(current_machine), default_opts, false, &error_abort); qobject_unref(default_opts); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 5d98a4e7c0..6c50d3ab4f 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -240,6 +240,7 @@ typedef enum X86Seg { #define CR4_OSFXSR_SHIFT 9 #define CR4_OSFXSR_MASK (1U << CR4_OSFXSR_SHIFT) #define CR4_OSXMMEXCPT_MASK (1U << 10) +#define CR4_UMIP_MASK (1U << 11) #define CR4_LA57_MASK (1U << 12) #define CR4_VMXE_MASK (1U << 13) #define CR4_SMXE_MASK (1U << 14) @@ -251,6 +252,14 @@ typedef enum X86Seg { #define CR4_PKE_MASK (1U << 22) #define CR4_PKS_MASK (1U << 24) +#define CR4_RESERVED_MASK \ +(~(target_ulong)(CR4_VME_MASK | CR4_PVI_MASK | CR4_TSD_MASK \ + | CR4_DE_MASK | CR4_PSE_MASK | CR4_PAE_MASK \ + | CR4_MCE_MASK | CR4_PGE_MASK | CR4_PCE_MASK \ + | CR4_OSFXSR_MASK | CR4_OSXMMEXCPT_MASK |CR4_UMIP_MASK \ + | CR4_FSGSBASE_MASK | CR4_PCIDE_MASK | CR4_OSXSAVE_MASK \ + | CR4_SMEP_MASK | CR4_SMAP_MASK | CR4_PKE_MASK | CR4_PKS_MASK)) + #define DR6_BD (1 << 13) #define DR6_BS (1 << 14) #define DR6_BT (1 << 15) @@ -466,6 +475,11 @@ typedef enum X86Seg { #define MSR_EFER_SVME (1 << 12) #define MSR_EFER_FFXSR (1 << 14) +#define MSR_EFER_RESERVED\ + (~(target_ulong)(MSR_EFER_SCE | MSR_EFER_LME\ + | MSR_EFER_LMA | MSR_EFER_NXE | MSR_EFER_SVME\ + | MSR_EFER_FFXSR)) + #define MSR_STAR 0xc0000081 #define MSR_LSTAR 0xc0000082 #define MSR_CSTAR 0xc0000083 @@ -2196,6 +2210,36 @@ static inline bool hyperv_feat_enabled(X86CPU *cpu, int feat) return !!(cpu->hyperv_features & BIT(feat)); } +static inline uint64_t cr4_reserved_bits(CPUX86State *env) +{ + uint64_t reserved_bits = CR4_RESERVED_MASK; + if (!env->features[FEAT_XSAVE]) { + reserved_bits |= CR4_OSXSAVE_MASK; + } + if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMEP)) { + reserved_bits |= CR4_SMEP_MASK; + } + if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) { + reserved_bits |= CR4_SMAP_MASK; + } + if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_FSGSBASE)) { + reserved_bits |= CR4_FSGSBASE_MASK; + } + if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKU)) { + reserved_bits |= CR4_PKE_MASK; + } + if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_LA57)) { + reserved_bits |= CR4_LA57_MASK; + } + if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_UMIP)) { + reserved_bits |= CR4_UMIP_MASK; + } + if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_PKS)) { + reserved_bits |= CR4_PKS_MASK; + } + return reserved_bits; +} + #if defined(TARGET_X86_64) && \ defined(CONFIG_USER_ONLY) && \ defined(CONFIG_LINUX) diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c index db0d8a9d79..a2af2c9bba 100644 --- a/target/i386/tcg/sysemu/misc_helper.c +++ b/target/i386/tcg/sysemu/misc_helper.c @@ -99,6 +99,9 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) cpu_x86_update_cr3(env, t0); break; case 4: + if (t0 & cr4_reserved_bits(env)) { + cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC()); + } if (((t0 ^ env->cr[4]) & CR4_LA57_MASK) && (env->hflags & HF_CS64_MASK)) { raise_exception_ra(env, EXCP0D_GPF, GETPC()); diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c index 00618cff23..4d64ec378e 100644 --- a/target/i386/tcg/sysemu/svm_helper.c +++ b/target/i386/tcg/sysemu/svm_helper.c @@ -65,6 +65,51 @@ static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr, sc->base, sc->limit, sc->flags); } +static inline bool ctl_has_irq(uint32_t int_ctl) +{ + uint32_t int_prio; + uint32_t tpr; + + int_prio = (int_ctl & V_INTR_PRIO_MASK) >> V_INTR_MASKING_SHIFT; + tpr = int_ctl & V_TPR_MASK; + return (int_ctl & V_IRQ_MASK) && (int_prio >= tpr); +} + +static inline bool is_efer_invalid_state (CPUX86State *env) +{ + if (!(env->efer & MSR_EFER_SVME)) { + return true; + } + + if (env->efer & MSR_EFER_RESERVED) { + return true; + } + + if ((env->efer & (MSR_EFER_LMA | MSR_EFER_LME)) && + !(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { + return true; + } + + if ((env->efer & MSR_EFER_LME) && (env->cr[0] & CR0_PG_MASK) + && !(env->cr[4] & CR4_PAE_MASK)) { + return true; + } + + if ((env->efer & MSR_EFER_LME) && (env->cr[0] & CR0_PG_MASK) + && !(env->cr[0] & CR0_PE_MASK)) { + return true; + } + + if ((env->efer & MSR_EFER_LME) && (env->cr[0] & CR0_PG_MASK) + && (env->cr[4] & CR4_PAE_MASK) + && (env->segs[R_CS].flags & DESC_L_MASK) + && (env->segs[R_CS].flags & DESC_B_MASK)) { + return true; + } + + return false; +} + void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) { CPUState *cs = env_cpu(env); @@ -75,6 +120,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) uint32_t int_ctl; uint32_t asid; uint64_t new_cr0; + uint64_t new_cr4; cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC()); @@ -215,14 +261,16 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) if ((new_cr0 & CR0_NW_MASK) && !(new_cr0 & CR0_CD_MASK)) { cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC()); } + new_cr4 = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr4)); + if (new_cr4 & cr4_reserved_bits(env)) { + cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC()); + } /* clear exit_info_2 so we behave like the real hardware */ x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0); cpu_x86_update_cr0(env, new_cr0); - cpu_x86_update_cr4(env, x86_ldq_phys(cs, - env->vm_vmcb + offsetof(struct vmcb, - save.cr4))); + cpu_x86_update_cr4(env, new_cr4); cpu_x86_update_cr3(env, x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, save.cr3))); @@ -278,6 +326,10 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) } #endif + if (is_efer_invalid_state(env)) { + cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC()); + } + switch (x86_ldub_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) { case TLB_CONTROL_DO_NOTHING: @@ -290,7 +342,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) env->hflags2 |= HF2_GIF_MASK; - if (int_ctl & V_IRQ_MASK) { + if (ctl_has_irq(int_ctl)) { CPUState *cs = env_cpu(env); cs->interrupt_request |= CPU_INTERRUPT_VIRQ; diff --git a/util/qemu-config.c b/util/qemu-config.c index 84ee6dc4ea..436ab63b16 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -255,8 +255,6 @@ CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, info->option = g_strdup(vm_config_groups[i]->name); if (!strcmp("drive", vm_config_groups[i]->name)) { info->parameters = get_drive_infolist(); - } else if (!strcmp("machine", vm_config_groups[i]->name)) { - info->parameters = query_option_descs(machine_opts.desc); } else { info->parameters = query_option_descs(vm_config_groups[i]->desc); @@ -265,6 +263,13 @@ CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, } } + if (!has_option || !strcmp(option, "machine")) { + info = g_malloc0(sizeof(*info)); + info->option = g_strdup("machine"); + info->parameters = query_option_descs(machine_opts.desc); + QAPI_LIST_PREPEND(conf_list, info); + } + if (conf_list == NULL) { error_setg(errp, "invalid option name: %s", option); } @@ -414,15 +419,16 @@ static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque, if (ferror(fp)) { loc_pop(&loc); error_setg_errno(errp, errno, "Cannot read config file"); - return res; + goto out_no_loc; } res = count; -out: if (qdict) { cb(group, qdict, opaque, errp); - qobject_unref(qdict); } +out: loc_pop(&loc); +out_no_loc: + qobject_unref(qdict); return res; }