(2010/10/05 3:54), Marcelo Tosatti wrote: > Port qemu-kvm's > > commit 4b62fff1101a7ad77553147717a8bd3bf79df7ef > Author: Huang Ying <ying.huang@xxxxxxxxx> > Date: Mon Sep 21 10:43:25 2009 +0800 > > MCE: Relay UCR MCE to guest > > UCR (uncorrected recovery) MCE is supported in recent Intel CPUs, > where some hardware error such as some memory error can be reported > without PCC (processor context corrupted). To recover from such MCE, > the corresponding memory will be unmapped, and all processes accessing > the memory will be killed via SIGBUS. > > For KVM, if QEMU/KVM is killed, all guest processes will be killed > too. So we relay SIGBUS from host OS to guest system via a UCR MCE > injection. Then guest OS can isolate corresponding memory and kill > necessary guest processes only. SIGBUS sent to main thread (not VCPU > threads) will be broadcast to all VCPU threads as UCR MCE. > > Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx> > (snip) > +static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo, > + void *ctx) > +{ > +#if defined(TARGET_I386) > + if (kvm_on_sigbus_vcpu(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr)) > +#endif > + sigbus_reraise(); > +} > + > static void qemu_kvm_eat_signal(CPUState *env, int timeout) > { > struct timespec ts; > int r, e; > siginfo_t siginfo; > sigset_t waitset; > + sigset_t chkset; > > ts.tv_sec = timeout / 1000; > ts.tv_nsec = (timeout % 1000) * 1000000; > > sigemptyset(&waitset); > sigaddset(&waitset, SIG_IPI); > + sigaddset(&waitset, SIGBUS); > > - qemu_mutex_unlock(&qemu_global_mutex); > - r = sigtimedwait(&waitset, &siginfo, &ts); > - e = errno; > - qemu_mutex_lock(&qemu_global_mutex); > + do { > + qemu_mutex_unlock(&qemu_global_mutex); > > - if (r == -1 && !(e == EAGAIN || e == EINTR)) { > - fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); > - exit(1); > - } > + r = sigtimedwait(&waitset, &siginfo, &ts); > + e = errno; > + > + qemu_mutex_lock(&qemu_global_mutex); > + > + if (r == -1 && !(e == EAGAIN || e == EINTR)) { > + fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); > + exit(1); > + } > + > + switch (r) { > + case SIGBUS: > +#ifdef TARGET_I386 > + if (kvm_on_sigbus(env, siginfo.si_code, siginfo.si_addr)) > +#endif > + sigbus_reraise(); > + break; > + default: > + break; > + } > + > + r = sigpending(&chkset); > + if (r == -1) { > + fprintf(stderr, "sigpending: %s\n", strerror(e)); > + exit(1); > + } > + } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); > } > > static void qemu_kvm_wait_io_event(CPUState *env) (snip) > Index: qemu/kvm.h > =================================================================== > --- qemu.orig/kvm.h > +++ qemu/kvm.h > @@ -110,6 +110,9 @@ int kvm_arch_init_vcpu(CPUState *env); > > void kvm_arch_reset_vcpu(CPUState *env); > > +int kvm_on_sigbus(CPUState *env, int code, void *addr); > +int kvm_on_sigbus_vcpu(int code, void *addr); > + > struct kvm_guest_debug; > struct kvm_debug_exit_arch; > So kvm_on_sigbus() is called from qemu_kvm_eat_signal() that is called on vcpu thread, while kvm_on_sigbus_vcpu() is called via sigbus_handler that invoked on iothread using signalfd. ... Inverse naming? Thanks, H.Seto -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html