Revision 419fb20a target-i386/kvm.c

b/target-i386/kvm.c
172 172
#endif
173 173
    return features;
174 174
}
175
#endif
175
#endif /* CONFIG_KVM_PARA */
176 176

  
177 177
#ifdef KVM_CAP_MCE
178 178
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
......
273 273
    run_on_cpu(env, kvm_do_inject_x86_mce, &data);
274 274
}
275 275

  
276
static void kvm_mce_broadcast_rest(CPUState *env);
277
#endif
276
static void kvm_mce_broadcast_rest(CPUState *env)
277
{
278
    struct kvm_x86_mce mce = {
279
        .bank = 1,
280
        .status = MCI_STATUS_VAL | MCI_STATUS_UC,
281
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
282
        .addr = 0,
283
        .misc = 0,
284
    };
285
    CPUState *cenv;
286

  
287
    /* Broadcast MCA signal for processor version 06H_EH and above */
288
    if (cpu_x86_support_mca_broadcast(env)) {
289
        for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
290
            if (cenv == env) {
291
                continue;
292
            }
293
            kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
294
        }
295
    }
296
}
297

  
298
static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
299
{
300
    struct kvm_x86_mce mce = {
301
        .bank = 9,
302
        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
303
                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
304
                  | MCI_STATUS_AR | 0x134,
305
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
306
        .addr = paddr,
307
        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
308
    };
309
    int r;
310

  
311
    r = kvm_set_mce(env, &mce);
312
    if (r < 0) {
313
        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
314
        abort();
315
    }
316
    kvm_mce_broadcast_rest(env);
317
}
318

  
319
static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
320
{
321
    struct kvm_x86_mce mce = {
322
        .bank = 9,
323
        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
324
                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
325
                  | 0xc0,
326
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
327
        .addr = paddr,
328
        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
329
    };
330
    int r;
331

  
332
    r = kvm_set_mce(env, &mce);
333
    if (r < 0) {
334
        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
335
        abort();
336
    }
337
    kvm_mce_broadcast_rest(env);
338
}
339

  
340
static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
341
{
342
    struct kvm_x86_mce mce = {
343
        .bank = 9,
344
        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
345
                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
346
                  | 0xc0,
347
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
348
        .addr = paddr,
349
        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
350
    };
351

  
352
    kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
353
    kvm_mce_broadcast_rest(env);
354
}
355
#endif /* KVM_CAP_MCE */
356

  
357
static void hardware_memory_error(void)
358
{
359
    fprintf(stderr, "Hardware memory error!\n");
360
    exit(1);
361
}
362

  
363
int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
364
{
365
#ifdef KVM_CAP_MCE
366
    void *vaddr;
367
    ram_addr_t ram_addr;
368
    target_phys_addr_t paddr;
369

  
370
    if ((env->mcg_cap & MCG_SER_P) && addr
371
        && (code == BUS_MCEERR_AR
372
            || code == BUS_MCEERR_AO)) {
373
        vaddr = (void *)addr;
374
        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
375
            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
376
            fprintf(stderr, "Hardware memory error for memory used by "
377
                    "QEMU itself instead of guest system!\n");
378
            /* Hope we are lucky for AO MCE */
379
            if (code == BUS_MCEERR_AO) {
380
                return 0;
381
            } else {
382
                hardware_memory_error();
383
            }
384
        }
385

  
386
        if (code == BUS_MCEERR_AR) {
387
            /* Fake an Intel architectural Data Load SRAR UCR */
388
            kvm_mce_inj_srar_dataload(env, paddr);
389
        } else {
390
            /*
391
             * If there is an MCE excpetion being processed, ignore
392
             * this SRAO MCE
393
             */
394
            if (!kvm_mce_in_progress(env)) {
395
                /* Fake an Intel architectural Memory scrubbing UCR */
396
                kvm_mce_inj_srao_memscrub(env, paddr);
397
            }
398
        }
399
    } else
400
#endif /* KVM_CAP_MCE */
401
    {
402
        if (code == BUS_MCEERR_AO) {
403
            return 0;
404
        } else if (code == BUS_MCEERR_AR) {
405
            hardware_memory_error();
406
        } else {
407
            return 1;
408
        }
409
    }
410
    return 0;
411
}
412

  
413
int kvm_arch_on_sigbus(int code, void *addr)
414
{
415
#ifdef KVM_CAP_MCE
416
    if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
417
        void *vaddr;
418
        ram_addr_t ram_addr;
419
        target_phys_addr_t paddr;
420

  
421
        /* Hope we are lucky for AO MCE */
422
        vaddr = addr;
423
        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
424
            !kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr,
425
                                               &paddr)) {
426
            fprintf(stderr, "Hardware memory error for memory used by "
427
                    "QEMU itself instead of guest system!: %p\n", addr);
428
            return 0;
429
        }
430
        kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
431
    } else
432
#endif /* KVM_CAP_MCE */
433
    {
434
        if (code == BUS_MCEERR_AO) {
435
            return 0;
436
        } else if (code == BUS_MCEERR_AR) {
437
            hardware_memory_error();
438
        } else {
439
            return 1;
440
        }
441
    }
442
    return 0;
443
}
278 444

  
279 445
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
280 446
                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
......
294 460
    }
295 461

  
296 462
    kvm_inject_x86_mce_on(cenv, &mce, flag);
297
#else
463
#else /* !KVM_CAP_MCE*/
298 464
    if (flag & ABORT_ON_ERROR) {
299 465
        abort();
300 466
    }
