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.
This commit is contained in:
parent
c217b20ef6
commit
a7e2341e20
@ -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[] = {
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
|
||||
sc->acpi_wakeaddr = acpi_wakeaddr;
|
||||
sc->acpi_wakephys = vtophys(acpi_wakeaddr);
|
||||
wakeaddr = acpi_alloc_wakeup_handler();
|
||||
if (wakeaddr == NULL)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user