diff options
author | Mike Larkin <mlarkin@cvs.openbsd.org> | 2014-07-09 11:37:17 +0000 |
---|---|---|
committer | Mike Larkin <mlarkin@cvs.openbsd.org> | 2014-07-09 11:37:17 +0000 |
commit | 0053cf4ab1127d6994edc86edc446e1655c33a16 (patch) | |
tree | b723970471664a024b1f3c53478da817f5e864b7 | |
parent | 7a60749ed5233c0bbfa2014ba2cbd5e8265ee395 (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.c | 14 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/hibernate_machdep.c | 26 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/ipifuncs.c | 23 | ||||
-rw-r--r-- | sys/arch/amd64/include/cpu.h | 3 | ||||
-rw-r--r-- | sys/arch/amd64/include/hibernate.h | 3 | ||||
-rw-r--r-- | sys/arch/amd64/include/intrdefs.h | 7 | ||||
-rw-r--r-- | sys/arch/i386/i386/hibernate_machdep.c | 17 |
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 */ |