amd64 acpi_wakeup: map 1:1 whole low 4G for the trampoline page table

This is required since kernel text might be physically located
anywhere below 4G.

PR:	258432
Reported by:	Taku YAMAMOTO <taku@tackymt.homeip.net>
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D31916
This commit is contained in:
Konstantin Belousov 2021-09-11 21:36:38 +03:00
parent ceca8ac1ce
commit db2ba218d9

View File

@ -99,7 +99,7 @@ static void acpi_wakeup_cpus(struct acpi_softc *);
#endif
#ifdef __amd64__
#define ACPI_WAKEPAGES 5
#define ACPI_WAKEPAGES 8
#else
#define ACPI_WAKEPAGES 1
#endif
@ -426,8 +426,8 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
static void *wakeaddr;
void *wakepages[ACPI_WAKEPAGES];
#ifdef __amd64__
uint64_t *pt5, *pt4, *pt3, *pt2;
vm_paddr_t pt5pa, pt4pa, pt3pa, pt2pa;
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
@ -443,15 +443,21 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
#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));
@ -473,31 +479,44 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
#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;
/* 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;
/* Create 1:1 mapping for the low 4G */
if (la57) {
bcopy(kernel_pmap->pm_pmltop, pt5, PAGE_SIZE);
pt5[0] = (uint64_t)pt4pa;
pt5[0] |= PG_V | PG_RW | PG_U;
} else {
bcopy(kernel_pmap->pm_pmltop, pt4, PAGE_SIZE);
}
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)