summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2007-03-14 22:30:02 +0000
committernjl <njl@FreeBSD.org>2007-03-14 22:30:02 +0000
commit1f769530b3bf6e9a8b728d08281775a547e1fc02 (patch)
treebf7884a58f63dcadffcac49d4c9d455a13e5af56
parent9a87c96269f3588a9094bd93b2c3db26b31394ad (diff)
downloadFreeBSD-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.c17
-rw-r--r--sys/i386/i386/pmap.c7
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;
}
/*
OpenPOWER on IntegriCloud