summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2014-07-09 11:37:17 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2014-07-09 11:37:17 +0000
commit0053cf4ab1127d6994edc86edc446e1655c33a16 (patch)
treeb723970471664a024b1f3c53478da817f5e864b7
parent7a60749ed5233c0bbfa2014ba2cbd5e8265ee395 (diff)
Fixes a hibernate issue wherein we locked the kernel lock while hatching
but then parked ourselves in real mode without completing acquisition of said lock. Also removes the park routine from i386 since we don't need it (the APs are already parked at the time we start unpack). discussed with and ok kettenis@, also ok deraadt@
-rw-r--r--sys/arch/amd64/amd64/cpu.c14
-rw-r--r--sys/arch/amd64/amd64/hibernate_machdep.c26
-rw-r--r--sys/arch/amd64/amd64/ipifuncs.c23
-rw-r--r--sys/arch/amd64/include/cpu.h3
-rw-r--r--sys/arch/amd64/include/hibernate.h3
-rw-r--r--sys/arch/amd64/include/intrdefs.h7
-rw-r--r--sys/arch/i386/i386/hibernate_machdep.c17
7 files changed, 43 insertions, 50 deletions
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
index 88725f77d78..9596efc9697 100644
--- a/sys/arch/amd64/amd64/cpu.c
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.61 2014/04/30 06:24:23 sf Exp $ */
+/* $OpenBSD: cpu.c,v 1.62 2014/07/09 11:37:16 mlarkin Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
@@ -103,6 +103,11 @@
#include <amd64/isa/nvram.h>
#include <dev/isa/isareg.h>
+#ifdef HIBERNATE
+#include <sys/hibernate.h>
+#include <machine/hibernate.h>
+#endif /* HIBERNATE */
+
int cpu_match(struct device *, void *, void *);
void cpu_attach(struct device *, struct device *, void *);
void patinit(struct cpu_info *ci);
@@ -589,7 +594,7 @@ cpu_boot_secondary_processors(void)
continue;
if ((ci->ci_flags & CPUF_PRESENT) == 0)
continue;
- if (ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY))
+ if (ci->ci_flags & (CPUF_BSP | CPUF_SP | CPUF_PRIMARY))
continue;
ci->ci_randseed = (arc4random() & 0x7fffffff) + 1;
cpu_boot_secondary(ci);
@@ -705,6 +710,11 @@ cpu_hatch(void *v)
while ((ci->ci_flags & CPUF_IDENTIFY) == 0)
delay(10);
+#ifdef HIBERNATE
+ if ((ci->ci_flags & CPUF_PARK) != 0)
+ hibernate_drop_to_real_mode();
+#endif /* HIBERNATE */
+
identifycpu(ci);
/* Signal we're done */
diff --git a/sys/arch/amd64/amd64/hibernate_machdep.c b/sys/arch/amd64/amd64/hibernate_machdep.c
index 33c695e9c3a..a5f07699ee4 100644
--- a/sys/arch/amd64/amd64/hibernate_machdep.c
+++ b/sys/arch/amd64/amd64/hibernate_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate_machdep.c,v 1.21 2014/06/11 00:30:25 mlarkin Exp $ */
+/* $OpenBSD: hibernate_machdep.c,v 1.22 2014/07/09 11:37:16 mlarkin Exp $ */
/*
* Copyright (c) 2012 Mike Larkin <mlarkin@openbsd.org>
@@ -32,6 +32,7 @@
#include <uvm/uvm_extern.h>
#include <uvm/uvm_pmemrange.h>
+#include <machine/cpu.h>
#include <machine/hibernate.h>
#include <machine/hibernate_var.h>
#include <machine/kcore.h>
@@ -359,16 +360,25 @@ hibernate_disable_intr_machdep(void)
void
hibernate_quiesce_cpus(void)
{
- KASSERT(CPU_IS_PRIMARY(curcpu()));
+ struct cpu_info *ci;
+ u_long i;
- /* Start the hatched (but idling) APs */
- cpu_boot_secondary_processors();
+ KASSERT(CPU_IS_PRIMARY(curcpu()));
- /* Demote the APs to real mode */
- x86_broadcast_ipi(X86_IPI_HALT_REALMODE);
+ for (i = 0; i < MAXCPUS; i++) {
+ ci = cpu_info[i];
+ if (ci == NULL)
+ continue;
+ if (ci->ci_idle_pcb == NULL)
+ continue;
+ if ((ci->ci_flags & CPUF_PRESENT) == 0)
+ continue;
+ if (ci->ci_flags & (CPUF_BSP | CPUF_SP | CPUF_PRIMARY))
+ continue;
+ atomic_setbits_int(&ci->ci_flags, CPUF_GO | CPUF_PARK);
+ }
/* Wait a bit for the APs to park themselves */
- delay(1000000);
-
+ delay(500000);
}
#endif /* MULTIPROCESSOR */
diff --git a/sys/arch/amd64/amd64/ipifuncs.c b/sys/arch/amd64/amd64/ipifuncs.c
index 608570f5386..2b04b5bb858 100644
--- a/sys/arch/amd64/amd64/ipifuncs.c
+++ b/sys/arch/amd64/amd64/ipifuncs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipifuncs.c,v 1.23 2014/03/29 18:09:28 guenther Exp $ */
+/* $OpenBSD: ipifuncs.c,v 1.24 2014/07/09 11:37:16 mlarkin Exp $ */
/* $NetBSD: ipifuncs.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*-
@@ -85,11 +85,6 @@ void (*ipifunc[X86_NIPI])(struct cpu_info *) =
#else
NULL,
#endif
-#ifdef HIBERNATE
- x86_64_ipi_halt_realmode,
-#else
- NULL,
-#endif /* HIBERNATE */
};
void
@@ -135,19 +130,3 @@ x86_64_ipi_reload_mtrr(struct cpu_info *ci)
mem_range_softc.mr_op->reload(&mem_range_softc);
}
#endif
-
-#ifdef HIBERNATE
-void
-x86_64_ipi_halt_realmode(struct cpu_info *ci)
-{
- /* Halt CPUs and park in real mode */
-
- fpusave_cpu(ci, 1);
- disable_intr();
- wbinvd();
- ci->ci_flags &= ~CPUF_RUNNING;
- wbinvd();
-
- hibernate_drop_to_real_mode();
-}
-#endif /* HIBERNATE */
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index 4495ed1a7a9..c833c97b3dd 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.83 2014/02/13 23:11:06 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.84 2014/07/09 11:37:16 mlarkin Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -163,6 +163,7 @@ struct cpu_info {
#define CPUF_RUNNING 0x2000 /* CPU is running */
#define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */
#define CPUF_GO 0x8000 /* CPU should start running */
+#define CPUF_PARK 0x10000 /* CPU should self-park in real mode */
#define PROC_PC(p) ((p)->p_md.md_regs->tf_rip)
#define PROC_STACK(p) ((p)->p_md.md_regs->tf_rsp)
diff --git a/sys/arch/amd64/include/hibernate.h b/sys/arch/amd64/include/hibernate.h
index 9d620add2cf..cfcb812ff78 100644
--- a/sys/arch/amd64/include/hibernate.h
+++ b/sys/arch/amd64/include/hibernate.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate.h,v 1.5 2014/05/31 06:30:16 mlarkin Exp $ */
+/* $OpenBSD: hibernate.h,v 1.6 2014/07/09 11:37:16 mlarkin Exp $ */
/*
* Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
@@ -32,4 +32,5 @@ void hibernate_enable_intr_machdep(void);
void hibernate_disable_intr_machdep(void);
#ifdef MULTIPROCESSOR
void hibernate_quiesce_cpus(void);
+void hibernate_drop_to_real_mode(void);
#endif /* MULTIPROCESSOR */
diff --git a/sys/arch/amd64/include/intrdefs.h b/sys/arch/amd64/include/intrdefs.h
index b08eda38d1b..251e2958490 100644
--- a/sys/arch/amd64/include/intrdefs.h
+++ b/sys/arch/amd64/include/intrdefs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intrdefs.h,v 1.11 2013/06/01 22:22:13 mlarkin Exp $ */
+/* $OpenBSD: intrdefs.h,v 1.12 2014/07/09 11:37:16 mlarkin Exp $ */
/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */
#ifndef _AMD64_INTRDEFS_H
@@ -81,12 +81,11 @@
#define X86_IPI_DDB 0x00000080
#define X86_IPI_HALT_REALMODE 0x00000100
-#define X86_NIPI 9
+#define X86_NIPI 8
#define X86_IPI_NAMES { "halt IPI", "nop IPI", "FPU flush IPI", \
"FPU synch IPI", "TLB shootdown IPI", \
- "MTRR update IPI", "setperf IPI", "ddb IPI", \
- "realmode halt IPI" }
+ "MTRR update IPI", "setperf IPI", "ddb IPI" }
#define IREENT_MAGIC 0x18041969
diff --git a/sys/arch/i386/i386/hibernate_machdep.c b/sys/arch/i386/i386/hibernate_machdep.c
index 932f7b89417..d14cb76d5af 100644
--- a/sys/arch/i386/i386/hibernate_machdep.c
+++ b/sys/arch/i386/i386/hibernate_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate_machdep.c,v 1.31 2014/06/11 00:30:25 mlarkin Exp $ */
+/* $OpenBSD: hibernate_machdep.c,v 1.32 2014/07/09 11:37:16 mlarkin Exp $ */
/*
* Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
@@ -297,20 +297,13 @@ hibernate_disable_intr_machdep(void)
#ifdef MULTIPROCESSOR
/*
- * Quiesce CPUs in a multiprocessor machine before resuming. We need to do
- * this since the APs will be hatched (but waiting for CPUF_GO), and we don't
- * want the APs to be executing code and causing side effects during the
- * unpack operation.
+ * On i386, the APs have not been hatched at the time hibernate resume is
+ * called, so there is no need to quiesce them. We do want to make sure
+ * however that we are on the BSP.
*/
void
hibernate_quiesce_cpus(void)
{
- KASSERT(CPU_IS_PRIMARY(curcpu()));
-
- /* Start the hatched (but idling) APs */
- cpu_boot_secondary_processors();
-
- /* Now shut them down */
- acpi_sleep_mp();
+ KASSERT(CPU_IS_PRIMARY(curcpu()));
}
#endif /* MULTIPROCESSOR */