diff options
author | Renato Botelho <renato@netgate.com> | 2015-08-26 09:57:18 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2015-08-26 09:57:18 -0300 |
commit | db675751fbe2719e40d2d9e7ca50d71ac7871b1d (patch) | |
tree | 439ea42c110371603c2eb536c881c81d6f9a8c46 /sys/amd64 | |
parent | 3a1ead7396ada9e53eaee9dd7d1a1db12690488a (diff) | |
parent | e3e10fb92a1524019f130fd5982a6694f2cc3741 (diff) | |
download | FreeBSD-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.c | 61 | ||||
-rw-r--r-- | sys/amd64/amd64/pmap.c | 114 |
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); } /* |