summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2010-10-05 17:06:51 +0000
committeralc <alc@FreeBSD.org>2010-10-05 17:06:51 +0000
commitbc318f82cfe1aeb52138931a69460858259cc811 (patch)
tree53f3b24e271a3e431308d04cbea885980a5f5dc0 /sys/i386
parent36b4e77eb5958e043d8d97f76fa33c172876e0cc (diff)
downloadFreeBSD-src-bc318f82cfe1aeb52138931a69460858259cc811.zip
FreeBSD-src-bc318f82cfe1aeb52138931a69460858259cc811.tar.gz
Initialize KPTmap in locore so that vm86.c can call vtophys() (or really
pmap_kextract()) before pmap_bootstrap() is called. Document the set of pmap functions that may be called before pmap_bootstrap() is called. Tested by: bde@ Reviewed by: kib@ Discussed with: jhb@ MFC after: 6 weeks
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/locore.s10
-rw-r--r--sys/i386/i386/pmap.c21
-rw-r--r--sys/i386/include/pmap.h34
3 files changed, 50 insertions, 15 deletions
diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s
index 170aaf1..107cbcf 100644
--- a/sys/i386/i386/locore.s
+++ b/sys/i386/i386/locore.s
@@ -104,6 +104,9 @@ IdlePTD: .long 0 /* phys addr of kernel PTD */
IdlePDPT: .long 0 /* phys addr of kernel PDPT */
#endif
+ .globl KPTmap
+KPTmap: .long 0 /* address of kernel page tables */
+
.globl KPTphys
KPTphys: .long 0 /* phys addr of kernel page tables */
@@ -715,6 +718,8 @@ no_kernend:
/* Allocate Kernel Page Tables */
ALLOCPAGES(NKPT)
movl %esi,R(KPTphys)
+ addl $(KERNBASE-(KPTDI<<(PDRSHIFT-PAGE_SHIFT+PTESHIFT))),%esi
+ movl %esi,R(KPTmap)
/* Allocate Page Table Directory */
#ifdef PAE
@@ -778,6 +783,11 @@ no_kernend:
shrl $PAGE_SHIFT,%ecx
fillkptphys($PG_RW)
+/* Map page table pages. */
+ movl R(KPTphys),%eax
+ movl $NKPT,%ecx
+ fillkptphys($PG_RW)
+
/* Map page directory. */
#ifdef PAE
movl R(IdlePDPT), %eax
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 5c2c696..80444e6 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -247,7 +247,7 @@ struct sysmaps {
caddr_t CADDR2;
};
static struct sysmaps sysmaps_pcpu[MAXCPU];
-pt_entry_t *CMAP1 = 0, *KPTmap;
+pt_entry_t *CMAP1 = 0;
static pt_entry_t *CMAP3;
static pd_entry_t *KPTD;
caddr_t CADDR1 = 0, ptvmmap = 0;
@@ -362,12 +362,11 @@ pmap_bootstrap(vm_paddr_t firstaddr)
int i;
/*
- * XXX The calculation of virtual_avail is wrong. It's NKPT*PAGE_SIZE too
- * large. It should instead be correctly calculated in locore.s and
- * not based on 'first' (which is a physical address, not a virtual
- * address, for the start of unused physical memory). The kernel
- * page tables are NOT double mapped and thus should not be included
- * in this calculation.
+ * Initialize the first available kernel virtual address. However,
+ * using "firstaddr" may waste a few pages of the kernel virtual
+ * address space, because locore may not have mapped every physical
+ * page that it allocated. Preferably, locore would provide a first
+ * unused virtual address in addition to "firstaddr".
*/
virtual_avail = (vm_offset_t) KERNBASE + firstaddr;
@@ -437,6 +436,10 @@ pmap_bootstrap(vm_paddr_t firstaddr)
/*
* KPTmap is used by pmap_kextract().
+ *
+ * KPTmap is first initialized by locore. However, that initial
+ * KPTmap can only support NKPT page table pages. Here, a larger
+ * KPTmap is created that can support KVA_PAGES page table pages.
*/
SYSMAP(pt_entry_t *, KPTD, KPTmap, KVA_PAGES)
@@ -1386,6 +1389,8 @@ retry:
/*
* Add a wired page to the kva.
* Note: not SMP coherent.
+ *
+ * This function may be used before pmap_bootstrap() is called.
*/
PMAP_INLINE void
pmap_kenter(vm_offset_t va, vm_paddr_t pa)
@@ -1408,6 +1413,8 @@ pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode)
/*
* Remove a page from the kernel pagetables.
* Note: not SMP coherent.
+ *
+ * This function may be used before pmap_bootstrap() is called.
*/
PMAP_INLINE void
pmap_kremove(vm_offset_t va)
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index 440735b..e62e989 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -191,12 +191,21 @@ extern pdpt_entry_t *IdlePDPT;
extern pd_entry_t *IdlePTD; /* physical address of "Idle" state directory */
/*
- * virtual address to page table entry and
- * to physical address.
- * Note: these work recursively, thus vtopte of a pte will give
- * the corresponding pde that in turn maps it.
+ * Translate a virtual address to the kernel virtual address of its page table
+ * entry (PTE). This can be used recursively. If the address of a PTE as
+ * previously returned by this macro is itself given as the argument, then the
+ * address of the page directory entry (PDE) that maps the PTE will be
+ * returned.
+ *
+ * This macro may be used before pmap_bootstrap() is called.
*/
#define vtopte(va) (PTmap + i386_btop(va))
+
+/*
+ * Translate a virtual address to its physical address.
+ *
+ * This macro may be used before pmap_bootstrap() is called.
+ */
#define vtophys(va) pmap_kextract((vm_offset_t)(va))
#ifdef XEN
@@ -272,14 +281,18 @@ pte_load_store_ma(pt_entry_t *ptep, pt_entry_t v)
* table pages, and not user page table pages, and (2) it provides access to
* a kernel page table page after the corresponding virtual addresses have
* been promoted to a 2/4MB page mapping.
+ *
+ * KPTmap is first initialized by locore to support just NPKT page table
+ * pages. Later, it is reinitialized by pmap_bootstrap() to allow for
+ * expansion of the kernel page table.
*/
extern pt_entry_t *KPTmap;
/*
- * Routine: pmap_kextract
- * Function:
- * Extract the physical page address associated
- * kernel virtual address.
+ * Extract from the kernel page table the physical address that is mapped by
+ * the given virtual address "va".
+ *
+ * This function may be used before pmap_bootstrap() is called.
*/
static __inline vm_paddr_t
pmap_kextract(vm_offset_t va)
@@ -486,6 +499,11 @@ extern vm_offset_t virtual_end;
#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode)
#define pmap_unmapbios(va, sz) pmap_unmapdev((va), (sz))
+/*
+ * Only the following functions or macros may be used before pmap_bootstrap()
+ * is called: pmap_kenter(), pmap_kextract(), pmap_kremove(), vtophys(), and
+ * vtopte().
+ */
void pmap_bootstrap(vm_paddr_t);
int pmap_cache_bits(int mode, boolean_t is_pde);
int pmap_change_attr(vm_offset_t, vm_size_t, int);
OpenPOWER on IntegriCloud