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
This commit is contained in:
Nate Lawson 2007-03-14 22:30:02 +00:00
parent 4a36f4ba35
commit 9b0df55b61
2 changed files with 13 additions and 11 deletions

View File

@ -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);

View File

@ -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;
}
/*