aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2009-10-08 17:41:53 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2009-10-08 17:41:53 +0000
commita7e2341e20a38619ffecb850186736ca89e0243c (patch)
treea89be9ece2e55e12a45b805879c8d0efd5d61ff5 /sys/amd64
parentc217b20ef6dbb61de76e4c194d03cdb0cffcbb01 (diff)
downloadsrc-a7e2341e20a38619ffecb850186736ca89e0243c.tar.gz
src-a7e2341e20a38619ffecb850186736ca89e0243c.zip
Clean up amd64 suspend/resume code.
- Allocate memory for wakeup code after ACPI bus is attached. The early memory allocation hack was inherited from i386 but amd64 does not need it. - Exclude real mode IVT and BDA explicitly. Improve comments about memory allocation and reason for the exclusions. It is a no-op in reality, though. - Remove an unnecessary CLD from wakeup code and re-align.
Notes
Notes: svn path=/head/; revision=197863
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/acpica/acpi_machdep.c13
-rw-r--r--sys/amd64/acpica/acpi_wakecode.S6
-rw-r--r--sys/amd64/acpica/acpi_wakeup.c49
3 files changed, 35 insertions, 33 deletions
diff --git a/sys/amd64/acpica/acpi_machdep.c b/sys/amd64/acpica/acpi_machdep.c
index 9d62ab5c81e1..7e7a01aef50c 100644
--- a/sys/amd64/acpica/acpi_machdep.c
+++ b/sys/amd64/acpica/acpi_machdep.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
+
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -511,7 +512,6 @@ acpi_machdep_init(device_t dev)
sc->acpi_clone = apm_create_clone(sc->acpi_dev_t, sc);
clone_setup(&apm_clones);
EVENTHANDLER_REGISTER(dev_clone, apm_clone, 0, 1000);
- acpi_install_wakeup_handler(sc);
if (intr_model != ACPI_INTR_PIC)
acpi_SetIntrModel(intr_model);
@@ -801,13 +801,20 @@ nexus_acpi_probe(device_t dev)
static int
nexus_acpi_attach(device_t dev)
{
+ device_t acpi_dev;
+ int error;
nexus_init_resources();
bus_generic_probe(dev);
- if (BUS_ADD_CHILD(dev, 10, "acpi", 0) == NULL)
+ acpi_dev = BUS_ADD_CHILD(dev, 10, "acpi", 0);
+ if (acpi_dev == NULL)
panic("failed to add acpi0 device");
- return (bus_generic_attach(dev));
+ error = bus_generic_attach(dev);
+ if (error == 0)
+ acpi_install_wakeup_handler(device_get_softc(acpi_dev));
+
+ return (error);
}
static device_method_t nexus_acpi_methods[] = {
diff --git a/sys/amd64/acpica/acpi_wakecode.S b/sys/amd64/acpica/acpi_wakecode.S
index 4e82f53196af..1372cc1a2d09 100644
--- a/sys/amd64/acpica/acpi_wakecode.S
+++ b/sys/amd64/acpica/acpi_wakecode.S
@@ -54,18 +54,17 @@
.data /* So we can modify it */
ALIGN_TEXT
-wakeup_start:
.code16
+wakeup_start:
/*
* Set up segment registers for real mode, a small stack for
* any calls we make, and clear any flags.
*/
cli /* make sure no interrupts */
- cld
mov %cs, %ax /* copy %cs to %ds. Remember these */
mov %ax, %ds /* are offsets rather than selectors */
mov %ax, %ss
- movw $PAGE_SIZE - 8, %sp
+ movw $PAGE_SIZE, %sp
xorw %ax, %ax
pushw %ax
popfw
@@ -129,6 +128,7 @@ wakeup_sw32:
/*
* At this point, we are running in 32 bit legacy protected mode.
*/
+ ALIGN_TEXT
.code32
wakeup_32:
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c
index bcc405fca0a3..cfc960b3951b 100644
--- a/sys/amd64/acpica/acpi_wakeup.c
+++ b/sys/amd64/acpica/acpi_wakeup.c
@@ -31,13 +31,11 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/memrange.h>
#include <sys/smp.h>
-#include <sys/types.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -46,11 +44,11 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#include <machine/pmap.h>
#include <machine/specialreg.h>
-#include <machine/vmparam.h>
#ifdef SMP
#include <machine/apicreg.h>
#include <machine/smp.h>
+#include <machine/vmparam.h>
#endif
#include <contrib/dev/acpica/include/acpi.h>
@@ -63,10 +61,6 @@ __FBSDID("$FreeBSD$");
/* Make sure the code is less than a page and leave room for the stack. */
CTASSERT(sizeof(wakecode) < PAGE_SIZE - 1024);
-#ifndef _SYS_CDEFS_H_
-#error this file needs sys/cdefs.h as a prerequisite
-#endif
-
extern int acpi_resume_beep;
extern int acpi_reset_video;
@@ -79,7 +73,7 @@ static struct xpcb *stopxpcbs;
int acpi_restorecpu(struct xpcb *, vm_offset_t);
int acpi_savecpu(struct xpcb *);
-static void acpi_alloc_wakeup_handler(void);
+static void *acpi_alloc_wakeup_handler(void);
static void acpi_stop_beep(void *);
#ifdef SMP
@@ -322,49 +316,50 @@ out:
return (ret);
}
-static vm_offset_t acpi_wakeaddr;
-
-static void
+static void *
acpi_alloc_wakeup_handler(void)
{
void *wakeaddr;
- if (!cold)
- return;
-
/*
* Specify the region for our wakeup code. We want it in the low 1 MB
- * region, excluding video memory and above (0xa0000). We ask for
- * it to be page-aligned, just to be safe.
+ * region, excluding real mode IVT (0-0x3ff), BDA (0x400-0x4ff), EBDA
+ * (less than 128KB, below 0xa0000, must be excluded by SMAP and DSDT),
+ * and ROM area (0xa0000 and above). The temporary page tables must be
+ * page-aligned.
*/
- wakeaddr = contigmalloc(4 * PAGE_SIZE, M_DEVBUF, M_NOWAIT, 0, 0x9ffff,
- PAGE_SIZE, 0ul);
+ wakeaddr = contigmalloc(4 * PAGE_SIZE, M_DEVBUF, M_NOWAIT, 0x500,
+ 0xa0000, PAGE_SIZE, 0ul);
if (wakeaddr == NULL) {
printf("%s: can't alloc wake memory\n", __func__);
- return;
+ return (NULL);
}
stopxpcbs = malloc(mp_ncpus * sizeof(*stopxpcbs), M_DEVBUF, M_NOWAIT);
if (stopxpcbs == NULL) {
contigfree(wakeaddr, 4 * PAGE_SIZE, M_DEVBUF);
printf("%s: can't alloc CPU state memory\n", __func__);
- return;
+ return (NULL);
}
- acpi_wakeaddr = (vm_offset_t)wakeaddr;
-}
-SYSINIT(acpiwakeup, SI_SUB_KMEM, SI_ORDER_ANY, acpi_alloc_wakeup_handler, 0);
+ return (wakeaddr);
+}
void
acpi_install_wakeup_handler(struct acpi_softc *sc)
{
+ static void *wakeaddr = NULL;
uint64_t *pt4, *pt3, *pt2;
int i;
- if (acpi_wakeaddr == 0ul)
+ if (wakeaddr != NULL)
+ return;
+
+ wakeaddr = acpi_alloc_wakeup_handler();
+ if (wakeaddr == NULL)
return;
- sc->acpi_wakeaddr = acpi_wakeaddr;
- sc->acpi_wakephys = vtophys(acpi_wakeaddr);
+ sc->acpi_wakeaddr = (vm_offset_t)wakeaddr;
+ sc->acpi_wakephys = vtophys(wakeaddr);
bcopy(wakecode, (void *)WAKECODE_VADDR(sc), sizeof(wakecode));
@@ -390,7 +385,7 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
WAKECODE_FIXUP(wakeup_sfmask, uint64_t, rdmsr(MSR_SF_MASK));
/* Build temporary page tables below realmode code. */
- pt4 = (uint64_t *)acpi_wakeaddr;
+ pt4 = wakeaddr;
pt3 = pt4 + (PAGE_SIZE) / sizeof(uint64_t);
pt2 = pt3 + (PAGE_SIZE) / sizeof(uint64_t);