In order to satisfy ACPI's need for an identity mapping, modify the

temporary mapping created by locore so that the lowest two to four
megabytes can become a permanent identity mapping.  This implementation
avoids any use of a large page mapping.
This commit is contained in:
Alan Cox 2007-03-24 19:53:22 +00:00
parent 1069807f7e
commit 8a5e898d63
2 changed files with 40 additions and 32 deletions

View File

@ -777,21 +777,6 @@ no_kernend:
movl %esi, R(SMPpt) /* relocated to KVM space */
#endif /* SMP */
/* Map page zero read-write so bios32 calls can use it */
xorl %eax, %eax
movl $PG_RW,%edx
movl $1,%ecx
fillkptphys(%edx)
/* Map read-only from page 1 to the beginning of the kernel text section */
movl $PAGE_SIZE, %eax
xorl %edx,%edx
movl $R(btext),%ecx
addl $PAGE_MASK,%ecx
subl %eax,%ecx
shrl $PAGE_SHIFT,%ecx
fillkptphys(%edx)
/*
* Enable PSE and PGE.
*/
@ -815,22 +800,21 @@ no_kernend:
#endif
/*
* Write page tables for the kernel starting at btext and
* until the end. Make sure to map read+write. We do this even
* Initialize page table pages mapping physical address zero through the
* end of the kernel. All of the page table entries allow read and write
* access. Write access to the first physical page is required by bios32
* calls, and write access to the first 1 MB of physical memory is required
* by ACPI for implementing suspend and resume. We do this even
* if we've enabled PSE above, we'll just switch the corresponding kernel
* PDEs before we turn on paging.
*
* XXX: We waste some pages here in the PSE case! DON'T BLINDLY REMOVE
* THIS! SMP needs the page table to be there to map the kernel P==V.
*/
movl $R(btext),%eax
addl $PAGE_MASK, %eax
andl $~PAGE_MASK, %eax
movl $PG_RW,%edx
xorl %eax, %eax
movl R(KERNend),%ecx
subl %eax,%ecx
shrl $PAGE_SHIFT,%ecx
fillkptphys(%edx)
fillkptphys($PG_RW)
/* Map page directory. */
#ifdef PAE
@ -901,11 +885,37 @@ no_kernend:
fillkpt(R(SMPptpa), $PG_RW)
#endif /* SMP */
/* install a pde for temporary double map of bottom of VA */
/*
* Create an identity mapping for low physical memory, including the kernel.
* The part of this mapping that covers the first 1 MB of physical memory
* becomes a permanent part of the kernel's address space. The rest of this
* mapping is destroyed in pmap_bootstrap(). Ordinarily, the same page table
* pages are shared by the identity mapping and the kernel's native mapping.
* However, the permanent identity mapping cannot contain PG_G mappings.
* Thus, if the kernel is loaded within the permanent identity mapping, that
* page table page must be duplicated and not shared.
*
* N.B. Due to errata concerning large pages and physical address zero,
* a PG_PS mapping is not used.
*/
movl R(KPTphys), %eax
xorl %ebx, %ebx
movl $NKPT, %ecx
fillkpt(R(IdlePTD), $PG_RW)
#if KERNLOAD < (1 << PDRSHIFT)
testl $PG_G, R(pgeflag)
jz 1f
ALLOCPAGES(1)
movl %esi, %edi
movl R(IdlePTD), %eax
movl (%eax), %esi
movl %edi, (%eax)
movl $PAGE_SIZE, %ecx
cld
rep
movsb
1:
#endif
/*
* For the non-PSE case, install PDEs for PTs covering the KVA.

View File

@ -408,13 +408,18 @@ pmap_bootstrap(vm_paddr_t firstaddr)
*CMAP1 = 0;
/*
* Leave in place 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.
*/
#ifdef XBOX
/* FIXME: This is gross, but needed for the XBOX. Since we are in such
* an early stadium, we cannot yet neatly map video memory ... :-(
* Better fixes are very welcome! */
if (!arch_i386_is_xbox)
#endif
for (i = 0; i < NKPT; i++)
for (i = 1; i < NKPT; i++)
PTD[i] = 0;
/* Initialize the PAT MSR if present. */
@ -422,13 +427,6 @@ pmap_bootstrap(vm_paddr_t firstaddr)
/* 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;
}
/*