There is a huge fpu synchronization issue here.
When the remote CPUs receive the ACPI sleep IPI, they do not save the fpu state of the lwp they are executing. The problem is, when waking up they reinitialize the registers of their local fpu and go back to their lwp directly. Therefore, if an lwp is interrupted while storing data in an fpu register, that data gets overwritten, which basically means the lwp is likely to go crazy when resuming execution. Fix this by simply saving the fpu state correctly. This way when going to sleep the state is stored in the lwp's pcb and CR0_TS is set, so the next time the lwp wants to use the fpu we'll get a dna, and the state will be restored as expected. While here, don't forget to reenable interrupts (and the spl) if an error occurs.
This commit is contained in:
parent
72c89a7fde
commit
21053717d0
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: acpi_wakeup.c,v 1.44 2016/10/20 14:06:18 maxv Exp $ */
|
||||
/* $NetBSD: acpi_wakeup.c,v 1.45 2016/10/20 16:05:04 maxv Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002, 2011 The NetBSD Foundation, Inc.
|
||||
@ -59,7 +59,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.44 2016/10/20 14:06:18 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.45 2016/10/20 16:05:04 maxv Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -250,13 +250,17 @@ acpi_md_sleep_enter(int state)
|
||||
void
|
||||
acpi_cpu_sleep(struct cpu_info *ci)
|
||||
{
|
||||
int s;
|
||||
|
||||
KASSERT(!CPU_IS_PRIMARY(ci));
|
||||
KASSERT(ci == curcpu());
|
||||
|
||||
s = splhigh();
|
||||
fpusave_cpu(true);
|
||||
x86_disable_intr();
|
||||
|
||||
if (acpi_md_sleep_prepare(-1))
|
||||
return;
|
||||
goto out;
|
||||
|
||||
/* Execute Wakeup */
|
||||
cpu_init_msrs(ci, false);
|
||||
@ -272,7 +276,9 @@ acpi_cpu_sleep(struct cpu_info *ci)
|
||||
kcpuset_atomic_set(kcpuset_running, cpu_index(ci));
|
||||
tsc_sync_ap(ci);
|
||||
|
||||
out:
|
||||
x86_enable_intr();
|
||||
splx(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user