diff --git a/sys/compat/linuxkpi/common/include/linux/vmalloc.h b/sys/compat/linuxkpi/common/include/linux/vmalloc.h --- a/sys/compat/linuxkpi/common/include/linux/vmalloc.h +++ b/sys/compat/linuxkpi/common/include/linux/vmalloc.h @@ -35,8 +35,11 @@ #define VM_MAP 0x0000 #define PAGE_KERNEL 0x0000 +#define vmap_pfn(...) linuxkpi_vmap_pfn(__VA_ARGS__) + void *vmap(struct page **pages, unsigned int count, unsigned long flags, int prot); +void *linuxkpi_vmap_pfn(unsigned long *pfns, unsigned int count, int prot); void vunmap(void *addr); #endif /* _LINUXKPI_LINUX_VMALLOC_H_ */ diff --git a/sys/compat/linuxkpi/common/src/linux_page.c b/sys/compat/linuxkpi/common/src/linux_page.c --- a/sys/compat/linuxkpi/common/src/linux_page.c +++ b/sys/compat/linuxkpi/common/src/linux_page.c @@ -342,6 +342,16 @@ int is_vmalloc_addr(const void *addr) { + struct vmmap *vmmap; + + mtx_lock(&vmmaplock); + LIST_FOREACH(vmmap, &vmmaphead[VM_HASH(addr)], vm_next) + if (addr == vmmap->vm_addr) + break; + mtx_unlock(&vmmaplock); + if (vmmap != NULL) + return(1); + return (vtoslab((vm_offset_t)addr & ~UMA_SLAB_MASK) != NULL); } @@ -431,6 +441,28 @@ return ((void *)off); } +void * +linuxkpi_vmap_pfn(unsigned long *pfns, unsigned int count, int prot) +{ +#ifdef __amd64__ + vm_offset_t off; + size_t size; + + size = count * PAGE_SIZE; + off = kva_alloc(size); + if (off == 0) + return (NULL); + vmmap_add((void *)off, size, true); + pmap_qmapdev_attr(off, pfns, count, pgprot2cachemode(prot)); + + return ((void *)off); +#else + /* vmap_pfn() is currently used only by i915kms */ + panic("pmap_qmapdev_attr is not implemented on %s", MACHINE); + return (NULL); +#endif +} + void vunmap(void *addr) {