svn commit: r287126 - in stable/10/sys: amd64/amd64 conf dev/vt/hw/efifb dev/vt/hw/vga i386/i386 x86/include x86/x86

Marcel Moolenaar marcel at FreeBSD.org
Tue Aug 25 14:39:44 UTC 2015


Author: marcel
Date: Tue Aug 25 14:39:40 2015
New Revision: 287126
URL: https://svnweb.freebsd.org/changeset/base/287126

Log:
  MFC r286667 & r286723
  
  Better support memory mapped console devices, such as VGA and EFI
  frame buffers and memory mapped UARTs.
  
  PR:		191564, 194952, 202276

Added:
  stable/10/sys/x86/x86/bus_machdep.c
     - copied unchanged from r286667, head/sys/x86/x86/bus_machdep.c
Modified:
  stable/10/sys/amd64/amd64/machdep.c
  stable/10/sys/amd64/amd64/pmap.c
  stable/10/sys/conf/files.amd64
  stable/10/sys/conf/files.i386
  stable/10/sys/dev/vt/hw/efifb/efifb.c
  stable/10/sys/dev/vt/hw/vga/vt_vga.c
  stable/10/sys/dev/vt/hw/vga/vt_vga_reg.h
  stable/10/sys/i386/i386/machdep.c
  stable/10/sys/i386/i386/pmap.c
  stable/10/sys/x86/include/bus.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/10/sys/amd64/amd64/machdep.c	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/amd64/amd64/machdep.c	Tue Aug 25 14:39:40 2015	(r287126)
@@ -1931,38 +1931,6 @@ hammer_time(u_int64_t modulep, u_int64_t
 	    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
 
 	/* 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();
 

Modified: stable/10/sys/amd64/amd64/pmap.c
==============================================================================
--- stable/10/sys/amd64/amd64/pmap.c	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/amd64/amd64/pmap.c	Tue Aug 25 14:39:40 2015	(r287126)
@@ -360,6 +360,18 @@ static u_int64_t	DMPDphys;	/* phys addr 
 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;
 
 /*
@@ -1014,6 +1026,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 +1098,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 +6260,54 @@ pmap_pde_attr(pd_entry_t *pde, int cache
 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 +6332,32 @@ pmap_mapbios(vm_paddr_t pa, vm_size_t si
 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);
 }
 
 /*

Modified: stable/10/sys/conf/files.amd64
==============================================================================
--- stable/10/sys/conf/files.amd64	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/conf/files.amd64	Tue Aug 25 14:39:40 2015	(r287126)
@@ -588,6 +588,7 @@ x86/isa/nmi.c			standard
 x86/isa/orm.c			optional	isa
 x86/pci/pci_bus.c		optional	pci
 x86/pci/qpi.c			optional	pci
+x86/x86/bus_machdep.c		standard
 x86/x86/busdma_bounce.c		standard
 x86/x86/busdma_machdep.c	standard
 x86/x86/dump_machdep.c		standard

Modified: stable/10/sys/conf/files.i386
==============================================================================
--- stable/10/sys/conf/files.i386	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/conf/files.i386	Tue Aug 25 14:39:40 2015	(r287126)
@@ -589,6 +589,7 @@ x86/isa/nmi.c			standard
 x86/isa/orm.c			optional isa
 x86/pci/pci_bus.c		optional pci
 x86/pci/qpi.c			optional pci
+x86/x86/bus_machdep.c		standard
 x86/x86/busdma_bounce.c		standard
 x86/x86/busdma_machdep.c	standard
 x86/x86/dump_machdep.c		standard

Modified: stable/10/sys/dev/vt/hw/efifb/efifb.c
==============================================================================
--- stable/10/sys/dev/vt/hw/efifb/efifb.c	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/dev/vt/hw/efifb/efifb.c	Tue Aug 25 14:39:40 2015	(r287126)
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
 
 static vd_init_t vt_efifb_init;
 static vd_probe_t vt_efifb_probe;
-static void vt_efifb_remap(void *efifb_data);
 
 static struct vt_driver vt_efifb_driver = {
 	.vd_name = "efifb",
@@ -73,8 +72,6 @@ static struct vt_driver vt_efifb_driver 
 static struct fb_info local_info;
 VT_DRIVER_DECLARE(vt_efifb, vt_efifb_driver);
 
-SYSINIT(efifb_remap, SI_SUB_KMEM, SI_ORDER_ANY, vt_efifb_remap, &local_info);
-
 static int
 vt_efifb_probe(struct vt_device *vd)
 {
@@ -139,12 +136,8 @@ vt_efifb_init(struct vt_device *vd)
 
 	info->fb_size = info->fb_height * info->fb_stride;
 	info->fb_pbase = efifb->fb_addr;
-	/*
-	 * Use the direct map as a crutch until pmap is available. Once pmap
-	 * is online, the framebuffer will be remapped by vt_efifb_remap()
-	 * using pmap_mapdev_attr().
-	 */
-	info->fb_vbase = PHYS_TO_DMAP(efifb->fb_addr);
+	info->fb_vbase = (intptr_t)pmap_mapdev_attr(info->fb_pbase,
+	    info->fb_size, VM_MEMATTR_WRITE_COMBINING);
 
 	/* Get pixel storage size. */
 	info->fb_bpp = info->fb_stride / info->fb_width * 8;
@@ -160,22 +153,3 @@ vt_efifb_init(struct vt_device *vd)
 
 	return (CN_INTERNAL);
 }
