summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2007-03-24 19:53:22 +0000
committeralc <alc@FreeBSD.org>2007-03-24 19:53:22 +0000
commit8453d04a6b4fe12be044582ed42383daa3d6f9d5 (patch)
treeeff26e1c033c49f6a6088b3ec7835ee5dd23219e /sys/i386
parente39860cf02c6c4a7ff28cd3faa71dfe540a62bdb (diff)
downloadFreeBSD-src-8453d04a6b4fe12be044582ed42383daa3d6f9d5.zip
FreeBSD-src-8453d04a6b4fe12be044582ed42383daa3d6f9d5.tar.gz
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.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/locore.s58
-rw-r--r--sys/i386/i386/pmap.c14
2 files changed, 40 insertions, 32 deletions
diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s
index b789504..d922e11 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 19a18e9..a05d680 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;
}
/*
OpenPOWER on IntegriCloud