Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Dec 2025 21:31:44 +0000
From:      Vladimir Kondratyev <wulf@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: df49fd8efa1a - main - LinuxKPI: Implement vmap_pfn
Message-ID:  <69432140.44b43.40043075@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=df49fd8efa1a885089488458df0e7e88c9649c90

commit df49fd8efa1a885089488458df0e7e88c9649c90
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2025-12-17 21:31:11 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2025-12-17 21:31:11 +0000

    LinuxKPI: Implement vmap_pfn
    
    Required by i915kms to support recent discrete graphics cards.
    
    MFC after:      1 week
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D54225
---
 sys/compat/linuxkpi/common/include/linux/vmalloc.h |  3 +
 sys/compat/linuxkpi/common/src/linux_page.c        | 65 ++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/vmalloc.h b/sys/compat/linuxkpi/common/include/linux/vmalloc.h
index 00650a2df9b6..a7f77f090755 100644
--- 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
index 57ca1401b912..82f3a2a4639f 100644
--- a/sys/compat/linuxkpi/common/src/linux_page.c
+++ b/sys/compat/linuxkpi/common/src/linux_page.c
@@ -341,6 +341,16 @@ static struct mtx vmmaplock;
 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);
 }
 
@@ -418,6 +428,61 @@ vmap(struct page **pages, unsigned int count, unsigned long flags, int prot)
 	return ((void *)off);
 }
 
+#define	VMAP_MAX_CHUNK_SIZE (65536U / sizeof(struct vm_page)) /* KMEM_ZMAX */
+
+void *
+linuxkpi_vmap_pfn(unsigned long *pfns, unsigned int count, int prot)
+{
+	vm_page_t m, *ma, fma;
+	vm_offset_t off, coff;
+	vm_paddr_t pa;
+	vm_memattr_t attr;
+	size_t size;
+	unsigned int i, c, chunk;
+
+	size = ptoa(count);
+	off = kva_alloc(size);
+	if (off == 0)
+		return (NULL);
+	vmmap_add((void *)off, size);
+
+	chunk = MIN(count, VMAP_MAX_CHUNK_SIZE);
+	attr = pgprot2cachemode(prot);
+	ma = malloc(chunk * sizeof(vm_page_t), M_TEMP, M_WAITOK | M_ZERO);
+	fma = NULL;
+	c = 0;
+	coff = off;
+	for (i = 0; i < count; i++) {
+		pa = IDX_TO_OFF(pfns[i]);
+		m = PHYS_TO_VM_PAGE(pa);
+		if (m == NULL) {
+			if (fma == NULL)
+				fma = malloc(chunk * sizeof(struct vm_page),
+				    M_TEMP, M_WAITOK | M_ZERO);
+			m = fma + c;
+			vm_page_initfake(m, pa, attr);
+		} else {
+			pmap_page_set_memattr(m, attr);
+		}
+		ma[c] = m;
+		c++;
+		if (c == chunk || i == count - 1) {
+			pmap_qenter(coff, ma, c);
+			if (i == count - 1)
+				break;
+			coff += ptoa(c);
+			c = 0;
+			memset(ma, 0, chunk * sizeof(vm_page_t));
+			if (fma != NULL)
+				memset(fma, 0, chunk * sizeof(struct vm_page));
+		}
+	}
+	free(fma, M_TEMP);
+	free(ma, M_TEMP);
+
+	return ((void *)off);
+}
+
 void
 vunmap(void *addr)
 {


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69432140.44b43.40043075>