-
-static void
-vt_efifb_remap(void *xinfo)
-{
-	struct fb_info *info = xinfo;
-
-	if (info->fb_pbase == 0)
-		return;
-
-	/*
-	 * Remap as write-combining. This massively improves performance and
-	 * happens very early in kernel initialization, when everything is
-	 * still single-threaded and interrupts are off, so replacing the
-	 * mapping address is safe.
-	 */
-	info->fb_vbase = (intptr_t)pmap_mapdev_attr(info->fb_pbase,
-	    info->fb_size, VM_MEMATTR_WRITE_COMBINING);
-}
-

Modified: stable/10/sys/dev/vt/hw/vga/vt_vga.c
==============================================================================
--- stable/10/sys/dev/vt/hw/vga/vt_vga.c	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/dev/vt/hw/vga/vt_vga.c	Tue Aug 25 14:39:40 2015	(r287126)
@@ -42,13 +42,6 @@ __FBSDID("$FreeBSD$");
 
 #include <machine/bus.h>
 
-#if defined(__amd64__) || defined(__i386__)
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/pmap.h>
-#include <machine/vmparam.h>
-#endif /* __amd64__ || __i386__ */
-
 struct vga_softc {
 	bus_space_tag_t		 vga_fb_tag;
 	bus_space_handle_t	 vga_fb_handle;
@@ -885,9 +878,9 @@ vga_bitblt_text_txtmode(struct vt_device
 			/* Convert colors to VGA attributes. */
 			attr = bg << 4 | fg;
 
-			MEM_WRITE1(sc, 0x18000 + (row * 80 + col) * 2 + 0,
+			MEM_WRITE1(sc, (row * 80 + col) * 2 + 0,
 			    ch);
-			MEM_WRITE1(sc, 0x18000 + (row * 80 + col) * 2 + 1,
+			MEM_WRITE1(sc, (row * 80 + col) * 2 + 1,
 			    attr);
 		}
 	}
@@ -1211,9 +1204,7 @@ vga_init(struct vt_device *vd)
 
 #if defined(__amd64__) || defined(__i386__)
 	sc->vga_fb_tag = X86_BUS_SPACE_MEM;
-	sc->vga_fb_handle = KERNBASE + VGA_MEM_BASE;
 	sc->vga_reg_tag = X86_BUS_SPACE_IO;
-	sc->vga_reg_handle = VGA_REG_BASE;
 #elif defined(__ia64__)
 	sc->vga_fb_tag = IA64_BUS_SPACE_MEM;
 	sc->vga_fb_handle = IA64_PHYS_TO_RR6(VGA_MEM_BASE);
@@ -1223,14 +1214,21 @@ vga_init(struct vt_device *vd)
 # error "Architecture not yet supported!"
 #endif
 
+	bus_space_map(sc->vga_reg_tag, VGA_REG_BASE, VGA_REG_SIZE, 0,
+	    &sc->vga_reg_handle);
+
 	TUNABLE_INT_FETCH("hw.vga.textmode", &textmode);
 	if (textmode) {
 		vd->vd_flags |= VDF_TEXTMODE;
 		vd->vd_width = 80;
 		vd->vd_height = 25;
+		bus_space_map(sc->vga_fb_tag, VGA_TXT_BASE, VGA_TXT_SIZE, 0,
+		    &sc->vga_fb_handle);
 	} else {
 		vd->vd_width = VT_VGA_WIDTH;
 		vd->vd_height = VT_VGA_HEIGHT;
+		bus_space_map(sc->vga_fb_tag, VGA_MEM_BASE, VGA_MEM_SIZE, 0,
+		    &sc->vga_fb_handle);
 	}
 	vga_initialize(vd, textmode);
 

Modified: stable/10/sys/dev/vt/hw/vga/vt_vga_reg.h
==============================================================================
--- stable/10/sys/dev/vt/hw/vga/vt_vga_reg.h	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/dev/vt/hw/vga/vt_vga_reg.h	Tue Aug 25 14:39:40 2015	(r287126)
@@ -49,6 +49,8 @@
 
 #define	VGA_MEM_BASE	0xA0000
 #define	VGA_MEM_SIZE	0x10000
+#define	VGA_TXT_BASE	0xB8000
+#define	VGA_TXT_SIZE	0x08000
 #define	VGA_REG_BASE	0x3c0
 #define	VGA_REG_SIZE	0x10+0x0c
 

Modified: stable/10/sys/i386/i386/machdep.c
==============================================================================
--- stable/10/sys/i386/i386/machdep.c	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/i386/i386/machdep.c	Tue Aug 25 14:39:40 2015	(r287126)
@@ -3320,6 +3320,40 @@ init386(first)
 	 */
 	i8254_init();
 
+	finishidentcpu();	/* Final stage of CPU initialization */
+	setidt(IDT_UD, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL,
+	    GSEL(GCODE_SEL, SEL_KPL));
+	setidt(IDT_GP, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL,
+	    GSEL(GCODE_SEL, SEL_KPL));
+	initializecpu();	/* Initialize CPU registers */
+	initializecpucache();
+
+	/* pointer to selector slot for %fs/%gs */
+	PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd);
+
+	dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
+	    dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)];
+	dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
+	    dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
+#if defined(PAE) || defined(PAE_TABLES)
+	dblfault_tss.tss_cr3 = (int)IdlePDPT;
+#else
+	dblfault_tss.tss_cr3 = (int)IdlePTD;
+#endif
+	dblfault_tss.tss_eip = (int)dblfault_handler;
+	dblfault_tss.tss_eflags = PSL_KERNEL;
+	dblfault_tss.tss_ds = dblfault_tss.tss_es =
+	    dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL);
+	dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL);
+	dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
+	dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
+
+	vm86_initialize();
+	getmemsize(first);
+	init_param2(physmem);
+
+	/* now running on new page tables, configured,and u/iom is accessible */
+
 	/*
 	 * Initialize the console before we print anything out.
 	 */
