svn commit: r197863 - head/sys/amd64/acpica

Jung-uk Kim jkim at FreeBSD.org
Thu Oct 8 17:41:54 UTC 2009


Author: jkim
Date: Thu Oct  8 17:41:53 2009
New Revision: 197863
URL: http://svn.freebsd.org/changeset/base/197863

Log:
  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.

Modified:
  head/sys/amd64/acpica/acpi_machdep.c
  head/sys/amd64/acpica/acpi_wakecode.S
  head/sys/amd64/acpica/acpi_wakeup.c

Modified: head/sys/amd64/acpica/acpi_machdep.c
==============================================================================
--- head/sys/amd64/acpica/acpi_machdep.c	Thu Oct  8 17:11:01 2009	(r197862)
+++ head/sys/amd64/acpica/acpi_machdep.c	Thu Oct  8 17:41:53 2009	(r197863)
@@ -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[] = {

Modified: head/sys/amd64/acpica/acpi_wakecode.S
==============================================================================
--- head/sys/amd64/acpica/acpi_wakecode.S	Thu Oct  8 17:11:01 2009	(r197862)
+++ head/sys/amd64/acpica/acpi_wakecode.S	Thu Oct  8 17:41:53 2009	(r197863)
@@ -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:
 

Modified: head/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/amd64/acpica/acpi_wakeup.c	Thu Oct  8 17:11:01 2009	(r197862)
+++ head/sys/amd64/acpica/acpi_wakeup.c	Thu Oct  8 17:41:53 2009	(r197863)
@@ -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_
 	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);
 


More information about the svn-src-head mailing list