diff options
author | njl <njl@FreeBSD.org> | 2007-03-14 22:30:02 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2007-03-14 22:30:02 +0000 |
commit | 1f769530b3bf6e9a8b728d08281775a547e1fc02 (patch) | |
tree | bf7884a58f63dcadffcac49d4c9d455a13e5af56 | |
parent | 9a87c96269f3588a9094bd93b2c3db26b31394ad (diff) | |
download | FreeBSD-src-1f769530b3bf6e9a8b728d08281775a547e1fc02.zip FreeBSD-src-1f769530b3bf6e9a8b728d08281775a547e1fc02.tar.gz |
Create an identity mapping (V=P) super page for the low memory region on
boot. Then, just switch to the kernel pmap when suspending instead of
allocating/freeing our own mapping every time. This should solve a panic
of pmap_remove() being called with interrupts disabled. Thanks to Alan
Cox for developing this patch.
Note: this means that ACPI requires super page (PG_PS) support in the CPU.
This has been present since the Pentium and first documented in the
Pentium Pro. However, it may need to be revisited later.
Submitted by: alc
MFC after: 1 month
-rw-r--r-- | sys/i386/acpica/acpi_wakeup.c | 17 | ||||
-rw-r--r-- | sys/i386/i386/pmap.c | 7 |
2 files changed, 13 insertions, 11 deletions
diff --git a/sys/i386/acpica/acpi_wakeup.c b/sys/i386/acpica/acpi_wakeup.c index 0b5a39e..cc5803d 100644 --- a/sys/i386/acpica/acpi_wakeup.c +++ b/sys/i386/acpica/acpi_wakeup.c @@ -192,11 +192,9 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) { ACPI_STATUS status; struct pmap *pm; - vm_page_t page; int ret; uint32_t cr3; u_long ef; - struct proc *p; ret = 0; if (sc->acpi_wakeaddr == 0) @@ -206,10 +204,12 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) ef = read_eflags(); - /* Create Identity Mapping */ - if ((p = curproc) == NULL) - p = &proc0; - pm = vmspace_pmap(p->p_vmspace); + /* + * Temporarily switch to the kernel pmap because it provides an + * identity mapping (setup at boot) for the low physical memory + * region containing the wakeup code. + */ + pm = kernel_pmap; cr3 = rcr3(); #ifdef PAE load_cr3(vtophys(pm->pm_pdpt)); @@ -217,10 +217,6 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) load_cr3(vtophys(pm->pm_pdir)); #endif - page = PHYS_TO_VM_PAGE(sc->acpi_wakephys); - pmap_enter(pm, sc->acpi_wakephys, page, - VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, 1); - ret_addr = 0; ACPI_DISABLE_IRQS(); if (acpi_savecpu()) { @@ -283,7 +279,6 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) } out: - pmap_remove(pm, sc->acpi_wakephys, sc->acpi_wakephys + PAGE_SIZE); load_cr3(cr3); write_eflags(ef); diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index b2ab67d..18130fa 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -422,6 +422,13 @@ pmap_bootstrap(vm_paddr_t firstaddr, vm_paddr_t loadaddr) /* Turn on PG_G on kernel page(s) */ pmap_set_pg(); + + /* + * Create an identity mapping (virt == phys) for the low 1 MB + * physical memory region that is used by the ACPI wakeup code. + * This mapping must not have PG_G set. + */ + kernel_pmap->pm_pdir[0] = PG_PS | PG_RW | PG_V; } /* |