@@ -3361,40 +3395,6 @@ init386(first)
 		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
 #endif
 
-	finishidentcpu();	/* Final stage of CPU initialization */
-	setidt(IDT_UD, &IDTVEC(ill),  SDT_SYS386TGT, SEL_KPL,
-	    GSEL(GCODE_SEL, SEL_KPL));
-	setidt(IDT_GP, &IDTVEC(prot),  SDT_SYS386TGT, SEL_KPL,
-	    GSEL(GCODE_SEL, SEL_KPL));
-	initializecpu();	/* Initialize CPU registers */
-	initializecpucache();
-
-	/* pointer to selector slot for %fs/%gs */
-	PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd);
-
-	dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
-	    dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)];
-	dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
-	    dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
-#if defined(PAE) || defined(PAE_TABLES)
-	dblfault_tss.tss_cr3 = (int)IdlePDPT;
-#else
-	dblfault_tss.tss_cr3 = (int)IdlePTD;
-#endif
-	dblfault_tss.tss_eip = (int)dblfault_handler;
-	dblfault_tss.tss_eflags = PSL_KERNEL;
-	dblfault_tss.tss_ds = dblfault_tss.tss_es =
-	    dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL);
-	dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL);
-	dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
-	dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
-
-	vm86_initialize();
-	getmemsize(first);
-	init_param2(physmem);
-
-	/* now running on new page tables, configured,and u/iom is accessible */
-
 	msgbufinit(msgbufp, msgbufsize);
 #ifdef DEV_NPX
 	npxinit(true);

