summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2006-06-10 08:20:17 +0000
committernjl <njl@FreeBSD.org>2006-06-10 08:20:17 +0000
commit547b3085eef9ae73ef08458e8c0b0c1c036de34f (patch)
tree7b040ecef1efe17dc500a6f5a19a68105f6e12c1 /sys
parent66b0070261edf8213d0517b7a31e3e4bf28f2fe3 (diff)
downloadFreeBSD-src-547b3085eef9ae73ef08458e8c0b0c1c036de34f.zip
FreeBSD-src-547b3085eef9ae73ef08458e8c0b0c1c036de34f.tar.gz
* Ask for a page-aligned page instead of an arbitrary address. This should
not be necessary but might be helpful and at least reduce fragmentation. * Add an assert to detect if the wakecode ever grows too big. We include 1 KB for stack, which should be more than enough also. * Remove unnecessary initialization of static variables. * Add comments and a bootverbose print giving the page phys address.
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/acpica/acpi_wakeup.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/sys/i386/acpica/acpi_wakeup.c b/sys/i386/acpica/acpi_wakeup.c
index 543c0f2..8295f9f 100644
--- a/sys/i386/acpica/acpi_wakeup.c
+++ b/sys/i386/acpica/acpi_wakeup.c
@@ -52,6 +52,9 @@ __FBSDID("$FreeBSD$");
#include "acpi_wakecode.h"
+/* Make sure the code is less than one 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
@@ -67,7 +70,7 @@ static uint32_t r_eax, r_ebx, r_ecx, r_edx, r_ebp, r_esi, r_edi,
r_efl, r_cr0, r_cr2, r_cr3, r_cr4, ret_addr;
static uint16_t r_cs, r_ds, r_es, r_fs, r_gs, r_ss, r_tr;
-static uint32_t r_esp = 0;
+static uint32_t r_esp;
static void acpi_printcpu(void);
static void acpi_realmodeinst(void *arg, bus_dma_segment_t *segs,
@@ -282,7 +285,7 @@ out:
static bus_dma_tag_t acpi_waketag;
static bus_dmamap_t acpi_wakemap;
-static vm_offset_t acpi_wakeaddr = 0;
+static vm_offset_t acpi_wakeaddr;
static void
acpi_alloc_wakeup_handler(void)
@@ -292,16 +295,21 @@ acpi_alloc_wakeup_handler(void)
if (!cold)
return;
- if (bus_dma_tag_create(/* parent */ NULL, /* alignment */ 2, 0,
- /* lowaddr below 1MB */ 0x9ffff,
- /* highaddr */ BUS_SPACE_MAXADDR, NULL, NULL,
- PAGE_SIZE, 1, PAGE_SIZE, 0, busdma_lock_mutex,
- &Giant, &acpi_waketag) != 0) {
+ /*
+ * 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.
+ */
+ if (bus_dma_tag_create(/*parent*/ NULL,
+ /*alignment*/ PAGE_SIZE, /*no boundary*/ 0,
+ /*lowaddr*/ 0x9ffff, /*highaddr*/ BUS_SPACE_MAXADDR, NULL, NULL,
+ /*maxsize*/ PAGE_SIZE, /*segments*/ 1, /*maxsegsize*/ PAGE_SIZE,
+ 0, busdma_lock_mutex, &Giant, &acpi_waketag) != 0) {
printf("acpi_alloc_wakeup_handler: can't create wake tag\n");
return;
}
- if (bus_dmamem_alloc(acpi_waketag, &wakeaddr,
- BUS_DMA_NOWAIT, &acpi_wakemap)) {
+ if (bus_dmamem_alloc(acpi_waketag, &wakeaddr, BUS_DMA_NOWAIT,
+ &acpi_wakemap) != 0) {
printf("acpi_alloc_wakeup_handler: can't alloc wake memory\n");
return;
}
@@ -313,13 +321,21 @@ SYSINIT(acpiwakeup, SI_SUB_KMEM, SI_ORDER_ANY, acpi_alloc_wakeup_handler, 0)
static void
acpi_realmodeinst(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
- struct acpi_softc *sc = arg;
- uint32_t *addr;
+ struct acpi_softc *sc;
+ uint32_t *addr;
+ /* Overwrite the ljmp target with the real address */
+ sc = arg;
+ sc->acpi_wakephys = segs[0].ds_addr;
addr = (uint32_t *)&wakecode[wakeup_sw32 + 2];
- *addr = segs[0].ds_addr + wakeup_32;
+ *addr = sc->acpi_wakephys + wakeup_32;
+
+ /* Copy the wake code into our low page and save its physical addr. */
bcopy(wakecode, (void *)sc->acpi_wakeaddr, sizeof(wakecode));
- sc->acpi_wakephys = segs[0].ds_addr;
+ if (bootverbose) {
+ device_printf(sc->acpi_dev, "wakeup code va %#x pa %#x\n",
+ acpi_wakeaddr, sc->acpi_wakephys);
+ }
}
void
@@ -333,6 +349,5 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
sc->acpi_wakemap = acpi_wakemap;
bus_dmamap_load(sc->acpi_waketag, sc->acpi_wakemap,
- (void *)sc->acpi_wakeaddr, PAGE_SIZE,
- acpi_realmodeinst, sc, 0);
+ (void *)sc->acpi_wakeaddr, PAGE_SIZE, acpi_realmodeinst, sc, 0);
}
OpenPOWER on IntegriCloud