301
#endif
467
#endif /* !KVM_CAP_MCE*/
302 468
}
303 469

  
304 470
static void cpu_update_state(void *opaque, int running, int reason)
......
1783 1949
    return !(env->cr[0] & CR0_PE_MASK) ||
1784 1950
           ((env->segs[R_CS].selector  & 3) != 3);
1785 1951
}
1786

  
1787
static void hardware_memory_error(void)
1788
{
1789
    fprintf(stderr, "Hardware memory error!\n");
1790
    exit(1);
1791
}
1792

  
1793
#ifdef KVM_CAP_MCE
1794
static void kvm_mce_broadcast_rest(CPUState *env)
1795
{
1796
    struct kvm_x86_mce mce = {
1797
        .bank = 1,
1798
        .status = MCI_STATUS_VAL | MCI_STATUS_UC,
1799
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
1800
        .addr = 0,
1801
        .misc = 0,
1802
    };
1803
    CPUState *cenv;
1804

  
1805
    /* Broadcast MCA signal for processor version 06H_EH and above */
1806
    if (cpu_x86_support_mca_broadcast(env)) {
1807
        for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
1808
            if (cenv == env) {
1809
                continue;
1810
            }
1811
            kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
1812
        }
1813
    }
1814
}
1815

  
1816
static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
1817
{
1818
    struct kvm_x86_mce mce = {
1819
        .bank = 9,
1820
        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
1821
                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
1822
                  | MCI_STATUS_AR | 0x134,
1823
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
1824
        .addr = paddr,
1825
        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
1826
    };
1827
    int r;
1828

  
1829
    r = kvm_set_mce(env, &mce);
1830
    if (r < 0) {
1831
        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
1832
        abort();
1833
    }
1834
    kvm_mce_broadcast_rest(env);
1835
}
1836

  
1837
static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
1838
{
1839
    struct kvm_x86_mce mce = {
1840
        .bank = 9,
1841
        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
1842
                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
1843
                  | 0xc0,
1844
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
1845
        .addr = paddr,
1846
        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
1847
    };
1848
    int r;
1849

  
1850
    r = kvm_set_mce(env, &mce);
1851
    if (r < 0) {
1852
        fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
1853
        abort();
1854
    }
1855
    kvm_mce_broadcast_rest(env);
1856
}
1857

  
1858
static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
1859
{
1860
    struct kvm_x86_mce mce = {
1861
        .bank = 9,
1862
        .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
1863
                  | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
1864
                  | 0xc0,
1865
        .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
1866
        .addr = paddr,
1867
        .misc = (MCM_ADDR_PHYS << 6) | 0xc,
1868
    };
1869

  
1870
    kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
1871
    kvm_mce_broadcast_rest(env);
1872
}
1873

  
1874
#endif
1875

  
1876
int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
1877
{
1878
#if defined(KVM_CAP_MCE)
1879
    void *vaddr;
1880
    ram_addr_t ram_addr;
1881
    target_phys_addr_t paddr;
1882

  
1883
    if ((env->mcg_cap & MCG_SER_P) && addr
1884
        && (code == BUS_MCEERR_AR
1885
            || code == BUS_MCEERR_AO)) {
1886
        vaddr = (void *)addr;
1887
        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
1888
            !kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
1889
            fprintf(stderr, "Hardware memory error for memory used by "
1890
                    "QEMU itself instead of guest system!\n");
1891
            /* Hope we are lucky for AO MCE */
1892
            if (code == BUS_MCEERR_AO) {
1893
                return 0;
1894
            } else {
1895
                hardware_memory_error();
1896
            }
1897
        }
1898

  
1899
        if (code == BUS_MCEERR_AR) {
1900
            /* Fake an Intel architectural Data Load SRAR UCR */
1901
            kvm_mce_inj_srar_dataload(env, paddr);
1902
        } else {
1903
            /*
1904
             * If there is an MCE excpetion being processed, ignore
1905
             * this SRAO MCE
1906
             */
1907
            if (!kvm_mce_in_progress(env)) {
1908
                /* Fake an Intel architectural Memory scrubbing UCR */
1909
                kvm_mce_inj_srao_memscrub(env, paddr);
1910
            }
1911
        }
1912
    } else
1913
#endif
1914
    {
1915
        if (code == BUS_MCEERR_AO) {
1916
            return 0;
1917
        } else if (code == BUS_MCEERR_AR) {
1918
            hardware_memory_error();
1919
        } else {
1920
            return 1;
1921
        }
1922
    }
1923
    return 0;
1924
}
1925

  
1926
int kvm_arch_on_sigbus(int code, void *addr)
1927
{
1928
#if defined(KVM_CAP_MCE)
1929
    if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
1930
        void *vaddr;
1931
        ram_addr_t ram_addr;
1932
        target_phys_addr_t paddr;
1933

  
1934
        /* Hope we are lucky for AO MCE */
1935
        vaddr = addr;
1936
        if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
1937
            !kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr, &paddr)) {
1938
            fprintf(stderr, "Hardware memory error for memory used by "
1939
                    "QEMU itself instead of guest system!: %p\n", addr);
1940
            return 0;
1941
        }
1942
        kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
1943
    } else
1944
#endif
1945
    {
1946
        if (code == BUS_MCEERR_AO) {
1947
            return 0;
1948
        } else if (code == BUS_MCEERR_AR) {
1949
            hardware_memory_error();
1950
        } else {
1951
            return 1;
1952
        }
1953
    }
1954
    return 0;
1955
}

Also available in: Unified diff