Modified: stable/10/sys/i386/i386/pmap.c
==============================================================================
--- stable/10/sys/i386/i386/pmap.c	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/i386/i386/pmap.c	Tue Aug 25 14:39:40 2015	(r287126)
@@ -232,6 +232,18 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_ena
 #define	PAT_INDEX_SIZE	8
 static int pat_index[PAT_INDEX_SIZE];	/* cache mode to PAT index conversion */
 
+/*
+ * 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;
 
 /*
@@ -731,6 +743,7 @@ pmap_ptelist_init(vm_offset_t *head, voi
 void
 pmap_init(void)
 {
+	struct pmap_preinit_mapping *ppim;
 	vm_page_t mpte;
 	vm_size_t s;
 	int i, pv_npg;
@@ -814,6 +827,17 @@ pmap_init(void)
 	    UMA_ZONE_VM | UMA_ZONE_NOFREE);
 	uma_zone_set_allocf(pdptzone, pmap_pdpt_allocf);
 #endif
+
+	pmap_initialized = 1;
+	if (!bootverbose)
+		return;
+	for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) {
+		ppim = pmap_preinit_mapping + i;
+		if (ppim->va == 0)
+			continue;
+		printf("PPIM %u: PA=%#jx, VA=%#x, size=%#x, mode=%#x\n", i,
+		    (uintmax_t)ppim->pa, ppim->va, ppim->sz, ppim->mode);
+	}
 }
 
 
@@ -5162,8 +5186,10 @@ pmap_pde_attr(pd_entry_t *pde, int cache
 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;
 
 	offset = pa & PAGE_MASK;
 	size = round_page(offset + size);
@@ -5171,11 +5197,36 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_
 
 	if (pa < KERNLOAD && pa + size <= KERNLOAD)
 		va = KERNBASE + pa;
-	else
+	else 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));
+		}
 		va = kva_alloc(size);
-	if (!va)
-		panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
-
+		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);
@@ -5200,14 +5251,31 @@ pmap_mapbios(vm_paddr_t pa, vm_size_t si
 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 (va >= KERNBASE && va + size <= KERNBASE + KERNLOAD)
 		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);
 }
 
 /*

Modified: stable/10/sys/x86/include/bus.h
==============================================================================
--- stable/10/sys/x86/include/bus.h	Tue Aug 25 09:16:09 2015	(r287125)
+++ stable/10/sys/x86/include/bus.h	Tue Aug 25 14:39:40 2015	(r287126)
@@ -130,32 +130,15 @@
  * Map a region of device bus space into CPU virtual address space.
  */
 
-static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
-				  bus_size_t size, int flags,
-				  bus_space_handle_t *bshp);
-
-static __inline int
-bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
-	      bus_size_t size __unused, int flags __unused,
-	      bus_space_handle_t *bshp)
-{
-
-	*bshp = addr;
-	return (0);
-}
+int bus_space_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size,
+    int flags, bus_space_handle_t *bshp);
 
 /*
  * Unmap a region of device bus space.
  */
 
-static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
-				     bus_size_t size);
-
-static __inline void
-bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
-		bus_size_t size __unused)
-{
-}
+void bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t bsh,
+    bus_size_t size);
 
 /*
  * Get a new handle for a subregion of an already-mapped area of bus space.

Copied: stable/10/sys/x86/x86/bus_machdep.c (from r286667, head/sys/x86/x86/bus_machdep.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/10/sys/x86/x86/bus_machdep.c	Tue Aug 25 14:39:40 2015	(r287126, copy of r286667, head/sys/x86/x86/bus_machdep.c)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2015 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <x86/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+/*
+ * Implementation of bus_space_map(), which effectively is a thin
+ * wrapper around pmap_mapdev() for memory mapped I/O space. It's
+ * implemented here and not in <x86/bus.h> to avoid pollution.
+ */
+int
+bus_space_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size,
+    int flags __unused, bus_space_handle_t *bshp)
+{
+
+	*bshp = (tag == X86_BUS_SPACE_MEM)
+	    ? (uintptr_t)pmap_mapdev(addr, size)
+	    : addr;
+	return (0);
+}
+
+void
+bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
+{
+
+	if (tag == X86_BUS_SPACE_MEM)
+		pmap_unmapdev(bsh, size);
+}


More information about the svn-src-all mailing list