1*f5cc5a5cSClaudio Fontana /* 2*f5cc5a5cSClaudio Fontana * x86 KVM CPU type initialization 3*f5cc5a5cSClaudio Fontana * 4*f5cc5a5cSClaudio Fontana * Copyright 2021 SUSE LLC 5*f5cc5a5cSClaudio Fontana * 6*f5cc5a5cSClaudio Fontana * This work is licensed under the terms of the GNU GPL, version 2 or later. 7*f5cc5a5cSClaudio Fontana * See the COPYING file in the top-level directory. 8*f5cc5a5cSClaudio Fontana */ 9*f5cc5a5cSClaudio Fontana 10*f5cc5a5cSClaudio Fontana #include "qemu/osdep.h" 11*f5cc5a5cSClaudio Fontana #include "cpu.h" 12*f5cc5a5cSClaudio Fontana #include "host-cpu.h" 13*f5cc5a5cSClaudio Fontana #include "kvm-cpu.h" 14*f5cc5a5cSClaudio Fontana #include "qapi/error.h" 15*f5cc5a5cSClaudio Fontana #include "sysemu/sysemu.h" 16*f5cc5a5cSClaudio Fontana #include "hw/boards.h" 17*f5cc5a5cSClaudio Fontana 18*f5cc5a5cSClaudio Fontana #include "kvm_i386.h" 19*f5cc5a5cSClaudio Fontana #include "hw/core/accel-cpu.h" 20*f5cc5a5cSClaudio Fontana 21*f5cc5a5cSClaudio Fontana static void kvm_cpu_realizefn(CPUState *cs, Error **errp) 22*f5cc5a5cSClaudio Fontana { 23*f5cc5a5cSClaudio Fontana X86CPU *cpu = X86_CPU(cs); 24*f5cc5a5cSClaudio Fontana CPUX86State *env = &cpu->env; 25*f5cc5a5cSClaudio Fontana 26*f5cc5a5cSClaudio Fontana /* 27*f5cc5a5cSClaudio Fontana * The realize order is important, since x86_cpu_realize() checks if 28*f5cc5a5cSClaudio Fontana * nothing else has been set by the user (or by accelerators) in 29*f5cc5a5cSClaudio Fontana * cpu->ucode_rev and cpu->phys_bits. 30*f5cc5a5cSClaudio Fontana * 31*f5cc5a5cSClaudio Fontana * realize order: 32*f5cc5a5cSClaudio Fontana * kvm_cpu -> host_cpu -> x86_cpu 33*f5cc5a5cSClaudio Fontana */ 34*f5cc5a5cSClaudio Fontana if (cpu->max_features) { 35*f5cc5a5cSClaudio Fontana if (enable_cpu_pm && kvm_has_waitpkg()) { 36*f5cc5a5cSClaudio Fontana env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG; 37*f5cc5a5cSClaudio Fontana } 38*f5cc5a5cSClaudio Fontana if (cpu->ucode_rev == 0) { 39*f5cc5a5cSClaudio Fontana cpu->ucode_rev = 40*f5cc5a5cSClaudio Fontana kvm_arch_get_supported_msr_feature(kvm_state, 41*f5cc5a5cSClaudio Fontana MSR_IA32_UCODE_REV); 42*f5cc5a5cSClaudio Fontana } 43*f5cc5a5cSClaudio Fontana } 44*f5cc5a5cSClaudio Fontana host_cpu_realizefn(cs, errp); 45*f5cc5a5cSClaudio Fontana } 46*f5cc5a5cSClaudio Fontana 47*f5cc5a5cSClaudio Fontana /* 48*f5cc5a5cSClaudio Fontana * KVM-specific features that are automatically added/removed 49*f5cc5a5cSClaudio Fontana * from all CPU models when KVM is enabled. 50*f5cc5a5cSClaudio Fontana */ 51*f5cc5a5cSClaudio Fontana static PropValue kvm_default_props[] = { 52*f5cc5a5cSClaudio Fontana { "kvmclock", "on" }, 53*f5cc5a5cSClaudio Fontana { "kvm-nopiodelay", "on" }, 54*f5cc5a5cSClaudio Fontana { "kvm-asyncpf", "on" }, 55*f5cc5a5cSClaudio Fontana { "kvm-steal-time", "on" }, 56*f5cc5a5cSClaudio Fontana { "kvm-pv-eoi", "on" }, 57*f5cc5a5cSClaudio Fontana { "kvmclock-stable-bit", "on" }, 58*f5cc5a5cSClaudio Fontana { "x2apic", "on" }, 59*f5cc5a5cSClaudio Fontana { "kvm-msi-ext-dest-id", "off" }, 60*f5cc5a5cSClaudio Fontana { "acpi", "off" }, 61*f5cc5a5cSClaudio Fontana { "monitor", "off" }, 62*f5cc5a5cSClaudio Fontana { "svm", "off" }, 63*f5cc5a5cSClaudio Fontana { NULL, NULL }, 64*f5cc5a5cSClaudio Fontana }; 65*f5cc5a5cSClaudio Fontana 66*f5cc5a5cSClaudio Fontana void x86_cpu_change_kvm_default(const char *prop, const char *value) 67*f5cc5a5cSClaudio Fontana { 68*f5cc5a5cSClaudio Fontana PropValue *pv; 69*f5cc5a5cSClaudio Fontana for (pv = kvm_default_props; pv->prop; pv++) { 70*f5cc5a5cSClaudio Fontana if (!strcmp(pv->prop, prop)) { 71*f5cc5a5cSClaudio Fontana pv->value = value; 72*f5cc5a5cSClaudio Fontana break; 73*f5cc5a5cSClaudio Fontana } 74*f5cc5a5cSClaudio Fontana } 75*f5cc5a5cSClaudio Fontana 76*f5cc5a5cSClaudio Fontana /* 77*f5cc5a5cSClaudio Fontana * It is valid to call this function only for properties that 78*f5cc5a5cSClaudio Fontana * are already present in the kvm_default_props table. 79*f5cc5a5cSClaudio Fontana */ 80*f5cc5a5cSClaudio Fontana assert(pv->prop); 81*f5cc5a5cSClaudio Fontana } 82*f5cc5a5cSClaudio Fontana 83*f5cc5a5cSClaudio Fontana static bool lmce_supported(void) 84*f5cc5a5cSClaudio Fontana { 85*f5cc5a5cSClaudio Fontana uint64_t mce_cap = 0; 86*f5cc5a5cSClaudio Fontana 87*f5cc5a5cSClaudio Fontana if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) { 88*f5cc5a5cSClaudio Fontana return false; 89*f5cc5a5cSClaudio Fontana } 90*f5cc5a5cSClaudio Fontana return !!(mce_cap & MCG_LMCE_P); 91*f5cc5a5cSClaudio Fontana } 92*f5cc5a5cSClaudio Fontana 93*f5cc5a5cSClaudio Fontana static void kvm_cpu_max_instance_init(X86CPU *cpu) 94*f5cc5a5cSClaudio Fontana { 95*f5cc5a5cSClaudio Fontana CPUX86State *env = &cpu->env; 96*f5cc5a5cSClaudio Fontana KVMState *s = kvm_state; 97*f5cc5a5cSClaudio Fontana 98*f5cc5a5cSClaudio Fontana host_cpu_max_instance_init(cpu); 99*f5cc5a5cSClaudio Fontana 100*f5cc5a5cSClaudio Fontana if (lmce_supported()) { 101*f5cc5a5cSClaudio Fontana object_property_set_bool(OBJECT(cpu), "lmce", true, &error_abort); 102*f5cc5a5cSClaudio Fontana } 103*f5cc5a5cSClaudio Fontana 104*f5cc5a5cSClaudio Fontana env->cpuid_min_level = 105*f5cc5a5cSClaudio Fontana kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); 106*f5cc5a5cSClaudio Fontana env->cpuid_min_xlevel = 107*f5cc5a5cSClaudio Fontana kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); 108*f5cc5a5cSClaudio Fontana env->cpuid_min_xlevel2 = 109*f5cc5a5cSClaudio Fontana kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); 110*f5cc5a5cSClaudio Fontana } 111*f5cc5a5cSClaudio Fontana 112*f5cc5a5cSClaudio Fontana static void kvm_cpu_instance_init(CPUState *cs) 113*f5cc5a5cSClaudio Fontana { 114*f5cc5a5cSClaudio Fontana X86CPU *cpu = X86_CPU(cs); 115*f5cc5a5cSClaudio Fontana 116*f5cc5a5cSClaudio Fontana host_cpu_instance_init(cpu); 117*f5cc5a5cSClaudio Fontana 118*f5cc5a5cSClaudio Fontana if (!kvm_irqchip_in_kernel()) { 119*f5cc5a5cSClaudio Fontana x86_cpu_change_kvm_default("x2apic", "off"); 120*f5cc5a5cSClaudio Fontana } else if (kvm_irqchip_is_split() && kvm_enable_x2apic()) { 121*f5cc5a5cSClaudio Fontana x86_cpu_change_kvm_default("kvm-msi-ext-dest-id", "on"); 122*f5cc5a5cSClaudio Fontana } 123*f5cc5a5cSClaudio Fontana 124*f5cc5a5cSClaudio Fontana /* Special cases not set in the X86CPUDefinition structs: */ 125*f5cc5a5cSClaudio Fontana 126*f5cc5a5cSClaudio Fontana x86_cpu_apply_props(cpu, kvm_default_props); 127*f5cc5a5cSClaudio Fontana 128*f5cc5a5cSClaudio Fontana if (cpu->max_features) { 129*f5cc5a5cSClaudio Fontana kvm_cpu_max_instance_init(cpu); 130*f5cc5a5cSClaudio Fontana } 131*f5cc5a5cSClaudio Fontana } 132*f5cc5a5cSClaudio Fontana 133*f5cc5a5cSClaudio Fontana static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) 134*f5cc5a5cSClaudio Fontana { 135*f5cc5a5cSClaudio Fontana AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); 136*f5cc5a5cSClaudio Fontana 137*f5cc5a5cSClaudio Fontana acc->cpu_realizefn = kvm_cpu_realizefn; 138*f5cc5a5cSClaudio Fontana acc->cpu_instance_init = kvm_cpu_instance_init; 139*f5cc5a5cSClaudio Fontana } 140*f5cc5a5cSClaudio Fontana static const TypeInfo kvm_cpu_accel_type_info = { 141*f5cc5a5cSClaudio Fontana .name = ACCEL_CPU_NAME("kvm"), 142*f5cc5a5cSClaudio Fontana 143*f5cc5a5cSClaudio Fontana .parent = TYPE_ACCEL_CPU, 144*f5cc5a5cSClaudio Fontana .class_init = kvm_cpu_accel_class_init, 145*f5cc5a5cSClaudio Fontana .abstract = true, 146*f5cc5a5cSClaudio Fontana }; 147*f5cc5a5cSClaudio Fontana static void kvm_cpu_accel_register_types(void) 148*f5cc5a5cSClaudio Fontana { 149*f5cc5a5cSClaudio Fontana type_register_static(&kvm_cpu_accel_type_info); 150*f5cc5a5cSClaudio Fontana } 151*f5cc5a5cSClaudio Fontana type_init(kvm_cpu_accel_register_types); 152