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