MFC r286667 & r286723
Better support memory mapped console devices, such as VGA and EFI frame buffers and memory mapped UARTs. PR: 191564, 194952, 202276
This commit is contained in:
parent
d53cfebe2f
commit
87b09c366d
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
|
59
sys/x86/x86/bus_machdep.c
Normal file
59
sys/x86/x86/bus_machdep.c
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user