summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2015-08-25 14:39:40 +0000
committermarcel <marcel@FreeBSD.org>2015-08-25 14:39:40 +0000
commit87b09c366d87c98fd8a35cb0883c973290b0858b (patch)
treee20265d6eec7a4355210772dd496b1c6da24ed19
parentd53cfebe2f15ceb38c2d4e7897391b81ca63387c (diff)
downloadFreeBSD-src-87b09c366d87c98fd8a35cb0883c973290b0858b.zip
FreeBSD-src-87b09c366d87c98fd8a35cb0883c973290b0858b.tar.gz
MFC r286667 & r286723
Better support memory mapped console devices, such as VGA and EFI frame buffers and memory mapped UARTs. PR: 191564, 194952, 202276
-rw-r--r--sys/amd64/amd64/machdep.c61
-rw-r--r--sys/amd64/amd64/pmap.c106
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/dev/vt/hw/efifb/efifb.c30
-rw-r--r--sys/dev/vt/hw/vga/vt_vga.c20
-rw-r--r--sys/dev/vt/hw/vga/vt_vga_reg.h2
-rw-r--r--sys/i386/i386/machdep.c68
-rw-r--r--sys/i386/i386/pmap.c82
-rw-r--r--sys/x86/include/bus.h25
-rw-r--r--sys/x86/x86/bus_machdep.c59
11 files changed, 307 insertions, 148 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..074388b 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;
/*
@@ -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_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 +6332,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);
}
/*
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index ce1fc3a..de4ffd4 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -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
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index da2e20a..d5af459 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -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
diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c
index 05b2d79..35f1cd3 100644
--- a/sys/dev/vt/hw/efifb/efifb.c
+++ b/sys/dev/vt/hw/efifb/efifb.c
@@ -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);
-}
-
diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c
index bce1c61..62e409f 100644
--- a/sys/dev/vt/hw/vga/vt_vga.c
+++ b/sys/dev/vt/hw/vga/vt_vga.c
@@ -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 *vd, const struct vt_window *vw,
/* 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);
diff --git a/sys/dev/vt/hw/vga/vt_vga_reg.h b/sys/dev/vt/hw/vga/vt_vga_reg.h
index 5bfb8ce..cf33a37 100644
--- a/sys/dev/vt/hw/vga/vt_vga_reg.h
+++ b/sys/dev/vt/hw/vga/vt_vga_reg.h
@@ -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
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 3244be6..ab543fe 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -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);
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 4e09a90..540eb65 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -232,6 +232,18 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RDTUN, &pg_ps_enabled, 0,
#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, void *base, int npages)
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_bits)
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_t size, int mode)
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 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 (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);
}
/*
diff --git a/sys/x86/include/bus.h b/sys/x86/include/bus.h
index ced90d5..91de8cb 100644
--- a/sys/x86/include/bus.h
+++ b/sys/x86/include/bus.h
@@ -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.
diff --git a/sys/x86/x86/bus_machdep.c b/sys/x86/x86/bus_machdep.c
new file mode 100644
index 0000000..a629a81
--- /dev/null
+++ b/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);
+}
OpenPOWER on IntegriCloud