Revision e7701825 target-i386/kvm.c

b/target-i386/kvm.c
27 27
#include "hw/pc.h"
28 28
#include "hw/apic.h"
29 29
#include "ioport.h"
30
#include "kvm_x86.h"
30 31

  
31 32
#ifdef CONFIG_KVM_PARA
32 33
#include <linux/kvm_para.h>
......
167 168
}
168 169
#endif
169 170

  
171
#ifdef KVM_CAP_MCE
172
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
173
                                     int *max_banks)
174
{
175
    int r;
176

  
177
    r = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_MCE);
178
    if (r > 0) {
179
        *max_banks = r;
180
        return kvm_ioctl(s, KVM_X86_GET_MCE_CAP_SUPPORTED, mce_cap);
181
    }
182
    return -ENOSYS;
183
}
184

  
185
static int kvm_setup_mce(CPUState *env, uint64_t *mcg_cap)
186
{
187
    return kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, mcg_cap);
188
}
189

  
190
static int kvm_set_mce(CPUState *env, struct kvm_x86_mce *m)
191
{
192
    return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, m);
193
}
194

  
195
struct kvm_x86_mce_data
196
{
197
    CPUState *env;
198
    struct kvm_x86_mce *mce;
199
};
200

  
201
static void kvm_do_inject_x86_mce(void *_data)
202
{
203
    struct kvm_x86_mce_data *data = _data;
204
    int r;
205

  
206
    r = kvm_set_mce(data->env, data->mce);
207
    if (r < 0)
208
        perror("kvm_set_mce FAILED");
209
}
210
#endif
211

  
212
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
213
                        uint64_t mcg_status, uint64_t addr, uint64_t misc)
214
{
215
#ifdef KVM_CAP_MCE
216
    struct kvm_x86_mce mce = {
217
        .bank = bank,
218
        .status = status,
219
        .mcg_status = mcg_status,
220
        .addr = addr,
221
        .misc = misc,
222
    };
223
    struct kvm_x86_mce_data data = {
224
            .env = cenv,
225
            .mce = &mce,
226
    };
227

  
228
    run_on_cpu(cenv, kvm_do_inject_x86_mce, &data);
229
#endif
230
}
231

  
170 232
int kvm_arch_init_vcpu(CPUState *env)
171 233
{
172 234
    struct {
......
277 339

  
278 340
    cpuid_data.cpuid.nent = cpuid_i;
279 341

  
342
#ifdef KVM_CAP_MCE
343
    if (((env->cpuid_version >> 8)&0xF) >= 6
344
        && (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)
345
        && kvm_check_extension(env->kvm_state, KVM_CAP_MCE) > 0) {
346
        uint64_t mcg_cap;
347
        int banks;
348

  
349
        if (kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks))
350
            perror("kvm_get_mce_cap_supported FAILED");
351
        else {
352
            if (banks > MCE_BANKS_DEF)
353
                banks = MCE_BANKS_DEF;
354
            mcg_cap &= MCE_CAP_DEF;
355
            mcg_cap |= banks;
356
            if (kvm_setup_mce(env, &mcg_cap))
357
                perror("kvm_setup_mce FAILED");
358
            else
359
                env->mcg_cap = mcg_cap;
360
        }
361
    }
362
#endif
363

  
280 364
    return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
281 365
}
282 366

  

Also available in: Unified diff