mirror of https://github.com/xqemu/xqemu.git
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: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
20e0ff59a9
commit
a16fc07ebd
105
cpus.c
105
cpus.c
|
@ -922,6 +922,10 @@ static void sigbus_reraise(void)
|
||||||
|
|
||||||
static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx)
|
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)) {
|
if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) {
|
||||||
sigbus_reraise();
|
sigbus_reraise();
|
||||||
}
|
}
|
||||||
|
@ -939,55 +943,6 @@ static void qemu_init_sigbus(void)
|
||||||
prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
|
prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_kvm_eat_signals(CPUState *cpu)
|
|
||||||
{
|
|
||||||
struct timespec ts = { 0, 0 };
|
|
||||||
siginfo_t siginfo;
|
|
||||||
sigset_t waitset;
|
|
||||||
sigset_t chkset;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
sigemptyset(&waitset);
|
|
||||||
sigaddset(&waitset, SIG_IPI);
|
|
||||||
sigaddset(&waitset, SIGBUS);
|
|
||||||
|
|
||||||
do {
|
|
||||||
r = sigtimedwait(&waitset, &siginfo, &ts);
|
|
||||||
if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
|
|
||||||
perror("sigtimedwait");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (r) {
|
|
||||||
case SIGBUS:
|
|
||||||
if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) {
|
|
||||||
sigbus_reraise();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sigpending(&chkset);
|
|
||||||
if (r == -1) {
|
|
||||||
perror("sigpending");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !CONFIG_LINUX */
|
|
||||||
|
|
||||||
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 dummy_signal(int sig)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1012,12 +967,58 @@ static void qemu_kvm_init_cpu_signals(CPUState *cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* _WIN32 */
|
static void qemu_kvm_eat_signals(CPUState *cpu)
|
||||||
|
{
|
||||||
|
struct timespec ts = { 0, 0 };
|
||||||
|
siginfo_t siginfo;
|
||||||
|
sigset_t waitset;
|
||||||
|
sigset_t chkset;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
sigemptyset(&waitset);
|
||||||
|
sigaddset(&waitset, SIG_IPI);
|
||||||
|
sigaddset(&waitset, SIGBUS);
|
||||||
|
|
||||||
|
do {
|
||||||
|
r = sigtimedwait(&waitset, &siginfo, &ts);
|
||||||
|
if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
|
||||||
|
perror("sigtimedwait");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sigpending(&chkset);
|
||||||
|
if (r == -1) {
|
||||||
|
perror("sigpending");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
|
||||||
|
}
|
||||||
|
#else /* !CONFIG_LINUX */
|
||||||
|
static void qemu_init_sigbus(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_kvm_eat_signals(CPUState *cpu)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void qemu_kvm_init_cpu_signals(CPUState *cpu)
|
static void qemu_kvm_init_cpu_signals(CPUState *cpu)
|
||||||
{
|
{
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* !CONFIG_LINUX */
|
||||||
|
|
||||||
static QemuMutex qemu_global_mutex;
|
static QemuMutex qemu_global_mutex;
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,15 @@ void qemu_anon_ram_free(void *ptr, size_t size);
|
||||||
|
|
||||||
#endif
|
#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__) && \
|
#if defined(__linux__) && \
|
||||||
(defined(__x86_64__) || defined(__arm__) || defined(__aarch64__))
|
(defined(__x86_64__) || defined(__arm__) || defined(__aarch64__))
|
||||||
/* Use 2 MiB alignment so transparent hugepages can be used by KVM.
|
/* Use 2 MiB alignment so transparent hugepages can be used by KVM.
|
||||||
|
|
|
@ -64,13 +64,6 @@
|
||||||
* 255 kvm_msr_entry structs */
|
* 255 kvm_msr_entry structs */
|
||||||
#define MSR_BUF_SIZE 4096
|
#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[] = {
|
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
|
||||||
KVM_CAP_INFO(SET_TSS_ADDR),
|
KVM_CAP_INFO(SET_TSS_ADDR),
|
||||||
KVM_CAP_INFO(EXT_CPUID),
|
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;
|
ram_addr_t ram_addr;
|
||||||
hwaddr paddr;
|
hwaddr paddr;
|
||||||
|
|
||||||
if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) {
|
assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Because the MCE happened while running the VCPU, KVM could have
|
/* Because the MCE happened while running the VCPU, KVM could have
|
||||||
* injected action required MCEs too. Action optional MCEs should
|
* 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);
|
X86CPU *cpu = X86_CPU(first_cpu);
|
||||||
|
|
||||||
if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) {
|
assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code == BUS_MCEERR_AR) {
|
if (code == BUS_MCEERR_AR) {
|
||||||
hardware_memory_error();
|
hardware_memory_error();
|
||||||
|
|
Loading…
Reference in New Issue