summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2015-08-26 09:57:18 -0300
committerRenato Botelho <renato@netgate.com>2015-08-26 09:57:18 -0300
commitdb675751fbe2719e40d2d9e7ca50d71ac7871b1d (patch)
tree439ea42c110371603c2eb536c881c81d6f9a8c46 /sys/amd64
parent3a1ead7396ada9e53eaee9dd7d1a1db12690488a (diff)
parente3e10fb92a1524019f130fd5982a6694f2cc3741 (diff)
downloadFreeBSD-src-db675751fbe2719e40d2d9e7ca50d71ac7871b1d.zip
FreeBSD-src-db675751fbe2719e40d2d9e7ca50d71ac7871b1d.tar.gz
Merge branch 'stable/10' into devel
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/machdep.c61
-rw-r--r--sys/amd64/amd64/pmap.c114
2 files changed, 127 insertions, 48 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 51f5988..83b5e65 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1931,38 +1931,6 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
MODINFO_METADATA | MODINFOMD_EFI_MAP) != NULL)
vty_set_preferred(VTY_VT);
- /*
- * Initialize the console before we print anything out.
- */
- cninit();
-
-#ifdef DEV_ISA
-#ifdef DEV_ATPIC
- elcr_probe();
- atpic_startup();
-#else
- /* Reset and mask the atpics and leave them shut down. */
- atpic_reset();
-
- /*
- * Point the ICU spurious interrupt vectors at the APIC spurious
- * interrupt handler.
- */
- setidt(IDT_IO_INTS + 7, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
- setidt(IDT_IO_INTS + 15, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
-#endif
-#else
-#error "have you forgotten the isa device?";
-#endif
-
- kdb_init();
-
-#ifdef KDB
- if (boothowto & RB_KDB)
- kdb_enter(KDB_WHY_BOOTFLAGS,
- "Boot flags requested debugger");
-#endif
-
identify_cpu(); /* Final stage of CPU initialization */
initializecpu(); /* Initialize CPU registers */
initializecpucache();
@@ -2000,6 +1968,35 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
/* now running on new page tables, configured,and u/iom is accessible */
+ cninit();
+
+#ifdef DEV_ISA
+#ifdef DEV_ATPIC
+ elcr_probe();
+ atpic_startup();
+#else
+ /* Reset and mask the atpics and leave them shut down. */
+ atpic_reset();
+
+ /*
+ * Point the ICU spurious interrupt vectors at the APIC spurious
+ * interrupt handler.
+ */
+ setidt(IDT_IO_INTS + 7, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
+ setidt(IDT_IO_INTS + 15, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
+#endif
+#else
+#error "have you forgotten the isa device?";
+#endif
+
+ kdb_init();
+
+#ifdef KDB
+ if (boothowto & RB_KDB)
+ kdb_enter(KDB_WHY_BOOTFLAGS,
+ "Boot flags requested debugger");
+#endif
+
msgbufinit(msgbufp, msgbufsize);
fpuinit();
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 9e3be79..b47e97c 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -360,6 +360,18 @@ static u_int64_t DMPDphys; /* phys addr of direct mapped level 2 */
static u_int64_t DMPDPphys; /* phys addr of direct mapped level 3 */
static int ndmpdpphys; /* number of DMPDPphys pages */
+/*
+ * pmap_mapdev support pre initialization (i.e. console)
+ */
+#define PMAP_PREINIT_MAPPING_COUNT 8
+static struct pmap_preinit_mapping {
+ vm_paddr_t pa;
+ vm_offset_t va;
+ vm_size_t sz;
+ int mode;
+} pmap_preinit_mapping[PMAP_PREINIT_MAPPING_COUNT];
+static int pmap_initialized;
+
static struct rwlock_padalign pvh_global_lock;
/*
@@ -689,8 +701,14 @@ nkpt_init(vm_paddr_t addr)
* pmap_growkernel() will need to allocate page table pages to map
* the entire 512GB of KVA space which is an unnecessary tax on
* physical memory.
+ *
+ * Secondly, device memory mapped as part of setting up the low-
+ * level console(s) is taken from KVA, starting at virtual_avail.
+ * This is because cninit() is called after pmap_bootstrap() but
+ * before vm_init() and pmap_init(). 20MB for a frame buffer is
+ * not uncommon.
*/
- pt_pages += 8; /* 16MB additional slop for kernel modules */
+ pt_pages += 32; /* 64MB additional slop. */
#endif
nkpt = pt_pages;
}
@@ -1014,6 +1032,7 @@ pmap_page_init(vm_page_t m)
void
pmap_init(void)
{
+ struct pmap_preinit_mapping *ppim;
vm_page_t mpte;
vm_size_t s;
int i, pv_npg;
@@ -1085,6 +1104,22 @@ pmap_init(void)
mtx_init(&cpage_lock, "cpage", NULL, MTX_DEF);
cpage_a = kva_alloc(PAGE_SIZE);
cpage_b = kva_alloc(PAGE_SIZE);
+
+ pmap_initialized = 1;
+ for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
+ ppim = pmap_preinit_mapping + i;
+ if (ppim->va == 0)
+ continue;
+ /* Make the direct map consistent */
+ if (ppim->pa < dmaplimit && ppim->pa + ppim->sz < dmaplimit) {
+ (void)pmap_change_attr(PHYS_TO_DMAP(ppim->pa),
+ ppim->sz, ppim->mode);
+ }
+ if (!bootverbose)
+ continue;
+ printf("PPIM %u: PA=%#lx, VA=%#lx, size=%#lx, mode=%#x\n", i,
+ ppim->pa, ppim->va, ppim->sz, ppim->mode);
+ }
}
static SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0,
@@ -6231,24 +6266,54 @@ pmap_pde_attr(pd_entry_t *pde, int cache_bits, int mask)
void *
pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
{
+ struct pmap_preinit_mapping *ppim;
vm_offset_t va, offset;
vm_size_t tmpsize;
+ int i;
- /*
- * If the specified range of physical addresses fits within the direct
- * map window, use the direct map.
- */
- if (pa < dmaplimit && pa + size < dmaplimit) {
- va = PHYS_TO_DMAP(pa);
- if (!pmap_change_attr(va, size, mode))
- return ((void *)va);
- }
offset = pa & PAGE_MASK;
size = round_page(offset + size);
- va = kva_alloc(size);
- if (!va)
- panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
pa = trunc_page(pa);
+
+ if (!pmap_initialized) {
+ va = 0;
+ for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
+ ppim = pmap_preinit_mapping + i;
+ if (ppim->va == 0) {
+ ppim->pa = pa;
+ ppim->sz = size;
+ ppim->mode = mode;
+ ppim->va = virtual_avail;
+ virtual_avail += size;
+ va = ppim->va;
+ break;
+ }
+ }
+ if (va == 0)
+ panic("%s: too many preinit mappings", __func__);
+ } else {
+ /*
+ * If we have a preinit mapping, re-use it.
+ */
+ for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
+ ppim = pmap_preinit_mapping + i;
+ if (ppim->pa == pa && ppim->sz == size &&
+ ppim->mode == mode)
+ return ((void *)(ppim->va + offset));
+ }
+ /*
+ * If the specified range of physical addresses fits within
+ * the direct map window, use the direct map.
+ */
+ if (pa < dmaplimit && pa + size < dmaplimit) {
+ va = PHYS_TO_DMAP(pa);
+ if (!pmap_change_attr(va, size, mode))
+ return ((void *)(va + offset));
+ }
+ va = kva_alloc(size);
+ if (va == 0)
+ panic("%s: Couldn't allocate KVA", __func__);
+ }
for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE)
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
@@ -6273,15 +6338,32 @@ pmap_mapbios(vm_paddr_t pa, vm_size_t size)
void
pmap_unmapdev(vm_offset_t va, vm_size_t size)
{
- vm_offset_t base, offset;
+ struct pmap_preinit_mapping *ppim;
+ vm_offset_t offset;
+ int i;
/* If we gave a direct map region in pmap_mapdev, do nothing */
if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS)
return;
- base = trunc_page(va);
offset = va & PAGE_MASK;
size = round_page(offset + size);
- kva_free(base, size);
+ va = trunc_page(va);
+ for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
+ ppim = pmap_preinit_mapping + i;
+ if (ppim->va == va && ppim->sz == size) {
+ if (pmap_initialized)
+ return;
+ ppim->pa = 0;
+ ppim->va = 0;
+ ppim->sz = 0;
+ ppim->mode = 0;
+ if (va + size == virtual_avail)
+ virtual_avail = va;
+ return;
+ }
+ }
+ if (pmap_initialized)
+ kva_free(va, size);
}
/*
OpenPOWER on IntegriCloud