Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/acpica/acpi_wakeup.c
Show First 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
static void acpi_stop_beep(void *); | static void acpi_stop_beep(void *); | ||||
#ifdef SMP | #ifdef SMP | ||||
static int acpi_wakeup_ap(struct acpi_softc *, int); | static int acpi_wakeup_ap(struct acpi_softc *, int); | ||||
static void acpi_wakeup_cpus(struct acpi_softc *); | static void acpi_wakeup_cpus(struct acpi_softc *); | ||||
#endif | #endif | ||||
#ifdef __amd64__ | #ifdef __amd64__ | ||||
#define ACPI_WAKEPAGES 4 | #define ACPI_WAKEPAGES 5 | ||||
#else | #else | ||||
#define ACPI_WAKEPAGES 1 | #define ACPI_WAKEPAGES 1 | ||||
#endif | #endif | ||||
#define WAKECODE_FIXUP(offset, type, val) do { \ | #define WAKECODE_FIXUP(offset, type, val) do { \ | ||||
type *addr; \ | type *addr; \ | ||||
addr = (type *)(sc->acpi_wakeaddr + (offset)); \ | addr = (type *)(sc->acpi_wakeaddr + (offset)); \ | ||||
*addr = val; \ | *addr = val; \ | ||||
▲ Show 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void | void | ||||
acpi_install_wakeup_handler(struct acpi_softc *sc) | acpi_install_wakeup_handler(struct acpi_softc *sc) | ||||
{ | { | ||||
static void *wakeaddr; | static void *wakeaddr; | ||||
void *wakepages[ACPI_WAKEPAGES]; | void *wakepages[ACPI_WAKEPAGES]; | ||||
#ifdef __amd64__ | #ifdef __amd64__ | ||||
uint64_t *pt4, *pt3, *pt2; | uint64_t *pt5, *pt4, *pt3, *pt2; | ||||
vm_paddr_t pt4pa, pt3pa, pt2pa; | vm_paddr_t pt5pa, pt4pa, pt3pa, pt2pa; | ||||
int i; | int i; | ||||
#endif | #endif | ||||
if (wakeaddr != NULL) | if (wakeaddr != NULL) | ||||
return; | return; | ||||
if (acpi_alloc_wakeup_handler(wakepages) == NULL) | if (acpi_alloc_wakeup_handler(wakepages) == NULL) | ||||
return; | return; | ||||
wakeaddr = wakepages[0]; | wakeaddr = wakepages[0]; | ||||
sc->acpi_wakeaddr = (vm_offset_t)wakeaddr; | sc->acpi_wakeaddr = (vm_offset_t)wakeaddr; | ||||
sc->acpi_wakephys = vtophys(wakeaddr); | sc->acpi_wakephys = vtophys(wakeaddr); | ||||
#ifdef __amd64__ | #ifdef __amd64__ | ||||
if (la57) { | |||||
pt5 = wakepages[4]; | |||||
pt5pa = vtophys(pt5); | |||||
} | |||||
pt4 = wakepages[1]; | pt4 = wakepages[1]; | ||||
pt3 = wakepages[2]; | pt3 = wakepages[2]; | ||||
pt2 = wakepages[3]; | pt2 = wakepages[3]; | ||||
pt4pa = vtophys(pt4); | pt4pa = vtophys(pt4); | ||||
pt3pa = vtophys(pt3); | pt3pa = vtophys(pt3); | ||||
pt2pa = vtophys(pt2); | pt2pa = vtophys(pt2); | ||||
#endif | #endif | ||||
bcopy(wakecode, (void *)sc->acpi_wakeaddr, sizeof(wakecode)); | bcopy(wakecode, (void *)sc->acpi_wakeaddr, sizeof(wakecode)); | ||||
/* Patch GDT base address, ljmp targets. */ | /* Patch GDT base address, ljmp targets. */ | ||||
WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t, | WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t, | ||||
sc->acpi_wakephys + bootgdt); | sc->acpi_wakephys + bootgdt); | ||||
WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t, | WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t, | ||||
sc->acpi_wakephys + wakeup_32); | sc->acpi_wakephys + wakeup_32); | ||||
#ifdef __amd64__ | #ifdef __amd64__ | ||||
WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t, | WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t, | ||||
sc->acpi_wakephys + wakeup_64); | sc->acpi_wakephys + wakeup_64); | ||||
WAKECODE_FIXUP(wakeup_pagetables, uint32_t, pt4pa); | WAKECODE_FIXUP(wakeup_pagetables, uint32_t, la57 ? (pt5pa | 0x1) : | ||||
pt4pa); | |||||
#endif | #endif | ||||
/* Save pointers to some global data. */ | /* Save pointers to some global data. */ | ||||
WAKECODE_FIXUP(wakeup_ret, void *, resumectx); | WAKECODE_FIXUP(wakeup_ret, void *, resumectx); | ||||
#ifndef __amd64__ | #ifndef __amd64__ | ||||
WAKECODE_FIXUP(wakeup_cr3, register_t, pmap_get_kcr3()); | WAKECODE_FIXUP(wakeup_cr3, register_t, pmap_get_kcr3()); | ||||
#else /* __amd64__ */ | #else /* __amd64__ */ | ||||
/* Create the initial 1GB replicated page tables */ | /* Create the initial 1GB replicated page tables */ | ||||
for (i = 0; i < 512; i++) { | for (i = 0; i < NPTEPG; i++) { | ||||
if (la57) { | |||||
pt5[i] = (uint64_t)pt4pa; | |||||
pt5[i] |= PG_V | PG_RW | PG_U; | |||||
} | |||||
/* | /* | ||||
* Each slot of the level 4 pages points | * Each slot of the level 4 pages points | ||||
* to the same level 3 page | * to the same level 3 page | ||||
*/ | */ | ||||
pt4[i] = (uint64_t)pt3pa; | pt4[i] = (uint64_t)pt3pa; | ||||
pt4[i] |= PG_V | PG_RW | PG_U; | pt4[i] |= PG_V | PG_RW | PG_U; | ||||
/* | /* | ||||
* Each slot of the level 3 pages points | * Each slot of the level 3 pages points | ||||
* to the same level 2 page | * to the same level 2 page | ||||
*/ | */ | ||||
pt3[i] = (uint64_t)pt2pa; | pt3[i] = (uint64_t)pt2pa; | ||||
pt3[i] |= PG_V | PG_RW | PG_U; | pt3[i] |= PG_V | PG_RW | PG_U; | ||||
/* The level 2 page slots are mapped with 2MB pages for 1GB. */ | /* The level 2 page slots are mapped with 2MB pages for 1GB. */ | ||||
pt2[i] = i * (2 * 1024 * 1024); | pt2[i] = i * NBPDR; | ||||
pt2[i] |= PG_V | PG_RW | PG_PS | PG_U; | pt2[i] |= PG_V | PG_RW | PG_PS | PG_U; | ||||
} | } | ||||
#endif /* !__amd64__ */ | #endif /* !__amd64__ */ | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->acpi_dev, "wakeup code va %#jx pa %#jx\n", | device_printf(sc->acpi_dev, "wakeup code va %#jx pa %#jx\n", | ||||
(uintmax_t)sc->acpi_wakeaddr, (uintmax_t)sc->acpi_wakephys); | (uintmax_t)sc->acpi_wakeaddr, (uintmax_t)sc->acpi_wakephys); | ||||
} | } |