Fix the undersupported option KERNLOAD, part 2: fix crashes in locore

when KERNLOAD is smaller than NBPDR (not the default) and PG_G is
enabled (the default if the CPU supports it).  This case has relatively
minor problems with coherency of the permanent double mapping, but the
fix in r167869 to improve coherency creates page tables with 3 different
errors so never worked.

The permanent double mapping is fundamentally broken and will be removed
soon.  It fundamentally breaks trapping for null pointers and requires
complications to avoid cache coherency bugs.  It is currently used for
only a single instruction in ACPI resume,

Many fixes VM86 and/or ACPI and/or the double map were attempted near
r1200000.  r167869 attempted to fix cache coherency bugs in an unusual
case, but the bugs were unreachable because older errors in page tables
caused a crash first.

This commit just makes r167869 work as intended.  Part 1 of these fixes
fixed the other errors, but also stopped mapping the PDE for KERNBASE
as a large page, so double mapping of this PDE only causes the same
problems as when KERNLOAD is the default.  Except for the problem of
trapping null pointers, r167869 could be used to fix these problems,
but it is inactive in usual cases.  The only known other problem is
that incoherent permissions for page 0 cause spurious traps in VM86
BIOS calls.

Reviewed by:	kib
This commit is contained in:
Bruce Evans 2017-12-18 11:57:05 +00:00
parent 64874a795e
commit 4a5eb9ac99

View File

@ -790,8 +790,9 @@ no_kernend:
* 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.
* Thus, if the (physical) kernel overlaps the permanent identity mapping
* (and PG_G is enabled), the
* page table for the first PDE 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.
@ -804,10 +805,15 @@ no_kernend:
testl $PG_G, R(pgeflag)
jz 1f
ALLOCPAGES(1)
movl %esi, %eax
movl $1, %ecx
fillkptphys($PG_RW) /* map the new page table in std map */
movl %esi, %edi
movl R(IdlePTD), %eax
movl (%eax), %esi
movl (%eax), %esi /* top bits are 0 for PAE */
andl $~PAGE_MASK, %esi
movl %edi, (%eax)
orl $PG_V | PG_RW, (%eax) /* finish writing new PTD[0] */
movl $PAGE_SIZE, %ecx
cld
rep