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:
parent
4a36f4ba35
commit
9b0df55b61
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user