diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index b789504e55c5..d922e1100f75 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -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. diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 19a18e916092..a05d68008d82 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -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; } /*