mirror of https://gitee.com/openkylin/qemu.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)
|
||||
{
|
||||
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,55 +943,6 @@ static void qemu_init_sigbus(void)
|
|||
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)
|
||||
{
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
#endif /* !CONFIG_LINUX */
|
||||
|
||||
static QemuMutex qemu_global_mutex;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue