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:
parent
1069807f7e
commit
8a5e898d63
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user