@@ -2940,6 +2940,7 @@ void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu)
#ifdef KVM_HAVE_MCE_INJECTION
static __thread void *pending_sigbus_addr;
static __thread int pending_sigbus_code;
+static __thread short pending_sigbus_addr_lsb;
static __thread bool have_sigbus_pending;
#endif
@@ -3651,7 +3652,7 @@ void kvm_init_cpu_signals(CPUState *cpu)
}
/* Called asynchronously in VCPU thread. */
-int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
+int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr, short addr_lsb)
{
#ifdef KVM_HAVE_MCE_INJECTION
if (have_sigbus_pending) {
@@ -3660,6 +3661,7 @@ int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
have_sigbus_pending = true;
pending_sigbus_addr = addr;
pending_sigbus_code = code;
+ pending_sigbus_addr_lsb = addr_lsb;
qatomic_set(&cpu->exit_request, 1);
return 0;
#else
@@ -3668,7 +3670,7 @@ int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
}
/* Called synchronously (via signalfd) in main thread. */
-int kvm_on_sigbus(int code, void *addr)
+int kvm_on_sigbus(int code, void *addr, short addr_lsb)
{
#ifdef KVM_HAVE_MCE_INJECTION
/* Action required MCE kills the process if SIGBUS is blocked. Because
@@ -38,12 +38,12 @@ bool kvm_has_sync_mmu(void)
return false;
}
-int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
+int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr, short addr_lsb)
{
return 1;
}
-int kvm_on_sigbus(int code, void *addr)
+int kvm_on_sigbus(int code, void *addr, short addr_lsb)
{
return 1;
}
@@ -585,8 +585,9 @@ struct qemu_signalfd_siginfo {
uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */
uint64_t ssi_addr; /* Address that generated signal
(for hardware-generated signals) */
- uint8_t pad[48]; /* Pad size to 128 bytes (allow for
- additional fields in the future) */
+ uint16_t ssi_addr_lsb;/* Least significant bit of address (SIGBUS) */
+ uint8_t pad[46]; /* Pad size to 128 bytes (allow for */
+ /* additional fields in the future) */
};
int qemu_signalfd(const sigset_t *mask);
@@ -207,8 +207,8 @@ int kvm_has_gsi_routing(void);
bool kvm_arm_supports_user_irq(void);
-int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
-int kvm_on_sigbus(int code, void *addr);
+int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr, short addr_lsb);
+int kvm_on_sigbus(int code, void *addr, short addr_lsb);
#ifdef COMPILING_PER_TARGET
#include "cpu.h"
@@ -376,12 +376,14 @@ static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx)
if (current_cpu) {
/* Called asynchronously in VCPU thread. */
- if (kvm_on_sigbus_vcpu(current_cpu, siginfo->si_code, siginfo->si_addr)) {
+ if (kvm_on_sigbus_vcpu(current_cpu, siginfo->si_code,
+ siginfo->si_addr, siginfo->si_addr_lsb)) {
sigbus_reraise();
}
} else {
/* Called synchronously (via signalfd) in main thread. */
- if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) {
+ if (kvm_on_sigbus(siginfo->si_code,
+ siginfo->si_addr, siginfo->si_addr_lsb)) {
sigbus_reraise();
}
}
@@ -767,6 +767,9 @@ void sigaction_invoke(struct sigaction *action,
} else if (info->ssi_signo == SIGILL || info->ssi_signo == SIGFPE ||
info->ssi_signo == SIGSEGV || info->ssi_signo == SIGBUS) {
si.si_addr = (void *)(uintptr_t)info->ssi_addr;
+ if (info->ssi_signo == SIGBUS) {
+ si.si_addr_lsb = (short int)info->ssi_addr_lsb;
+ }
} else if (info->ssi_signo == SIGCHLD) {
si.si_pid = info->ssi_pid;
si.si_status = info->ssi_status;