Commit a16fc07e authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

cpus: reorganize signal handling code



Move the KVM "eat signals" code under CONFIG_LINUX, in preparation
for moving it to kvm-all.c; reraise non-MCE SIGBUS immediately,
without passing it to KVM.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 20e0ff59
Loading
Loading
Loading
Loading
+32 −31
Original line number Diff line number Diff line
@@ -922,6 +922,10 @@ static void sigbus_reraise(void)

static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx)
{
    if (siginfo->si_code != BUS_MCEERR_AO && siginfo->si_code != BUS_MCEERR_AR) {
        sigbus_reraise();
    }

    if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) {
        sigbus_reraise();
    }
@@ -939,6 +943,30 @@ static void qemu_init_sigbus(void)
    prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
}

static void dummy_signal(int sig)
{
}

static void qemu_kvm_init_cpu_signals(CPUState *cpu)
{
    int r;
    sigset_t set;
    struct sigaction sigact;

    memset(&sigact, 0, sizeof(sigact));
    sigact.sa_handler = dummy_signal;
    sigaction(SIG_IPI, &sigact, NULL);

    pthread_sigmask(SIG_BLOCK, NULL, &set);
    sigdelset(&set, SIG_IPI);
    sigdelset(&set, SIGBUS);
    r = kvm_set_signal_mask(cpu, &set);
    if (r) {
        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
        exit(1);
    }
}

static void qemu_kvm_eat_signals(CPUState *cpu)
{
    struct timespec ts = { 0, 0 };
@@ -960,6 +988,9 @@ static void qemu_kvm_eat_signals(CPUState *cpu)

        switch (r) {
        case SIGBUS:
            if (siginfo.si_code != BUS_MCEERR_AO && siginfo.si_code != BUS_MCEERR_AR) {
                sigbus_reraise();
            }
            if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) {
                sigbus_reraise();
            }
@@ -975,9 +1006,7 @@ static void qemu_kvm_eat_signals(CPUState *cpu)
        }
    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
}

#else /* !CONFIG_LINUX */

static void qemu_init_sigbus(void)
{
}
@@ -985,39 +1014,11 @@ static void qemu_init_sigbus(void)
static void qemu_kvm_eat_signals(CPUState *cpu)
{
}
#endif /* !CONFIG_LINUX */

#ifndef _WIN32
static void dummy_signal(int sig)
{
}

static void qemu_kvm_init_cpu_signals(CPUState *cpu)
{
    int r;
    sigset_t set;
    struct sigaction sigact;

    memset(&sigact, 0, sizeof(sigact));
    sigact.sa_handler = dummy_signal;
    sigaction(SIG_IPI, &sigact, NULL);

    pthread_sigmask(SIG_BLOCK, NULL, &set);
    sigdelset(&set, SIG_IPI);
    sigdelset(&set, SIGBUS);
    r = kvm_set_signal_mask(cpu, &set);
    if (r) {
        fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
        exit(1);
    }
}

#else /* _WIN32 */
static void qemu_kvm_init_cpu_signals(CPUState *cpu)
{
    abort();
}
#endif /* _WIN32 */
#endif /* !CONFIG_LINUX */

static QemuMutex qemu_global_mutex;

+9 −0
Original line number Diff line number Diff line
@@ -284,6 +284,15 @@ void qemu_anon_ram_free(void *ptr, size_t size);

#endif

#if defined(CONFIG_LINUX)
#ifndef BUS_MCEERR_AR
#define BUS_MCEERR_AR 4
#endif
#ifndef BUS_MCEERR_AO
#define BUS_MCEERR_AO 5
#endif
#endif

#if defined(__linux__) && \
    (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__))
   /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
+2 −13
Original line number Diff line number Diff line
@@ -64,13 +64,6 @@
 * 255 kvm_msr_entry structs */
#define MSR_BUF_SIZE 4096

#ifndef BUS_MCEERR_AR
#define BUS_MCEERR_AR 4
#endif
#ifndef BUS_MCEERR_AO
#define BUS_MCEERR_AO 5
#endif

const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
    KVM_CAP_INFO(SET_TSS_ADDR),
    KVM_CAP_INFO(EXT_CPUID),
@@ -469,9 +462,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
    ram_addr_t ram_addr;
    hwaddr paddr;

    if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) {
        return 1;
    }
    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);

    /* Because the MCE happened while running the VCPU, KVM could have
     * injected action required MCEs too.  Action optional MCEs should
@@ -504,9 +495,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
{
    X86CPU *cpu = X86_CPU(first_cpu);

    if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) {
        return 1;
    }
    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);

    if (code == BUS_MCEERR_AR) {
        hardware_memory_error();