Revision 0c31b744
b/target-i386/kvm.c | ||
---|---|---|
92 | 92 |
return cpuid; |
93 | 93 |
} |
94 | 94 |
|
95 |
#ifdef CONFIG_KVM_PARA |
|
96 |
struct kvm_para_features { |
|
97 |
int cap; |
|
98 |
int feature; |
|
99 |
} para_features[] = { |
|
100 |
{ KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE }, |
|
101 |
{ KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, |
|
102 |
{ KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, |
|
103 |
#ifdef KVM_CAP_ASYNC_PF |
|
104 |
{ KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF }, |
|
105 |
#endif |
|
106 |
{ -1, -1 } |
|
107 |
}; |
|
108 |
|
|
109 |
static int get_para_features(CPUState *env) |
|
110 |
{ |
|
111 |
int i, features = 0; |
|
112 |
|
|
113 |
for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) { |
|
114 |
if (kvm_check_extension(env->kvm_state, para_features[i].cap)) { |
|
115 |
features |= (1 << para_features[i].feature); |
|
116 |
} |
|
117 |
} |
|
118 |
|
|
119 |
return features; |
|
120 |
} |
|
121 |
#endif |
|
122 |
|
|
123 |
|
|
95 | 124 |
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, |
96 | 125 |
uint32_t index, int reg) |
97 | 126 |
{ |
... | ... | |
99 | 128 |
int i, max; |
100 | 129 |
uint32_t ret = 0; |
101 | 130 |
uint32_t cpuid_1_edx; |
131 |
#ifdef CONFIG_KVM_PARA |
|
132 |
int has_kvm_features = 0; |
|
133 |
#endif |
|
102 | 134 |
|
103 | 135 |
max = 1; |
104 | 136 |
while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) { |
... | ... | |
108 | 140 |
for (i = 0; i < cpuid->nent; ++i) { |
109 | 141 |
if (cpuid->entries[i].function == function && |
110 | 142 |
cpuid->entries[i].index == index) { |
143 |
#ifdef CONFIG_KVM_PARA |
|
144 |
if (cpuid->entries[i].function == KVM_CPUID_FEATURES) { |
|
145 |
has_kvm_features = 1; |
|
146 |
} |
|
147 |
#endif |
|
111 | 148 |
switch (reg) { |
112 | 149 |
case R_EAX: |
113 | 150 |
ret = cpuid->entries[i].eax; |
... | ... | |
140 | 177 |
|
141 | 178 |
qemu_free(cpuid); |
142 | 179 |
|
143 |
return ret; |
|
144 |
} |
|
145 |
|
|
146 | 180 |
#ifdef CONFIG_KVM_PARA |
147 |
struct kvm_para_features { |
|
148 |
int cap; |
|
149 |
int feature; |
|
150 |
} para_features[] = { |
|
151 |
{ KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE }, |
|
152 |
{ KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, |
|
153 |
{ KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, |
|
154 |
#ifdef KVM_CAP_ASYNC_PF |
|
155 |
{ KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF }, |
|
156 |
#endif |
|
157 |
{ -1, -1 } |
|
158 |
}; |
|
159 |
|
|
160 |
static int get_para_features(CPUState *env) |
|
161 |
{ |
|
162 |
int i, features = 0; |
|
163 |
|
|
164 |
for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) { |
|
165 |
if (kvm_check_extension(env->kvm_state, para_features[i].cap)) { |
|
166 |
features |= (1 << para_features[i].feature); |
|
167 |
} |
|
181 |
/* fallback for older kernels */ |
|
182 |
if (!has_kvm_features && (function == KVM_CPUID_FEATURES)) { |
|
183 |
ret = get_para_features(env); |
|
168 | 184 |
} |
169 |
#ifdef KVM_CAP_ASYNC_PF |
|
170 |
has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF); |
|
171 | 185 |
#endif |
172 |
return features; |
|
186 |
|
|
187 |
return ret; |
|
173 | 188 |
} |
174 |
#endif /* CONFIG_KVM_PARA */ |
|
175 | 189 |
|
176 | 190 |
typedef struct HWPoisonPage { |
177 | 191 |
ram_addr_t ram_addr; |
... | ... | |
397 | 411 |
c = &cpuid_data.entries[cpuid_i++]; |
398 | 412 |
memset(c, 0, sizeof(*c)); |
399 | 413 |
c->function = KVM_CPUID_FEATURES; |
400 |
c->eax = env->cpuid_kvm_features & get_para_features(env); |
|
414 |
c->eax = env->cpuid_kvm_features & kvm_arch_get_supported_cpuid(env, |
|
415 |
KVM_CPUID_FEATURES, 0, R_EAX); |
|
416 |
|
|
417 |
#ifdef KVM_CAP_ASYNC_PF |
|
418 |
has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF); |
|
419 |
#endif |
|
420 |
|
|
401 | 421 |
#endif |
402 | 422 |
|
403 | 423 |
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused); |
Also available in: Unified diff