From 547b3085eef9ae73ef08458e8c0b0c1c036de34f Mon Sep 17 00:00:00 2001 From: njl Date: Sat, 10 Jun 2006 08:20:17 +0000 Subject: [PATCH] * 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. --- sys/i386/acpica/acpi_wakeup.c | 45 +++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/sys/i386/acpica/acpi_wakeup.c b/sys/i386/acpica/acpi_wakeup.c index 543c0f2cca8..8295f9fc834 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 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) 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); } -- 2.45.2