diff --git a/sys/x86/acpica/acpi_wakeup.c b/sys/x86/acpica/acpi_wakeup.c --- a/sys/x86/acpica/acpi_wakeup.c +++ b/sys/x86/acpica/acpi_wakeup.c @@ -99,7 +99,7 @@ #endif #ifdef __amd64__ -#define ACPI_WAKEPAGES 5 +#define ACPI_WAKEPAGES 8 #else #define ACPI_WAKEPAGES 1 #endif @@ -164,16 +164,22 @@ int cpu; u_char mpbiosreason; - /* save the current value of the warm-start vector */ - mpbioswarmvec = *((uint32_t *)WARMBOOT_OFF); - outb(CMOS_REG, BIOS_RESET); - mpbiosreason = inb(CMOS_DATA); - - /* setup a vector to our boot code */ - *((volatile u_short *)WARMBOOT_OFF) = WARMBOOT_TARGET; - *((volatile u_short *)WARMBOOT_SEG) = sc->acpi_wakephys >> 4; - outb(CMOS_REG, BIOS_RESET); - outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */ +#ifdef __amd64__ + if (!efi_boot) { +#endif + /* save the current value of the warm-start vector */ + mpbioswarmvec = *((uint32_t *)WARMBOOT_OFF); + outb(CMOS_REG, BIOS_RESET); + mpbiosreason = inb(CMOS_DATA); + + /* setup a vector to our boot code */ + *((volatile u_short *)WARMBOOT_OFF) = WARMBOOT_TARGET; + *((volatile u_short *)WARMBOOT_SEG) = sc->acpi_wakephys >> 4; + outb(CMOS_REG, BIOS_RESET); + outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */ +#ifdef __amd64__ + } +#endif /* Wake up each AP. */ for (cpu = 1; cpu < mp_ncpus; cpu++) { @@ -197,11 +203,17 @@ pmap_remap_lowptdi(false); #endif - /* restore the warmstart vector */ - *(uint32_t *)WARMBOOT_OFF = mpbioswarmvec; +#ifdef __amd64__ + if (!efi_boot) { +#endif + /* restore the warmstart vector */ + *(uint32_t *)WARMBOOT_OFF = mpbioswarmvec; - outb(CMOS_REG, BIOS_RESET); - outb(CMOS_DATA, mpbiosreason); + outb(CMOS_REG, BIOS_RESET); + outb(CMOS_DATA, mpbiosreason); +#ifdef __amd64__ + } +#endif } #endif @@ -411,12 +423,12 @@ void acpi_install_wakeup_handler(struct acpi_softc *sc) { - static void *wakeaddr; - void *wakepages[ACPI_WAKEPAGES]; + static void *wakeaddr; + void *wakepages[ACPI_WAKEPAGES]; #ifdef __amd64__ - uint64_t *pt5, *pt4, *pt3, *pt2; - vm_paddr_t pt5pa, pt4pa, pt3pa, pt2pa; - int i; + uint64_t *pt5, *pt4, *pt3, *pt2_0, *pt2_1, *pt2_2, *pt2_3; + vm_paddr_t pt5pa, pt4pa, pt3pa, pt2_0pa, pt2_1pa, pt2_2pa, pt2_3pa; + int i; #endif if (wakeaddr != NULL) @@ -431,15 +443,21 @@ #ifdef __amd64__ if (la57) { - pt5 = wakepages[4]; + pt5 = wakepages[7]; pt5pa = vtophys(pt5); } pt4 = wakepages[1]; pt3 = wakepages[2]; - pt2 = wakepages[3]; + pt2_0 = wakepages[3]; + pt2_1 = wakepages[4]; + pt2_2 = wakepages[5]; + pt2_3 = wakepages[6]; pt4pa = vtophys(pt4); pt3pa = vtophys(pt3); - pt2pa = vtophys(pt2); + pt2_0pa = vtophys(pt2_0); + pt2_1pa = vtophys(pt2_1); + pt2_2pa = vtophys(pt2_2); + pt2_3pa = vtophys(pt2_3); #endif bcopy(wakecode, (void *)sc->acpi_wakeaddr, sizeof(wakecode)); @@ -461,31 +479,41 @@ #ifndef __amd64__ WAKECODE_FIXUP(wakeup_cr3, register_t, pmap_get_kcr3()); #else /* __amd64__ */ - /* Create the initial 1GB replicated page tables */ - 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 - * to the same level 3 page - */ - pt4[i] = (uint64_t)pt3pa; - pt4[i] |= PG_V | PG_RW | PG_U; - - /* - * Each slot of the level 3 pages points - * to the same level 2 page - */ - pt3[i] = (uint64_t)pt2pa; - pt3[i] |= PG_V | PG_RW | PG_U; + /* Create 1:1 mapping for the low 4G */ + if (la57) { + pt5[0] = (uint64_t)pt4pa; + pt5[0] |= PG_V | PG_RW | PG_U; + } - /* The level 2 page slots are mapped with 2MB pages for 1GB. */ - pt2[i] = i * NBPDR; - pt2[i] |= PG_V | PG_RW | PG_PS | PG_U; + pt4[0] = (uint64_t)pt3pa; + pt4[0] |= PG_V | PG_RW | PG_U; + + pt3[0] = (uint64_t)pt2_0pa; + pt3[0] |= PG_V | PG_RW | PG_U; + pt3[1] = (uint64_t)pt2_1pa; + pt3[1] |= PG_V | PG_RW | PG_U; + pt3[2] = (uint64_t)pt2_2pa; + pt3[2] |= PG_V | PG_RW | PG_U; + pt3[3] = (uint64_t)pt2_3pa; + pt3[3] |= PG_V | PG_RW | PG_U; + + for (i = 0; i < NPDEPG; i++) { + pt2_0[i] = (pd_entry_t)i * NBPDR; + pt2_0[i] |= PG_V | PG_RW | PG_PS | PG_U; + } + for (i = 0; i < NPDEPG; i++) { + pt2_1[i] = (pd_entry_t)NBPDP + i * NBPDR; + pt2_1[i] |= PG_V | PG_RW | PG_PS | PG_U; } + for (i = 0; i < NPDEPG; i++) { + pt2_2[i] = (pd_entry_t)2 * NBPDP + i * NBPDR; + pt2_2[i] |= PG_V | PG_RW | PG_PS | PG_U; + } + for (i = 0; i < NPDEPG; i++) { + pt2_3[i] = (pd_entry_t)3 * NBPDP + i * NBPDR; + pt2_3[i] |= PG_V | PG_RW | PG_PS | PG_U; + } + #endif /* !__amd64__ */ if (bootverbose)