[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [question] mask SIGBUS in qemu main thread
From: |
gengdongjiu |
Subject: |
Re: [Qemu-devel] [question] mask SIGBUS in qemu main thread |
Date: |
Mon, 20 Nov 2017 21:32:34 +0800 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 |
On 2017/11/20 21:00, Peter Maydell wrote:
> On 20 November 2017 at 12:50, Alex Bennée <address@hidden> wrote:
>> What exactly do you expect the main thread to do with a SIGBUS signal?
>
> For KVM, we (can) use SIGBUS for handling machine check exceptions:
> see qemu_init_sigbus() in cpus.c, where we use prctl(PR_MCE_KILL)
> to ask the host kernel to send us a SIGBUS if the memory used
> by the VM has memory corruption detected by the hardwar. This
> then lets us inform the guest (see kvm_mce_inject() in target/i386).
> (This will probably be coming to Arm KVM at some point, as part
> of the RAS extension support. See various threads in kvmarm list.)
thanks, yes, indeed.
when the RAS is enabled, if a guest memory address is corruption, host will
unmap the stage2 mapping and try to find a Qemu thread to
deliver the SIGBUS signal[1]. when Qemu receive the signal, it will try to do
some recovery for guest.
such as kvm_mce_inject() in target/i386.
In host kernel[1], if the flag set MF_ACTION_REQUIRED, host will find current
vcpu thread to deliver SIGBUS with si_code BUS_MCEERR_AR
Otherwise it will find Qemu main thread to deliver the SIGBUS with si_code
BUS_MCEERR_AO
For this case, Qemu will block this SIGBUS and this signal will be always
pending.
For the KVM[2], it does not matter, because KVM will choose the current vcpu
thread to deliver SIGBUS, not the main Qemu thread.
[1]
static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,
unsigned long pfn, struct page *page, int flags)
..................
if ((flags & MF_ACTION_REQUIRED) && t->mm == current->mm) {
si.si_code = BUS_MCEERR_AR;
ret = force_sig_info(SIGBUS, &si, current);
} else {
/*
* Don't use force here, it's convenient if the signal
* can be temporarily blocked.
* This could cause a loop when the user sets SIGBUS
* to SIG_IGN, but hopefully no one will do that?
*/
si.si_code = BUS_MCEERR_AO;
ret = send_sig_info(SIGBUS, &si, t); /* synchronous? */
}
}
[2]
static void kvm_send_hwpoison_signal(unsigned long address,
struct vm_area_struct *vma)
{
siginfo_t info;
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_MCEERR_AR;
info.si_addr = (void __user *)address;
if (is_vm_hugetlb_page(vma))
info.si_addr_lsb = huge_page_shift(hstate_vma(vma));
else
info.si_addr_lsb = PAGE_SHIFT;
send_sig_info(SIGBUS, &info, current);
}
>
> Because asynchronous signals are a pain to deal with, for the
> main thread we handle all our signals via signalfd(), which is
> why the main thread shows SIGBUS as blocked. The main thread
> will pick the signal up via the fd at some point. For KVM vcpu
> threads, the signal arrives asynchronously. See sigbus_handler()
> in cpus.c.
thanks Pether's explanation.
yes, you are right.
>
> thanks
> -- PMM
>
>