xref: /freebsd/sys/dev/netmap/netmap_mem2.c (revision f5dc2263ab1be8a35a7e27e82103f9ccd41ae584)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (C) 2012-2014 Matteo Landi
5  * Copyright (C) 2012-2016 Luigi Rizzo
6  * Copyright (C) 2012-2016 Giuseppe Lettieri
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *   1. Redistributions of source code must retain the above copyright
13  *      notice, this list of conditions and the following disclaimer.
14  *   2. Redistributions in binary form must reproduce the above copyright
15  *      notice, this list of conditions and the following disclaimer in the
16  *      documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #ifdef linux
32 #include "bsd_glue.h"
33 #endif /* linux */
34 
35 #ifdef __APPLE__
36 #include "osx_glue.h"
37 #endif /* __APPLE__ */
38 
39 #ifdef __FreeBSD__
40 #include <sys/types.h>
41 #include <sys/domainset.h>
42 #include <sys/limits.h>
43 #include <sys/malloc.h>
44 #include <sys/kernel.h>		/* MALLOC_DEFINE */
45 #include <sys/proc.h>
46 #include <vm/vm.h>	/* vtophys */
47 #include <vm/pmap.h>	/* vtophys */
48 #include <sys/socket.h> /* sockaddrs */
49 #include <sys/selinfo.h>
50 #include <sys/sysctl.h>
51 #include <net/if.h>
52 #include <net/if_var.h>
53 #include <net/vnet.h>
54 #include <machine/bus.h>	/* bus_dmamap_* */
55 
56 /* M_NETMAP only used in here */
57 MALLOC_DECLARE(M_NETMAP);
58 MALLOC_DEFINE(M_NETMAP, "netmap", "Network memory map");
59 
60 #endif /* __FreeBSD__ */
61 
62 #ifdef _WIN32
63 #include <win_glue.h>
64 #endif
65 
66 #include <net/netmap.h>
67 #include <dev/netmap/netmap_kern.h>
68 #include <net/netmap_virt.h>
69 #include "netmap_mem2.h"
70 
71 #ifdef _WIN32_USE_SMALL_GENERIC_DEVICES_MEMORY
72 #define NETMAP_BUF_MAX_NUM  8*4096      /* if too big takes too much time to allocate */
73 #else
74 #define NETMAP_BUF_MAX_NUM 20*4096*2	/* large machine */
75 #endif
76 
77 #define NETMAP_POOL_MAX_NAMSZ	32
78 
79 
80 enum {
81 	NETMAP_IF_POOL   = 0,
82 	NETMAP_RING_POOL,
83 	NETMAP_BUF_POOL,
84 	NETMAP_POOLS_NR
85 };
86 
87 
88 struct netmap_obj_params {
89 	u_int size;
90 	u_int num;
91 
92 	u_int last_size;
93 	u_int last_num;
94 };
95 
96 struct netmap_obj_pool {
97 	char name[NETMAP_POOL_MAX_NAMSZ];	/* name of the allocator */
98 
99 	/* ---------------------------------------------------*/
100 	/* these are only meaningful if the pool is finalized */
101 	/* (see 'finalized' field in netmap_mem_d)            */
102 	size_t memtotal;	/* actual total memory space */
103 
104 	struct lut_entry *lut;  /* virt,phys addresses, objtotal entries */
105 	uint32_t *bitmap;       /* one bit per buffer, 1 means free */
106 	uint32_t *invalid_bitmap;/* one bit per buffer, 1 means invalid */
107 	uint32_t bitmap_slots;	/* number of uint32 entries in bitmap */
108 
109 	u_int objtotal;         /* actual total number of objects. */
110 	u_int numclusters;	/* actual number of clusters */
111 	u_int objfree;          /* number of free objects. */
112 
113 	int	alloc_done;	/* we have allocated the memory */
114 	/* ---------------------------------------------------*/
115 
116 	/* limits */
117 	u_int objminsize;	/* minimum object size */
118 	u_int objmaxsize;	/* maximum object size */
119 	u_int nummin;		/* minimum number of objects */
120 	u_int nummax;		/* maximum number of objects */
121 
122 	/* these are changed only by config */
123 	u_int _objtotal;	/* total number of objects */
124 	u_int _objsize;		/* object size */
125 	u_int _clustsize;       /* cluster size */
126 	u_int _clustentries;    /* objects per cluster */
127 	u_int _numclusters;	/* number of clusters */
128 
129 	/* requested values */
130 	u_int r_objtotal;
131 	u_int r_objsize;
132 };
133 
134 #define NMA_LOCK_T		NM_MTX_T
135 #define NMA_LOCK_INIT(n)	NM_MTX_INIT((n)->nm_mtx)
136 #define NMA_LOCK_DESTROY(n)	NM_MTX_DESTROY((n)->nm_mtx)
137 #define NMA_LOCK(n)		NM_MTX_LOCK((n)->nm_mtx)
138 #define NMA_SPINLOCK(n)         NM_MTX_SPINLOCK((n)->nm_mtx)
139 #define NMA_UNLOCK(n)		NM_MTX_UNLOCK((n)->nm_mtx)
140 
141 struct netmap_mem_ops {
142 	int (*nmd_get_lut)(struct netmap_mem_d *, struct netmap_lut*);
143 	int  (*nmd_get_info)(struct netmap_mem_d *, uint64_t *size,
144 			u_int *memflags, uint16_t *id);
145 
146 	vm_paddr_t (*nmd_ofstophys)(struct netmap_mem_d *, vm_ooffset_t);
147 	int (*nmd_config)(struct netmap_mem_d *);
148 	int (*nmd_finalize)(struct netmap_mem_d *, struct netmap_adapter *);
149 	void (*nmd_deref)(struct netmap_mem_d *, struct netmap_adapter *);
150 	ssize_t  (*nmd_if_offset)(struct netmap_mem_d *, const void *vaddr);
151 	void (*nmd_delete)(struct netmap_mem_d *);
152 
153 	struct netmap_if * (*nmd_if_new)(struct netmap_mem_d *,
154 			struct netmap_adapter *, struct netmap_priv_d *);
155 	void (*nmd_if_delete)(struct netmap_mem_d *,
156 			struct netmap_adapter *, struct netmap_if *);
157 	int  (*nmd_rings_create)(struct netmap_mem_d *,
158 			struct netmap_adapter *);
159 	void (*nmd_rings_delete)(struct netmap_mem_d *,
160 			struct netmap_adapter *);
161 };
162 
163 struct netmap_mem_d {
164 	NMA_LOCK_T nm_mtx;  /* protect the allocator */
165 	size_t nm_totalsize; /* shorthand */
166 
167 	u_int flags;
168 #define NETMAP_MEM_FINALIZED	0x1	/* preallocation done */
169 #define NETMAP_MEM_HIDDEN	0x8	/* being prepared */
170 #define NETMAP_MEM_NOMAP	0x10	/* do not map/unmap pdevs */
171 	int lasterr;		/* last error for curr config */
172 	int active;		/* active users */
173 	int refcount;
174 	/* the three allocators */
175 	struct netmap_obj_pool pools[NETMAP_POOLS_NR];
176 
177 	nm_memid_t nm_id;	/* allocator identifier */
178 	int nm_grp;		/* iommu group id */
179 	int nm_numa_domain;	/* local NUMA domain */
180 
181 	/* list of all existing allocators, sorted by nm_id */
182 	struct netmap_mem_d *prev, *next;
183 
184 	const struct netmap_mem_ops *ops;
185 
186 	struct netmap_obj_params params[NETMAP_POOLS_NR];
187 
188 #define NM_MEM_NAMESZ	16
189 	char name[NM_MEM_NAMESZ];
190 };
191 
192 int
193 netmap_mem_get_lut(struct netmap_mem_d *nmd, struct netmap_lut *lut)
194 {
195 	int rv;
196 
197 	NMA_LOCK(nmd);
198 	rv = nmd->ops->nmd_get_lut(nmd, lut);
199 	NMA_UNLOCK(nmd);
200 
201 	return rv;
202 }
203 
204 int
205 netmap_mem_get_info(struct netmap_mem_d *nmd, uint64_t *size,
206 		u_int *memflags, nm_memid_t *memid)
207 {
208 	int rv;
209 
210 	NMA_LOCK(nmd);
211 	rv = nmd->ops->nmd_get_info(nmd, size, memflags, memid);
212 	NMA_UNLOCK(nmd);
213 
214 	return rv;
215 }
216 
217 vm_paddr_t
218 netmap_mem_ofstophys(struct netmap_mem_d *nmd, vm_ooffset_t off)
219 {
220 	vm_paddr_t pa;
221 
222 #if defined(__FreeBSD__)
223 	/* This function is called by netmap_dev_pager_fault(), which holds a
224 	 * non-sleepable lock since FreeBSD 12. Since we cannot sleep, we
225 	 * spin on the trylock. */
226 	NMA_SPINLOCK(nmd);
227 #else
228 	NMA_LOCK(nmd);
229 #endif
230 	pa = nmd->ops->nmd_ofstophys(nmd, off);
231 	NMA_UNLOCK(nmd);
232 
233 	return pa;
234 }
235 
236 static int
237 netmap_mem_config(struct netmap_mem_d *nmd)
238 {
239 	if (nmd->active) {
240 		/* already in use. Not fatal, but we
241 		 * cannot change the configuration
242 		 */
243 		return 0;
244 	}
245 
246 	return nmd->ops->nmd_config(nmd);
247 }
248 
249 ssize_t
250 netmap_mem_if_offset(struct netmap_mem_d *nmd, const void *off)
251 {
252 	ssize_t rv;
253 
254 	NMA_LOCK(nmd);
255 	rv = nmd->ops->nmd_if_offset(nmd, off);
256 	NMA_UNLOCK(nmd);
257 
258 	return rv;
259 }
260 
261 static void
262 netmap_mem_delete(struct netmap_mem_d *nmd)
263 {
264 	nmd->ops->nmd_delete(nmd);
265 }
266 
267 struct netmap_if *
268 netmap_mem_if_new(struct netmap_adapter *na, struct netmap_priv_d *priv)
269 {
270 	struct netmap_if *nifp;
271 	struct netmap_mem_d *nmd = na->nm_mem;
272 
273 	NMA_LOCK(nmd);
274 	nifp = nmd->ops->nmd_if_new(nmd, na, priv);
275 	NMA_UNLOCK(nmd);
276 
277 	return nifp;
278 }
279 
280 void
281 netmap_mem_if_delete(struct netmap_adapter *na, struct netmap_if *nif)
282 {
283 	struct netmap_mem_d *nmd = na->nm_mem;
284 
285 	NMA_LOCK(nmd);
286 	nmd->ops->nmd_if_delete(nmd, na, nif);
287 	NMA_UNLOCK(nmd);
288 }
289 
290 int
291 netmap_mem_rings_create(struct netmap_adapter *na)
292 {
293 	int rv;
294 	struct netmap_mem_d *nmd = na->nm_mem;
295 
296 	NMA_LOCK(nmd);
297 	rv = nmd->ops->nmd_rings_create(nmd, na);
298 	NMA_UNLOCK(nmd);
299 
300 	return rv;
301 }
302 
303 void
304 netmap_mem_rings_delete(struct netmap_adapter *na)
305 {
306 	struct netmap_mem_d *nmd = na->nm_mem;
307 
308 	NMA_LOCK(nmd);
309 	nmd->ops->nmd_rings_delete(nmd, na);
310 	NMA_UNLOCK(nmd);
311 }
312 
313 static int netmap_mem_map(struct netmap_obj_pool *, struct netmap_adapter *);
314 static int netmap_mem_unmap(struct netmap_obj_pool *, struct netmap_adapter *);
315 static int nm_mem_check_group(struct netmap_mem_d *, void *);
316 static void nm_mem_release_id(struct netmap_mem_d *);
317 
318 nm_memid_t
319 netmap_mem_get_id(struct netmap_mem_d *nmd)
320 {
321 	return nmd->nm_id;
322 }
323 
324 #ifdef NM_DEBUG_MEM_PUTGET
325 #define NM_DBG_REFC(nmd, func, line)	\
326 	nm_prinf("%s:%d mem[%d:%d] -> %d", func, line, (nmd)->nm_id, (nmd)->nm_grp, (nmd)->refcount);
327 #else
328 #define NM_DBG_REFC(nmd, func, line)
329 #endif
330 
331 /* circular list of all existing allocators */
332 static struct netmap_mem_d *netmap_last_mem_d = &nm_mem;
333 static NM_MTX_T nm_mem_list_lock;
334 
335 struct netmap_mem_d *
336 __netmap_mem_get(struct netmap_mem_d *nmd, const char *func, int line)
337 {
338 	NM_MTX_LOCK(nm_mem_list_lock);
339 	nmd->refcount++;
340 	NM_DBG_REFC(nmd, func, line);
341 	NM_MTX_UNLOCK(nm_mem_list_lock);
342 	return nmd;
343 }
344 
345 void
346 __netmap_mem_put(struct netmap_mem_d *nmd, const char *func, int line)
347 {
348 	int last;
349 	NM_MTX_LOCK(nm_mem_list_lock);
350 	last = (--nmd->refcount == 0);
351 	if (last)
352 		nm_mem_release_id(nmd);
353 	NM_DBG_REFC(nmd, func, line);
354 	NM_MTX_UNLOCK(nm_mem_list_lock);
355 	if (last)
356 		netmap_mem_delete(nmd);
357 }
358 
359 int
360 netmap_mem_finalize(struct netmap_mem_d *nmd, struct netmap_adapter *na)
361 {
362 	int lasterr = 0;
363 	if (nm_mem_check_group(nmd, na->pdev) < 0) {
364 		return ENOMEM;
365 	}
366 
367 	NMA_LOCK(nmd);
368 
369 	if (netmap_mem_config(nmd))
370 		goto out;
371 
372 	nmd->active++;
373 
374 	nmd->lasterr = nmd->ops->nmd_finalize(nmd, na);
375 
376 	if (!nmd->lasterr && !(nmd->flags & NETMAP_MEM_NOMAP)) {
377 		nmd->lasterr = netmap_mem_map(&nmd->pools[NETMAP_BUF_POOL], na);
378 	}
379 
380 out:
381 	lasterr = nmd->lasterr;
382 	NMA_UNLOCK(nmd);
383 
384 	if (lasterr)
385 		netmap_mem_deref(nmd, na);
386 
387 	return lasterr;
388 }
389 
390 static int
391 nm_isset(uint32_t *bitmap, u_int i)
392 {
393 	return bitmap[ (i>>5) ] & ( 1U << (i & 31U) );
394 }
395 
396 
397 static int
398 netmap_init_obj_allocator_bitmap(struct netmap_obj_pool *p)
399 {
400 	u_int n, j;
401 
402 	if (p->bitmap == NULL) {
403 		/* Allocate the bitmap */
404 		n = (p->objtotal + 31) / 32;
405 		p->bitmap = nm_os_malloc(sizeof(p->bitmap[0]) * n);
406 		if (p->bitmap == NULL) {
407 			nm_prerr("Unable to create bitmap (%d entries) for allocator '%s'", (int)n,
408 			    p->name);
409 			return ENOMEM;
410 		}
411 		p->bitmap_slots = n;
412 	} else {
413 		memset(p->bitmap, 0, p->bitmap_slots * sizeof(p->bitmap[0]));
414 	}
415 
416 	p->objfree = 0;
417 	/*
418 	 * Set all the bits in the bitmap that have
419 	 * corresponding buffers to 1 to indicate they are
420 	 * free.
421 	 */
422 	for (j = 0; j < p->objtotal; j++) {
423 		if (p->invalid_bitmap && nm_isset(p->invalid_bitmap, j)) {
424 			if (netmap_debug & NM_DEBUG_MEM)
425 				nm_prinf("skipping %s %d", p->name, j);
426 			continue;
427 		}
428 		p->bitmap[ (j>>5) ] |=  ( 1U << (j & 31U) );
429 		p->objfree++;
430 	}
431 
432 	if (netmap_verbose)
433 		nm_prinf("%s free %u", p->name, p->objfree);
434 	if (p->objfree == 0) {
435 		if (netmap_verbose)
436 			nm_prerr("%s: no objects available", p->name);
437 		return ENOMEM;
438 	}
439 
440 	return 0;
441 }
442 
443 static int
444 netmap_mem_init_bitmaps(struct netmap_mem_d *nmd)
445 {
446 	int i, error = 0;
447 
448 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
449 		struct netmap_obj_pool *p = &nmd->pools[i];
450 
451 		error = netmap_init_obj_allocator_bitmap(p);
452 		if (error)
453 			return error;
454 	}
455 
456 	/*
457 	 * buffers 0 and 1 are reserved
458 	 */
459 	if (nmd->pools[NETMAP_BUF_POOL].objfree < 2) {
460 		nm_prerr("%s: not enough buffers", nmd->pools[NETMAP_BUF_POOL].name);
461 		return ENOMEM;
462 	}
463 
464 	nmd->pools[NETMAP_BUF_POOL].objfree -= 2;
465 	if (nmd->pools[NETMAP_BUF_POOL].bitmap) {
466 		/* XXX This check is a workaround that prevents a
467 		 * NULL pointer crash which currently happens only
468 		 * with ptnetmap guests.
469 		 * Removed shared-info --> is the bug still there? */
470 		nmd->pools[NETMAP_BUF_POOL].bitmap[0] = ~3U;
471 	}
472 	return 0;
473 }
474 
475 int
476 netmap_mem_deref(struct netmap_mem_d *nmd, struct netmap_adapter *na)
477 {
478 	int last_user = 0;
479 	NMA_LOCK(nmd);
480 	if (na->active_fds <= 0 && !(nmd->flags & NETMAP_MEM_NOMAP))
481 		netmap_mem_unmap(&nmd->pools[NETMAP_BUF_POOL], na);
482 	if (nmd->active == 1) {
483 		last_user = 1;
484 		/*
485 		 * Reset the allocator when it falls out of use so that any
486 		 * pool resources leaked by unclean application exits are
487 		 * reclaimed.
488 		 */
489 		netmap_mem_init_bitmaps(nmd);
490 	}
491 	nmd->ops->nmd_deref(nmd, na);
492 
493 	nmd->active--;
494 	if (last_user) {
495 		nmd->lasterr = 0;
496 	}
497 
498 	NMA_UNLOCK(nmd);
499 	return last_user;
500 }
501 
502 
503 /* accessor functions */
504 static int
505 netmap_mem2_get_lut(struct netmap_mem_d *nmd, struct netmap_lut *lut)
506 {
507 	lut->lut = nmd->pools[NETMAP_BUF_POOL].lut;
508 #ifdef __FreeBSD__
509 	lut->plut = lut->lut;
510 #endif
511 	lut->objtotal = nmd->pools[NETMAP_BUF_POOL].objtotal;
512 	lut->objsize = nmd->pools[NETMAP_BUF_POOL]._objsize;
513 
514 	return 0;
515 }
516 
517 static struct netmap_obj_params netmap_min_priv_params[NETMAP_POOLS_NR] = {
518 	[NETMAP_IF_POOL] = {
519 		.size = 1024,
520 		.num  = 2,
521 	},
522 	[NETMAP_RING_POOL] = {
523 		.size = 5*PAGE_SIZE,
524 		.num  = 4,
525 	},
526 	[NETMAP_BUF_POOL] = {
527 		.size = 2048,
528 		.num  = 4098,
529 	},
530 };
531 
532 
533 /*
534  * nm_mem is the memory allocator used for all physical interfaces
535  * running in netmap mode.
536  * Virtual (VALE) ports will have each its own allocator.
537  */
538 extern const struct netmap_mem_ops netmap_mem_global_ops; /* forward */
539 struct netmap_mem_d nm_mem = {	/* Our memory allocator. */
540 	.pools = {
541 		[NETMAP_IF_POOL] = {
542 			.name 	= "netmap_if",
543 			.objminsize = sizeof(struct netmap_if),
544 			.objmaxsize = 4096,
545 			.nummin     = 10,	/* don't be stingy */
546 			.nummax	    = 10000,	/* XXX very large */
547 		},
548 		[NETMAP_RING_POOL] = {
549 			.name 	= "netmap_ring",
550 			.objminsize = sizeof(struct netmap_ring),
551 			.objmaxsize = 32*PAGE_SIZE,
552 			.nummin     = 2,
553 			.nummax	    = 1024,
554 		},
555 		[NETMAP_BUF_POOL] = {
556 			.name	= "netmap_buf",
557 			.objminsize = 64,
558 			.objmaxsize = 65536,
559 			.nummin     = 4,
560 			.nummax	    = 1000000, /* one million! */
561 		},
562 	},
563 
564 	.params = {
565 		[NETMAP_IF_POOL] = {
566 			.size = 1024,
567 			.num  = 100,
568 		},
569 		[NETMAP_RING_POOL] = {
570 			.size = 9*PAGE_SIZE,
571 			.num  = 200,
572 		},
573 		[NETMAP_BUF_POOL] = {
574 			.size = 2048,
575 			.num  = NETMAP_BUF_MAX_NUM,
576 		},
577 	},
578 
579 	.nm_id = 1,
580 	.nm_grp = -1,
581 	.nm_numa_domain = -1,
582 
583 	.prev = &nm_mem,
584 	.next = &nm_mem,
585 
586 	.ops = &netmap_mem_global_ops,
587 
588 	.name = "1"
589 };
590 
591 static struct netmap_mem_d nm_mem_blueprint;
592 
593 /* blueprint for the private memory allocators */
594 /* XXX clang is not happy about using name as a print format */
595 static const struct netmap_mem_d nm_blueprint = {
596 	.pools = {
597 		[NETMAP_IF_POOL] = {
598 			.name 	= "%s_if",
599 			.objminsize = sizeof(struct netmap_if),
600 			.objmaxsize = 4096,
601 			.nummin     = 1,
602 			.nummax	    = 100,
603 		},
604 		[NETMAP_RING_POOL] = {
605 			.name 	= "%s_ring",
606 			.objminsize = sizeof(struct netmap_ring),
607 			.objmaxsize = 32*PAGE_SIZE,
608 			.nummin     = 2,
609 			.nummax	    = 1024,
610 		},
611 		[NETMAP_BUF_POOL] = {
612 			.name	= "%s_buf",
613 			.objminsize = 64,
614 			.objmaxsize = 65536,
615 			.nummin     = 4,
616 			.nummax	    = 1000000, /* one million! */
617 		},
618 	},
619 
620 	.nm_grp = -1,
621 	.nm_numa_domain = -1,
622 
623 	.flags = NETMAP_MEM_PRIVATE,
624 
625 	.ops = &netmap_mem_global_ops,
626 };
627 
628 /* memory allocator related sysctls */
629 
630 #define STRINGIFY(x) #x
631 
632 #define DECLARE_SYSCTLS(id, name)				\
633 	SYSBEGIN(mem2_ ## name);				\
634 	SYSCTL_INT(_dev_netmap, OID_AUTO, name##_size,		\
635 	    CTLFLAG_RWTUN, &nm_mem.params[id].size, 0,		\
636 	    "Requested size of netmap " STRINGIFY(name) "s");	\
637 	SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_size,	\
638 	    CTLFLAG_RD, &nm_mem.pools[id]._objsize, 0,		\
639 	    "Current size of netmap " STRINGIFY(name) "s");	\
640 	SYSCTL_INT(_dev_netmap, OID_AUTO, name##_num,		\
641 	    CTLFLAG_RWTUN, &nm_mem.params[id].num, 0,		\
642 	    "Requested number of netmap " STRINGIFY(name) "s"); \
643 	SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_num,	\
644 	    CTLFLAG_RD, &nm_mem.pools[id].objtotal, 0,		\
645 	    "Current number of netmap " STRINGIFY(name) "s");	\
646 	SYSCTL_INT(_dev_netmap, OID_AUTO, priv_##name##_size,	\
647 	    CTLFLAG_RWTUN, &netmap_min_priv_params[id].size, 0,	\
648 	    "Default size of private netmap " STRINGIFY(name) "s"); \
649 	SYSCTL_INT(_dev_netmap, OID_AUTO, priv_##name##_num,	\
650 	    CTLFLAG_RWTUN, &netmap_min_priv_params[id].num, 0,	\
651 	    "Default number of private netmap " STRINGIFY(name) "s"); \
652 	SYSEND
653 
654 SYSCTL_DECL(_dev_netmap);
655 DECLARE_SYSCTLS(NETMAP_IF_POOL, if);
656 DECLARE_SYSCTLS(NETMAP_RING_POOL, ring);
657 DECLARE_SYSCTLS(NETMAP_BUF_POOL, buf);
658 
659 int netmap_port_numa_affinity = 0;
660 SYSCTL_INT(_dev_netmap, OID_AUTO, port_numa_affinity,
661     CTLFLAG_RDTUN, &netmap_port_numa_affinity, 0,
662     "Use NUMA-local memory for memory pools when possible");
663 
664 /* call with nm_mem_list_lock held */
665 static int
666 nm_mem_assign_id_locked(struct netmap_mem_d *nmd, int grp_id, int domain)
667 {
668 	nm_memid_t id;
669 	struct netmap_mem_d *scan = netmap_last_mem_d;
670 	int error = ENOMEM;
671 
672 	do {
673 		/* we rely on unsigned wrap around */
674 		id = scan->nm_id + 1;
675 		if (id == 0) /* reserve 0 as error value */
676 			id = 1;
677 		scan = scan->next;
678 		if (id != scan->nm_id) {
679 			nmd->nm_id = id;
680 			nmd->nm_grp = grp_id;
681 			nmd->nm_numa_domain = domain;
682 			nmd->prev = scan->prev;
683 			nmd->next = scan;
684 			scan->prev->next = nmd;
685 			scan->prev = nmd;
686 			netmap_last_mem_d = nmd;
687 			nmd->refcount = 1;
688 			NM_DBG_REFC(nmd, __FUNCTION__, __LINE__);
689 			error = 0;
690 			break;
691 		}
692 	} while (scan != netmap_last_mem_d);
693 
694 	return error;
695 }
696 
697 /* call with nm_mem_list_lock *not* held */
698 static int
699 nm_mem_assign_id(struct netmap_mem_d *nmd, int grp_id)
700 {
701 	int ret;
702 
703 	NM_MTX_LOCK(nm_mem_list_lock);
704 	ret = nm_mem_assign_id_locked(nmd, grp_id, -1);
705 	NM_MTX_UNLOCK(nm_mem_list_lock);
706 
707 	return ret;
708 }
709 
710 /* call with nm_mem_list_lock held */
711 static void
712 nm_mem_release_id(struct netmap_mem_d *nmd)
713 {
714 	nmd->prev->next = nmd->next;
715 	nmd->next->prev = nmd->prev;
716 
717 	if (netmap_last_mem_d == nmd)
718 		netmap_last_mem_d = nmd->prev;
719 
720 	nmd->prev = nmd->next = NULL;
721 }
722 
723 struct netmap_mem_d *
724 netmap_mem_find(nm_memid_t id)
725 {
726 	struct netmap_mem_d *nmd;
727 
728 	NM_MTX_LOCK(nm_mem_list_lock);
729 	nmd = netmap_last_mem_d;
730 	do {
731 		if (!(nmd->flags & NETMAP_MEM_HIDDEN) && nmd->nm_id == id) {
732 			nmd->refcount++;
733 			NM_DBG_REFC(nmd, __FUNCTION__, __LINE__);
734 			NM_MTX_UNLOCK(nm_mem_list_lock);
735 			return nmd;
736 		}
737 		nmd = nmd->next;
738 	} while (nmd != netmap_last_mem_d);
739 	NM_MTX_UNLOCK(nm_mem_list_lock);
740 	return NULL;
741 }
742 
743 static int
744 nm_mem_check_group(struct netmap_mem_d *nmd, void *dev)
745 {
746 	int err = 0, id;
747 
748 	/* Skip not hw adapters.
749 	 * Vale port can use particular allocator through vale-ctl -m option
750 	 */
751 	if (!dev)
752 		return 0;
753 	id = nm_iommu_group_id(dev);
754 	if (netmap_debug & NM_DEBUG_MEM)
755 		nm_prinf("iommu_group %d", id);
756 
757 	NMA_LOCK(nmd);
758 
759 	if (nmd->nm_grp != id) {
760 		if (netmap_verbose)
761 			nm_prerr("iommu group mismatch: %d vs %d",
762 					nmd->nm_grp, id);
763 		nmd->lasterr = err = ENOMEM;
764 	}
765 
766 	NMA_UNLOCK(nmd);
767 	return err;
768 }
769 
770 static struct lut_entry *
771 nm_alloc_lut(u_int nobj)
772 {
773 	size_t n = sizeof(struct lut_entry) * nobj;
774 	struct lut_entry *lut;
775 #ifdef linux
776 	lut = vmalloc(n);
777 #else
778 	lut = nm_os_malloc(n);
779 #endif
780 	return lut;
781 }
782 
783 static void
784 nm_free_lut(struct lut_entry *lut, u_int objtotal)
785 {
786 	bzero(lut, sizeof(struct lut_entry) * objtotal);
787 #ifdef linux
788 	vfree(lut);
789 #else
790 	nm_os_free(lut);
791 #endif
792 }
793 
794 #if defined(linux) || defined(_WIN32)
795 static struct plut_entry *
796 nm_alloc_plut(u_int nobj)
797 {
798 	size_t n = sizeof(struct plut_entry) * nobj;
799 	struct plut_entry *lut;
800 	lut = vmalloc(n);
801 	return lut;
802 }
803 
804 static void
805 nm_free_plut(struct plut_entry * lut)
806 {
807 	vfree(lut);
808 }
809 #endif /* linux or _WIN32 */
810 
811 
812 /*
813  * First, find the allocator that contains the requested offset,
814  * then locate the cluster through a lookup table.
815  */
816 static vm_paddr_t
817 netmap_mem2_ofstophys(struct netmap_mem_d* nmd, vm_ooffset_t offset)
818 {
819 	int i;
820 	vm_ooffset_t o = offset;
821 	vm_paddr_t pa;
822 	struct netmap_obj_pool *p;
823 
824 	p = nmd->pools;
825 
826 	for (i = 0; i < NETMAP_POOLS_NR; offset -= p[i].memtotal, i++) {
827 		if (offset >= p[i].memtotal)
828 			continue;
829 		// now lookup the cluster's address
830 #ifndef _WIN32
831 		pa = vtophys(p[i].lut[offset / p[i]._objsize].vaddr) +
832 			offset % p[i]._objsize;
833 #else
834 		pa = vtophys(p[i].lut[offset / p[i]._objsize].vaddr);
835 		pa.QuadPart += offset % p[i]._objsize;
836 #endif
837 		return pa;
838 	}
839 	/* this is only in case of errors */
840 	nm_prerr("invalid ofs 0x%x out of 0x%zx 0x%zx 0x%zx", (u_int)o,
841 		p[NETMAP_IF_POOL].memtotal,
842 		p[NETMAP_IF_POOL].memtotal
843 			+ p[NETMAP_RING_POOL].memtotal,
844 		p[NETMAP_IF_POOL].memtotal
845 			+ p[NETMAP_RING_POOL].memtotal
846 			+ p[NETMAP_BUF_POOL].memtotal);
847 #ifndef _WIN32
848 	return 0; /* bad address */
849 #else
850 	vm_paddr_t res;
851 	res.QuadPart = 0;
852 	return res;
853 #endif
854 }
855 
856 #ifdef _WIN32
857 
858 /*
859  * win32_build_virtual_memory_for_userspace
860  *
861  * This function get all the object making part of the pools and maps
862  * a contiguous virtual memory space for the userspace
863  * It works this way
864  * 1 - allocate a Memory Descriptor List wide as the sum
865  *		of the memory needed for the pools
866  * 2 - cycle all the objects in every pool and for every object do
867  *
868  *		2a - cycle all the objects in every pool, get the list
869  *				of the physical address descriptors
870  *		2b - calculate the offset in the array of pages descriptor in the
871  *				main MDL
872  *		2c - copy the descriptors of the object in the main MDL
873  *
874  * 3 - return the resulting MDL that needs to be mapped in userland
875  *
876  * In this way we will have an MDL that describes all the memory for the
877  * objects in a single object
878 */
879 
880 PMDL
881 win32_build_user_vm_map(struct netmap_mem_d* nmd)
882 {
883 	u_int memflags, ofs = 0;
884 	PMDL mainMdl, tempMdl;
885 	uint64_t memsize;
886 	int i, j;
887 
888 	if (netmap_mem_get_info(nmd, &memsize, &memflags, NULL)) {
889 		nm_prerr("memory not finalised yet");
890 		return NULL;
891 	}
892 
893 	mainMdl = IoAllocateMdl(NULL, memsize, FALSE, FALSE, NULL);
894 	if (mainMdl == NULL) {
895 		nm_prerr("failed to allocate mdl");
896 		return NULL;
897 	}
898 
899 	NMA_LOCK(nmd);
900 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
901 		struct netmap_obj_pool *p = &nmd->pools[i];
902 		int clsz = p->_clustsize;
903 		int clobjs = p->_clustentries; /* objects per cluster */
904 		int mdl_len = sizeof(PFN_NUMBER) * BYTES_TO_PAGES(clsz);
905 		PPFN_NUMBER pSrc, pDst;
906 
907 		/* each pool has a different cluster size so we need to reallocate */
908 		tempMdl = IoAllocateMdl(p->lut[0].vaddr, clsz, FALSE, FALSE, NULL);
909 		if (tempMdl == NULL) {
910 			NMA_UNLOCK(nmd);
911 			nm_prerr("fail to allocate tempMdl");
912 			IoFreeMdl(mainMdl);
913 			return NULL;
914 		}
915 		pSrc = MmGetMdlPfnArray(tempMdl);
916 		/* create one entry per cluster, the lut[] has one entry per object */
917 		for (j = 0; j < p->numclusters; j++, ofs += clsz) {
918 			pDst = &MmGetMdlPfnArray(mainMdl)[BYTES_TO_PAGES(ofs)];
919 			MmInitializeMdl(tempMdl, p->lut[j*clobjs].vaddr, clsz);
920 			MmBuildMdlForNonPagedPool(tempMdl); /* compute physical page addresses */
921 			RtlCopyMemory(pDst, pSrc, mdl_len); /* copy the page descriptors */
922 			mainMdl->MdlFlags = tempMdl->MdlFlags; /* XXX what is in here ? */
923 		}
924 		IoFreeMdl(tempMdl);
925 	}
926 	NMA_UNLOCK(nmd);
927 	return mainMdl;
928 }
929 
930 #endif /* _WIN32 */
931 
932 /*
933  * helper function for OS-specific mmap routines (currently only windows).
934  * Given an nmd and a pool index, returns the cluster size and number of clusters.
935  * Returns 0 if memory is finalised and the pool is valid, otherwise 1.
936  * It should be called under NMA_LOCK(nmd) otherwise the underlying info can change.
937  */
938 
939 int
940 netmap_mem2_get_pool_info(struct netmap_mem_d* nmd, u_int pool, u_int *clustsize, u_int *numclusters)
941 {
942 	if (!nmd || !clustsize || !numclusters || pool >= NETMAP_POOLS_NR)
943 		return 1; /* invalid arguments */
944 	// NMA_LOCK_ASSERT(nmd);
945 	if (!(nmd->flags & NETMAP_MEM_FINALIZED)) {
946 		*clustsize = *numclusters = 0;
947 		return 1; /* not ready yet */
948 	}
949 	*clustsize = nmd->pools[pool]._clustsize;
950 	*numclusters = nmd->pools[pool].numclusters;
951 	return 0; /* success */
952 }
953 
954 static int
955 netmap_mem2_get_info(struct netmap_mem_d* nmd, uint64_t* size,
956 			u_int *memflags, nm_memid_t *id)
957 {
958 	int error = 0;
959 	error = netmap_mem_config(nmd);
960 	if (error)
961 		goto out;
962 	if (size) {
963 		if (nmd->flags & NETMAP_MEM_FINALIZED) {
964 			*size = nmd->nm_totalsize;
965 		} else {
966 			int i;
967 			*size = 0;
968 			for (i = 0; i < NETMAP_POOLS_NR; i++) {
969 				struct netmap_obj_pool *p = nmd->pools + i;
970 				*size += ((size_t)p->_numclusters * (size_t)p->_clustsize);
971 			}
972 		}
973 	}
974 	if (memflags)
975 		*memflags = nmd->flags;
976 	if (id)
977 		*id = nmd->nm_id;
978 out:
979 	return error;
980 }
981 
982 /*
983  * we store objects by kernel address, need to find the offset
984  * within the pool to export the value to userspace.
985  * Algorithm: scan until we find the cluster, then add the
986  * actual offset in the cluster
987  */
988 static ssize_t
989 netmap_obj_offset(struct netmap_obj_pool *p, const void *vaddr)
990 {
991 	int i, k = p->_clustentries, n = p->objtotal;
992 	ssize_t ofs = 0;
993 
994 	for (i = 0; i < n; i += k, ofs += p->_clustsize) {
995 		const char *base = p->lut[i].vaddr;
996 		ssize_t relofs = (const char *) vaddr - base;
997 
998 		if (relofs < 0 || relofs >= p->_clustsize)
999 			continue;
1000 
1001 		ofs = ofs + relofs;
1002 		nm_prdis("%s: return offset %d (cluster %d) for pointer %p",
1003 		    p->name, ofs, i, vaddr);
1004 		return ofs;
1005 	}
1006 	nm_prerr("address %p is not contained inside any cluster (%s)",
1007 	    vaddr, p->name);
1008 	return 0; /* An error occurred */
1009 }
1010 
1011 /* Helper functions which convert virtual addresses to offsets */
1012 #define netmap_if_offset(n, v)					\
1013 	netmap_obj_offset(&(n)->pools[NETMAP_IF_POOL], (v))
1014 
1015 #define netmap_ring_offset(n, v)				\
1016     ((n)->pools[NETMAP_IF_POOL].memtotal + 			\
1017 	netmap_obj_offset(&(n)->pools[NETMAP_RING_POOL], (v)))
1018 
1019 static ssize_t
1020 netmap_mem2_if_offset(struct netmap_mem_d *nmd, const void *addr)
1021 {
1022 	return netmap_if_offset(nmd, addr);
1023 }
1024 
1025 /*
1026  * report the index, and use start position as a hint,
1027  * otherwise buffer allocation becomes terribly expensive.
1028  */
1029 static void *
1030 netmap_obj_malloc(struct netmap_obj_pool *p, u_int len, uint32_t *start, uint32_t *index)
1031 {
1032 	uint32_t i = 0;			/* index in the bitmap */
1033 	uint32_t mask, j = 0;		/* slot counter */
1034 	void *vaddr = NULL;
1035 
1036 	if (len > p->_objsize) {
1037 		nm_prerr("%s request size %d too large", p->name, len);
1038 		return NULL;
1039 	}
1040 
1041 	if (p->objfree == 0) {
1042 		nm_prerr("no more %s objects", p->name);
1043 		return NULL;
1044 	}
1045 	if (start)
1046 		i = *start;
1047 
1048 	/* termination is guaranteed by p->free, but better check bounds on i */
1049 	while (vaddr == NULL && i < p->bitmap_slots)  {
1050 		uint32_t cur = p->bitmap[i];
1051 		if (cur == 0) { /* bitmask is fully used */
1052 			i++;
1053 			continue;
1054 		}
1055 		/* locate a slot */
1056 		for (j = 0, mask = 1; (cur & mask) == 0; j++, mask <<= 1)
1057 			;
1058 
1059 		p->bitmap[i] &= ~mask; /* mark object as in use */
1060 		p->objfree--;
1061 
1062 		vaddr = p->lut[i * 32 + j].vaddr;
1063 		if (index)
1064 			*index = i * 32 + j;
1065 	}
1066 	nm_prdis("%s allocator: allocated object @ [%d][%d]: vaddr %p",p->name, i, j, vaddr);
1067 
1068 	if (start)
1069 		*start = i;
1070 	return vaddr;
1071 }
1072 
1073 
1074 /*
1075  * free by index, not by address.
1076  * XXX should we also cleanup the content ?
1077  */
1078 static int
1079 netmap_obj_free(struct netmap_obj_pool *p, uint32_t j)
1080 {
1081 	uint32_t *ptr, mask;
1082 
1083 	if (j >= p->objtotal) {
1084 		nm_prerr("invalid index %u, max %u", j, p->objtotal);
1085 		return 1;
1086 	}
1087 	ptr = &p->bitmap[j / 32];
1088 	mask = (1 << (j % 32));
1089 	if (*ptr & mask) {
1090 		nm_prerr("ouch, double free on buffer %d", j);
1091 		return 1;
1092 	} else {
1093 		*ptr |= mask;
1094 		p->objfree++;
1095 		return 0;
1096 	}
1097 }
1098 
1099 /*
1100  * free by address. This is slow but is only used for a few
1101  * objects (rings, nifp)
1102  */
1103 static void
1104 netmap_obj_free_va(struct netmap_obj_pool *p, void *vaddr)
1105 {
1106 	u_int i, j, n = p->numclusters;
1107 
1108 	for (i = 0, j = 0; i < n; i++, j += p->_clustentries) {
1109 		void *base = p->lut[i * p->_clustentries].vaddr;
1110 		ssize_t relofs = (ssize_t) vaddr - (ssize_t) base;
1111 
1112 		/* Given address, is out of the scope of the current cluster.*/
1113 		if (base == NULL || vaddr < base || relofs >= p->_clustsize)
1114 			continue;
1115 
1116 		j = j + relofs / p->_objsize;
1117 		/* KASSERT(j != 0, ("Cannot free object 0")); */
1118 		netmap_obj_free(p, j);
1119 		return;
1120 	}
1121 	nm_prerr("address %p is not contained inside any cluster (%s)",
1122 	    vaddr, p->name);
1123 }
1124 
1125 unsigned
1126 netmap_mem_bufsize(struct netmap_mem_d *nmd)
1127 {
1128 	return nmd->pools[NETMAP_BUF_POOL]._objsize;
1129 }
1130 
1131 #define netmap_if_malloc(n, len)	netmap_obj_malloc(&(n)->pools[NETMAP_IF_POOL], len, NULL, NULL)
1132 #define netmap_if_free(n, v)		netmap_obj_free_va(&(n)->pools[NETMAP_IF_POOL], (v))
1133 #define netmap_ring_malloc(n, len)	netmap_obj_malloc(&(n)->pools[NETMAP_RING_POOL], len, NULL, NULL)
1134 #define netmap_ring_free(n, v)		netmap_obj_free_va(&(n)->pools[NETMAP_RING_POOL], (v))
1135 #define netmap_buf_malloc(n, _pos, _index)			\
1136 	netmap_obj_malloc(&(n)->pools[NETMAP_BUF_POOL], netmap_mem_bufsize(n), _pos, _index)
1137 
1138 
1139 #if 0 /* currently unused */
1140 /* Return the index associated to the given packet buffer */
1141 #define netmap_buf_index(n, v)						\
1142     (netmap_obj_offset(&(n)->pools[NETMAP_BUF_POOL], (v)) / NETMAP_BDG_BUF_SIZE(n))
1143 #endif
1144 
1145 /*
1146  * allocate extra buffers in a linked list.
1147  * returns the actual number.
1148  */
1149 uint32_t
1150 netmap_extra_alloc(struct netmap_adapter *na, uint32_t *head, uint32_t n)
1151 {
1152 	struct netmap_mem_d *nmd = na->nm_mem;
1153 	uint32_t i, pos = 0; /* opaque, scan position in the bitmap */
1154 
1155 	NMA_LOCK(nmd);
1156 
1157 	*head = 0;	/* default, 'null' index ie empty list */
1158 	for (i = 0 ; i < n; i++) {
1159 		uint32_t cur = *head;	/* save current head */
1160 		uint32_t *p = netmap_buf_malloc(nmd, &pos, head);
1161 		if (p == NULL) {
1162 			nm_prerr("no more buffers after %d of %d", i, n);
1163 			*head = cur; /* restore */
1164 			break;
1165 		}
1166 		nm_prdis(5, "allocate buffer %d -> %d", *head, cur);
1167 		*p = cur; /* link to previous head */
1168 	}
1169 
1170 	NMA_UNLOCK(nmd);
1171 
1172 	return i;
1173 }
1174 
1175 static void
1176 netmap_extra_free(struct netmap_adapter *na, uint32_t head)
1177 {
1178 	struct lut_entry *lut = na->na_lut.lut;
1179 	struct netmap_mem_d *nmd = na->nm_mem;
1180 	struct netmap_obj_pool *p = &nmd->pools[NETMAP_BUF_POOL];
1181 	uint32_t i, cur, *buf;
1182 
1183 	nm_prdis("freeing the extra list");
1184 	for (i = 0; head >=2 && head < p->objtotal; i++) {
1185 		cur = head;
1186 		buf = lut[head].vaddr;
1187 		head = *buf;
1188 		*buf = 0;
1189 		if (netmap_obj_free(p, cur))
1190 			break;
1191 	}
1192 	if (head != 0)
1193 		nm_prerr("breaking with head %d", head);
1194 	if (netmap_debug & NM_DEBUG_MEM)
1195 		nm_prinf("freed %d buffers", i);
1196 }
1197 
1198 
1199 /* Return nonzero on error */
1200 static int
1201 netmap_new_bufs(struct netmap_mem_d *nmd, struct netmap_slot *slot, u_int n)
1202 {
1203 	struct netmap_obj_pool *p = &nmd->pools[NETMAP_BUF_POOL];
1204 	u_int i = 0;	/* slot counter */
1205 	uint32_t pos = 0;	/* slot in p->bitmap */
1206 	uint32_t index = 0;	/* buffer index */
1207 
1208 	for (i = 0; i < n; i++) {
1209 		void *vaddr = netmap_buf_malloc(nmd, &pos, &index);
1210 		if (vaddr == NULL) {
1211 			nm_prerr("no more buffers after %d of %d", i, n);
1212 			goto cleanup;
1213 		}
1214 		slot[i].buf_idx = index;
1215 		slot[i].len = p->_objsize;
1216 		slot[i].flags = 0;
1217 		slot[i].ptr = 0;
1218 	}
1219 
1220 	nm_prdis("%s: allocated %d buffers, %d available, first at %d", p->name, n, p->objfree, pos);
1221 	return (0);
1222 
1223 cleanup:
1224 	while (i > 0) {
1225 		i--;
1226 		netmap_obj_free(p, slot[i].buf_idx);
1227 	}
1228 	bzero(slot, n * sizeof(slot[0]));
1229 	return (ENOMEM);
1230 }
1231 
1232 static void
1233 netmap_mem_set_ring(struct netmap_mem_d *nmd, struct netmap_slot *slot, u_int n, uint32_t index)
1234 {
1235 	struct netmap_obj_pool *p = &nmd->pools[NETMAP_BUF_POOL];
1236 	u_int i;
1237 
1238 	for (i = 0; i < n; i++) {
1239 		slot[i].buf_idx = index;
1240 		slot[i].len = p->_objsize;
1241 		slot[i].flags = 0;
1242 	}
1243 }
1244 
1245 
1246 static void
1247 netmap_free_buf(struct netmap_mem_d *nmd, uint32_t i)
1248 {
1249 	struct netmap_obj_pool *p = &nmd->pools[NETMAP_BUF_POOL];
1250 
1251 	if (i < 2 || i >= p->objtotal) {
1252 		nm_prerr("Cannot free buf#%d: should be in [2, %d[", i, p->objtotal);
1253 		return;
1254 	}
1255 	netmap_obj_free(p, i);
1256 }
1257 
1258 
1259 static void
1260 netmap_free_bufs(struct netmap_mem_d *nmd, struct netmap_slot *slot, u_int n)
1261 {
1262 	u_int i;
1263 
1264 	for (i = 0; i < n; i++) {
1265 		if (slot[i].buf_idx > 1)
1266 			netmap_free_buf(nmd, slot[i].buf_idx);
1267 	}
1268 	nm_prdis("%s: released some buffers, available: %u",
1269 			p->name, p->objfree);
1270 }
1271 
1272 static void
1273 netmap_reset_obj_allocator(struct netmap_obj_pool *p)
1274 {
1275 
1276 	if (p == NULL)
1277 		return;
1278 	if (p->bitmap)
1279 		nm_os_free(p->bitmap);
1280 	p->bitmap = NULL;
1281 	if (p->invalid_bitmap)
1282 		nm_os_free(p->invalid_bitmap);
1283 	p->invalid_bitmap = NULL;
1284 	if (!p->alloc_done) {
1285 		/* allocation was done by somebody else.
1286 		 * Let them clean up after themselves.
1287 		 */
1288 		return;
1289 	}
1290 	if (p->lut) {
1291 		u_int i;
1292 
1293 		/*
1294 		 * Free each cluster allocated in
1295 		 * netmap_finalize_obj_allocator().  The cluster start
1296 		 * addresses are stored at multiples of p->_clusterentries
1297 		 * in the lut.
1298 		 */
1299 		for (i = 0; i < p->objtotal; i += p->_clustentries) {
1300 			free(p->lut[i].vaddr, M_NETMAP);
1301 		}
1302 		nm_free_lut(p->lut, p->objtotal);
1303 	}
1304 	p->lut = NULL;
1305 	p->objtotal = 0;
1306 	p->memtotal = 0;
1307 	p->numclusters = 0;
1308 	p->objfree = 0;
1309 	p->alloc_done = 0;
1310 }
1311 
1312 /*
1313  * Free all resources related to an allocator.
1314  */
1315 static void
1316 netmap_destroy_obj_allocator(struct netmap_obj_pool *p)
1317 {
1318 	if (p == NULL)
1319 		return;
1320 	netmap_reset_obj_allocator(p);
1321 }
1322 
1323 /*
1324  * We receive a request for objtotal objects, of size objsize each.
1325  * Internally we may round up both numbers, as we allocate objects
1326  * in small clusters multiple of the page size.
1327  * We need to keep track of objtotal and clustentries,
1328  * as they are needed when freeing memory.
1329  *
1330  * XXX note -- userspace needs the buffers to be contiguous,
1331  *	so we cannot afford gaps at the end of a cluster.
1332  */
1333 
1334 
1335 /* call with NMA_LOCK held */
1336 static int
1337 netmap_config_obj_allocator(struct netmap_obj_pool *p, u_int objtotal, u_int objsize)
1338 {
1339 	int i;
1340 	u_int clustsize;	/* the cluster size, multiple of page size */
1341 	u_int clustentries;	/* how many objects per entry */
1342 
1343 	/* we store the current request, so we can
1344 	 * detect configuration changes later */
1345 	p->r_objtotal = objtotal;
1346 	p->r_objsize = objsize;
1347 
1348 #define MAX_CLUSTSIZE	(1<<22)		// 4 MB
1349 #define LINE_ROUND	NM_BUF_ALIGN	// 64
1350 	if (objsize >= MAX_CLUSTSIZE) {
1351 		/* we could do it but there is no point */
1352 		nm_prerr("unsupported allocation for %d bytes", objsize);
1353 		return EINVAL;
1354 	}
1355 	/* make sure objsize is a multiple of LINE_ROUND */
1356 	i = (objsize & (LINE_ROUND - 1));
1357 	if (i) {
1358 		nm_prinf("aligning object by %d bytes", LINE_ROUND - i);
1359 		objsize += LINE_ROUND - i;
1360 	}
1361 	if (objsize < p->objminsize || objsize > p->objmaxsize) {
1362 		nm_prerr("requested objsize %d out of range [%d, %d]",
1363 			objsize, p->objminsize, p->objmaxsize);
1364 		return EINVAL;
1365 	}
1366 	if (objtotal < p->nummin || objtotal > p->nummax) {
1367 		nm_prerr("requested objtotal %d out of range [%d, %d]",
1368 			objtotal, p->nummin, p->nummax);
1369 		return EINVAL;
1370 	}
1371 	/*
1372 	 * Compute number of objects using a brute-force approach:
1373 	 * given a max cluster size,
1374 	 * we try to fill it with objects keeping track of the
1375 	 * wasted space to the next page boundary.
1376 	 */
1377 	for (clustentries = 0, i = 1;; i++) {
1378 		u_int delta, used = i * objsize;
1379 		if (used > MAX_CLUSTSIZE)
1380 			break;
1381 		delta = used % PAGE_SIZE;
1382 		if (delta == 0) { // exact solution
1383 			clustentries = i;
1384 			break;
1385 		}
1386 	}
1387 	/* exact solution not found */
1388 	if (clustentries == 0) {
1389 		nm_prerr("unsupported allocation for %d bytes", objsize);
1390 		return EINVAL;
1391 	}
1392 	/* compute clustsize */
1393 	clustsize = clustentries * objsize;
1394 	if (netmap_debug & NM_DEBUG_MEM)
1395 		nm_prinf("objsize %d clustsize %d objects %d",
1396 			objsize, clustsize, clustentries);
1397 
1398 	/*
1399 	 * The number of clusters is n = ceil(objtotal/clustentries)
1400 	 * objtotal' = n * clustentries
1401 	 */
1402 	p->_clustentries = clustentries;
1403 	p->_clustsize = clustsize;
1404 	p->_numclusters = (objtotal + clustentries - 1) / clustentries;
1405 
1406 	/* actual values (may be larger than requested) */
1407 	p->_objsize = objsize;
1408 	p->_objtotal = p->_numclusters * clustentries;
1409 
1410 	return 0;
1411 }
1412 
1413 /* call with NMA_LOCK held */
1414 static int
1415 netmap_finalize_obj_allocator(struct netmap_mem_d *nmd, struct netmap_obj_pool *p)
1416 {
1417 	int i; /* must be signed */
1418 
1419 	if (p->lut) {
1420 		/* if the lut is already there we assume that also all the
1421 		 * clusters have already been allocated, possibly by somebody
1422 		 * else (e.g., extmem). In the latter case, the alloc_done flag
1423 		 * will remain at zero, so that we will not attempt to
1424 		 * deallocate the clusters by ourselves in
1425 		 * netmap_reset_obj_allocator.
1426 		 */
1427 		return 0;
1428 	}
1429 
1430 	/* optimistically assume we have enough memory */
1431 	p->numclusters = p->_numclusters;
1432 	p->objtotal = p->_objtotal;
1433 	p->alloc_done = 1;
1434 
1435 	p->lut = nm_alloc_lut(p->objtotal);
1436 	if (p->lut == NULL) {
1437 		nm_prerr("Unable to create lookup table for '%s'", p->name);
1438 		goto clean;
1439 	}
1440 
1441 	/*
1442 	 * Allocate clusters, init pointers
1443 	 */
1444 
1445 	for (i = 0; i < (int)p->objtotal;) {
1446 		int lim = i + p->_clustentries;
1447 		char *clust;
1448 
1449 		/*
1450 		 * XXX Note, we only need contigmalloc() for buffers attached
1451 		 * to native interfaces. In all other cases (nifp, netmap rings
1452 		 * and even buffers for VALE ports or emulated interfaces) we
1453 		 * can live with standard malloc, because the hardware will not
1454 		 * access the pages directly.
1455 		 */
1456 		if (nmd->nm_numa_domain == -1) {
1457 			clust = contigmalloc(p->_clustsize, M_NETMAP,
1458 			    M_NOWAIT | M_ZERO, (size_t)0, -1UL, PAGE_SIZE, 0);
1459 		} else {
1460 			struct domainset *ds;
1461 
1462 			ds = DOMAINSET_PREF(nmd->nm_numa_domain);
1463 			clust = contigmalloc_domainset(p->_clustsize, M_NETMAP,
1464 			    ds, M_NOWAIT | M_ZERO, (size_t)0, -1UL, PAGE_SIZE, 0);
1465 		}
1466 		if (clust == NULL) {
1467 			/*
1468 			 * If we get here, there is a severe memory shortage,
1469 			 * so halve the allocated memory to reclaim some.
1470 			 */
1471 			nm_prerr("Unable to create cluster at %d for '%s' allocator",
1472 			    i, p->name);
1473 			if (i < 2) /* nothing to halve */
1474 				goto out;
1475 			lim = i / 2;
1476 			for (i--; i >= lim; i--) {
1477 				if (i % p->_clustentries == 0 && p->lut[i].vaddr)
1478 					free(p->lut[i].vaddr, M_NETMAP);
1479 				p->lut[i].vaddr = NULL;
1480 			}
1481 		out:
1482 			p->objtotal = i;
1483 			/* we may have stopped in the middle of a cluster */
1484 			p->numclusters = (i + p->_clustentries - 1) / p->_clustentries;
1485 			break;
1486 		}
1487 		/*
1488 		 * Set lut state for all buffers in the current cluster.
1489 		 *
1490 		 * [i, lim) is the set of buffer indexes that cover the
1491 		 * current cluster.
1492 		 *
1493 		 * 'clust' is really the address of the current buffer in
1494 		 * the current cluster as we index through it with a stride
1495 		 * of p->_objsize.
1496 		 */
1497 		for (; i < lim; i++, clust += p->_objsize) {
1498 			p->lut[i].vaddr = clust;
1499 #if !defined(linux) && !defined(_WIN32)
1500 			p->lut[i].paddr = vtophys(clust);
1501 #endif
1502 		}
1503 	}
1504 	p->memtotal = (size_t)p->numclusters * (size_t)p->_clustsize;
1505 	if (netmap_verbose)
1506 		nm_prinf("Pre-allocated %d clusters (%d/%zuKB) for '%s'",
1507 		    p->numclusters, p->_clustsize >> 10,
1508 		    p->memtotal >> 10, p->name);
1509 
1510 	return 0;
1511 
1512 clean:
1513 	netmap_reset_obj_allocator(p);
1514 	return ENOMEM;
1515 }
1516 
1517 /* call with lock held */
1518 static int
1519 netmap_mem_params_changed(struct netmap_obj_params* p)
1520 {
1521 	int i, rv = 0;
1522 
1523 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1524 		if (p[i].last_size != p[i].size || p[i].last_num != p[i].num) {
1525 			p[i].last_size = p[i].size;
1526 			p[i].last_num = p[i].num;
1527 			rv = 1;
1528 		}
1529 	}
1530 	return rv;
1531 }
1532 
1533 static void
1534 netmap_mem_reset_all(struct netmap_mem_d *nmd)
1535 {
1536 	int i;
1537 
1538 	if (netmap_debug & NM_DEBUG_MEM)
1539 		nm_prinf("resetting %p", nmd);
1540 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1541 		netmap_reset_obj_allocator(&nmd->pools[i]);
1542 	}
1543 	nmd->flags  &= ~NETMAP_MEM_FINALIZED;
1544 }
1545 
1546 static int
1547 netmap_mem_unmap(struct netmap_obj_pool *p, struct netmap_adapter *na)
1548 {
1549 	int i, lim = p->objtotal;
1550 	struct netmap_lut *lut;
1551 	if (na == NULL || na->pdev == NULL)
1552 		return 0;
1553 
1554 	lut = &na->na_lut;
1555 
1556 
1557 
1558 #if defined(__FreeBSD__)
1559 	/* On FreeBSD mapping and unmapping is performed by the txsync
1560 	 * and rxsync routine, packet by packet. */
1561 	(void)i;
1562 	(void)lim;
1563 	(void)lut;
1564 #elif defined(_WIN32)
1565 	(void)i;
1566 	(void)lim;
1567 	(void)lut;
1568 	nm_prerr("unsupported on Windows");
1569 #else /* linux */
1570 	nm_prdis("unmapping and freeing plut for %s", na->name);
1571 	if (lut->plut == NULL || na->pdev == NULL)
1572 		return 0;
1573 	for (i = 0; i < lim; i += p->_clustentries) {
1574 		if (lut->plut[i].paddr)
1575 			netmap_unload_map(na, (bus_dma_tag_t) na->pdev, &lut->plut[i].paddr, p->_clustsize);
1576 	}
1577 	nm_free_plut(lut->plut);
1578 	lut->plut = NULL;
1579 #endif /* linux */
1580 
1581 	return 0;
1582 }
1583 
1584 static int
1585 netmap_mem_map(struct netmap_obj_pool *p, struct netmap_adapter *na)
1586 {
1587 	int error = 0;
1588 	int i, lim = p->objtotal;
1589 	struct netmap_lut *lut = &na->na_lut;
1590 
1591 	if (na->pdev == NULL)
1592 		return 0;
1593 
1594 #if defined(__FreeBSD__)
1595 	/* On FreeBSD mapping and unmapping is performed by the txsync
1596 	 * and rxsync routine, packet by packet. */
1597 	(void)i;
1598 	(void)lim;
1599 	(void)lut;
1600 #elif defined(_WIN32)
1601 	(void)i;
1602 	(void)lim;
1603 	(void)lut;
1604 	nm_prerr("unsupported on Windows");
1605 #else /* linux */
1606 
1607 	if (lut->plut != NULL) {
1608 		nm_prdis("plut already allocated for %s", na->name);
1609 		return 0;
1610 	}
1611 
1612 	nm_prdis("allocating physical lut for %s", na->name);
1613 	lut->plut = nm_alloc_plut(lim);
1614 	if (lut->plut == NULL) {
1615 		nm_prerr("Failed to allocate physical lut for %s", na->name);
1616 		return ENOMEM;
1617 	}
1618 
1619 	for (i = 0; i < lim; i += p->_clustentries) {
1620 		lut->plut[i].paddr = 0;
1621 	}
1622 
1623 	for (i = 0; i < lim; i += p->_clustentries) {
1624 		int j;
1625 
1626 		if (p->lut[i].vaddr == NULL)
1627 			continue;
1628 
1629 		error = netmap_load_map(na, (bus_dma_tag_t) na->pdev, &lut->plut[i].paddr,
1630 				p->lut[i].vaddr, p->_clustsize);
1631 		if (error) {
1632 			nm_prerr("Failed to map cluster #%d from the %s pool", i, p->name);
1633 			break;
1634 		}
1635 
1636 		for (j = 1; j < p->_clustentries; j++) {
1637 			lut->plut[i + j].paddr = lut->plut[i + j - 1].paddr + p->_objsize;
1638 		}
1639 	}
1640 
1641 	if (error)
1642 		netmap_mem_unmap(p, na);
1643 
1644 #endif /* linux */
1645 
1646 	return error;
1647 }
1648 
1649 static int
1650 netmap_mem_finalize_all(struct netmap_mem_d *nmd)
1651 {
1652 	int i;
1653 	if (nmd->flags & NETMAP_MEM_FINALIZED)
1654 		return 0;
1655 	nmd->lasterr = 0;
1656 	nmd->nm_totalsize = 0;
1657 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1658 		nmd->lasterr = netmap_finalize_obj_allocator(nmd, &nmd->pools[i]);
1659 		if (nmd->lasterr)
1660 			goto error;
1661 		nmd->nm_totalsize += nmd->pools[i].memtotal;
1662 	}
1663 	nmd->nm_totalsize = (nmd->nm_totalsize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
1664 	nmd->lasterr = netmap_mem_init_bitmaps(nmd);
1665 	if (nmd->lasterr)
1666 		goto error;
1667 
1668 	nmd->flags |= NETMAP_MEM_FINALIZED;
1669 
1670 	if (netmap_verbose)
1671 		nm_prinf("interfaces %zd KB, rings %zd KB, buffers %zd MB",
1672 		    nmd->pools[NETMAP_IF_POOL].memtotal >> 10,
1673 		    nmd->pools[NETMAP_RING_POOL].memtotal >> 10,
1674 		    nmd->pools[NETMAP_BUF_POOL].memtotal >> 20);
1675 
1676 	if (netmap_verbose)
1677 		nm_prinf("Free buffers: %d", nmd->pools[NETMAP_BUF_POOL].objfree);
1678 
1679 
1680 	return 0;
1681 error:
1682 	netmap_mem_reset_all(nmd);
1683 	return nmd->lasterr;
1684 }
1685 
1686 /*
1687  * allocator for private memory
1688  */
1689 static void *
1690 _netmap_mem_private_new(size_t size, struct netmap_obj_params *p, int grp_id,
1691 		const struct netmap_mem_ops *ops, uint64_t memtotal, int *perr)
1692 {
1693 	struct netmap_mem_d *d = NULL;
1694 	int i, err = 0;
1695 	int checksz = 0;
1696 
1697 	/* if memtotal is !=0 we check that the request fits the available
1698 	 * memory. Moreover, any surprlus memory is assigned to buffers.
1699 	 */
1700 	checksz = (memtotal > 0);
1701 
1702 	d = nm_os_malloc(size);
1703 	if (d == NULL) {
1704 		err = ENOMEM;
1705 		goto error;
1706 	}
1707 
1708 	*d = nm_blueprint;
1709 	d->ops = ops;
1710 
1711 	err = nm_mem_assign_id(d, grp_id);
1712 	if (err)
1713 		goto error_free;
1714 	snprintf(d->name, NM_MEM_NAMESZ, "%d", d->nm_id);
1715 
1716 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1717 		snprintf(d->pools[i].name, NETMAP_POOL_MAX_NAMSZ,
1718 				nm_blueprint.pools[i].name,
1719 				d->name);
1720 		if (checksz) {
1721 			uint64_t poolsz = (uint64_t)p[i].num * p[i].size;
1722 			if (memtotal < poolsz) {
1723 				nm_prerr("%s: request too large", d->pools[i].name);
1724 				err = ENOMEM;
1725 				goto error_rel_id;
1726 			}
1727 			memtotal -= poolsz;
1728 		}
1729 		d->params[i].num = p[i].num;
1730 		d->params[i].size = p[i].size;
1731 	}
1732 	if (checksz && memtotal > 0) {
1733 		uint64_t sz = d->params[NETMAP_BUF_POOL].size;
1734 		uint64_t n = (memtotal + sz - 1) / sz;
1735 
1736 		if (n) {
1737 			if (netmap_verbose) {
1738 				nm_prinf("%s: adding %llu more buffers",
1739 				    d->pools[NETMAP_BUF_POOL].name,
1740 				    (unsigned long long)n);
1741 			}
1742 			d->params[NETMAP_BUF_POOL].num += n;
1743 		}
1744 	}
1745 
1746 	NMA_LOCK_INIT(d);
1747 
1748 	err = netmap_mem_config(d);
1749 	if (err)
1750 		goto error_destroy_lock;
1751 
1752 	d->flags &= ~NETMAP_MEM_FINALIZED;
1753 
1754 	return d;
1755 
1756 error_destroy_lock:
1757 	NMA_LOCK_DESTROY(d);
1758 error_rel_id:
1759 	nm_mem_release_id(d);
1760 error_free:
1761 	nm_os_free(d);
1762 error:
1763 	if (perr)
1764 		*perr = err;
1765 	return NULL;
1766 }
1767 
1768 struct netmap_mem_d *
1769 netmap_mem_private_new(u_int txr, u_int txd, u_int rxr, u_int rxd,
1770 		u_int extra_bufs, u_int npipes, int *perr)
1771 {
1772 	struct netmap_mem_d *d = NULL;
1773 	struct netmap_obj_params p[NETMAP_POOLS_NR];
1774 	int i;
1775 	u_int v, maxd;
1776 	/* account for the fake host rings */
1777 	txr++;
1778 	rxr++;
1779 
1780 	/* copy the min values */
1781 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1782 		p[i] = netmap_min_priv_params[i];
1783 	}
1784 
1785 	/* possibly increase them to fit user request */
1786 	v = sizeof(struct netmap_if) + sizeof(ssize_t) * (txr + rxr);
1787 	if (p[NETMAP_IF_POOL].size < v)
1788 		p[NETMAP_IF_POOL].size = v;
1789 	v = 2 + 4 * npipes;
1790 	if (p[NETMAP_IF_POOL].num < v)
1791 		p[NETMAP_IF_POOL].num = v;
1792 	maxd = (txd > rxd) ? txd : rxd;
1793 	v = sizeof(struct netmap_ring) + sizeof(struct netmap_slot) * maxd;
1794 	if (p[NETMAP_RING_POOL].size < v)
1795 		p[NETMAP_RING_POOL].size = v;
1796 	/* each pipe endpoint needs two tx rings (1 normal + 1 host, fake)
1797 	 * and two rx rings (again, 1 normal and 1 fake host)
1798 	 */
1799 	v = txr + rxr + 8 * npipes;
1800 	if (p[NETMAP_RING_POOL].num < v)
1801 		p[NETMAP_RING_POOL].num = v;
1802 	/* for each pipe we only need the buffers for the 4 "real" rings.
1803 	 * On the other end, the pipe ring dimension may be different from
1804 	 * the parent port ring dimension. As a compromise, we allocate twice the
1805 	 * space actually needed if the pipe rings were the same size as the parent rings
1806 	 */
1807 	v = (4 * npipes + rxr) * rxd + (4 * npipes + txr) * txd + 2 + extra_bufs;
1808 		/* the +2 is for the tx and rx fake buffers (indices 0 and 1) */
1809 	if (p[NETMAP_BUF_POOL].num < v)
1810 		p[NETMAP_BUF_POOL].num = v;
1811 
1812 	if (netmap_verbose)
1813 		nm_prinf("req if %d*%d ring %d*%d buf %d*%d",
1814 			p[NETMAP_IF_POOL].num,
1815 			p[NETMAP_IF_POOL].size,
1816 			p[NETMAP_RING_POOL].num,
1817 			p[NETMAP_RING_POOL].size,
1818 			p[NETMAP_BUF_POOL].num,
1819 			p[NETMAP_BUF_POOL].size);
1820 
1821 	d = _netmap_mem_private_new(sizeof(*d), p, -1, &netmap_mem_global_ops, 0, perr);
1822 
1823 	return d;
1824 }
1825 
1826 /* Reference IOMMU and NUMA local allocator - find existing or create new,
1827  * for non-hw adapters, fall back to global allocator.
1828  */
1829 struct netmap_mem_d *
1830 netmap_mem_get_allocator(struct netmap_adapter *na)
1831 {
1832 	int i, domain, err, grp_id;
1833 	struct netmap_mem_d *nmd;
1834 
1835 	if (na == NULL || na->pdev == NULL)
1836 		return netmap_mem_get(&nm_mem);
1837 
1838 	domain = nm_numa_domain(na->pdev);
1839 	grp_id = nm_iommu_group_id(na->pdev);
1840 
1841 	NM_MTX_LOCK(nm_mem_list_lock);
1842 	nmd = netmap_last_mem_d;
1843 	do {
1844 		if (!(nmd->flags & NETMAP_MEM_HIDDEN) &&
1845 		    nmd->nm_grp == grp_id && nmd->nm_numa_domain == domain) {
1846 			nmd->refcount++;
1847 			NM_DBG_REFC(nmd, __FUNCTION__, __LINE__);
1848 			NM_MTX_UNLOCK(nm_mem_list_lock);
1849 			return nmd;
1850 		}
1851 		nmd = nmd->next;
1852 	} while (nmd != netmap_last_mem_d);
1853 
1854 	nmd = nm_os_malloc(sizeof(*nmd));
1855 	if (nmd == NULL)
1856 		goto error;
1857 
1858 	*nmd = nm_mem_blueprint;
1859 
1860 	err = nm_mem_assign_id_locked(nmd, grp_id, domain);
1861 	if (err)
1862 		goto error_free;
1863 
1864 	snprintf(nmd->name, sizeof(nmd->name), "%d", nmd->nm_id);
1865 
1866 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1867 		snprintf(nmd->pools[i].name, NETMAP_POOL_MAX_NAMSZ, "%s-%s",
1868 			nm_mem_blueprint.pools[i].name, nmd->name);
1869 	}
1870 
1871 	NMA_LOCK_INIT(nmd);
1872 
1873 	NM_MTX_UNLOCK(nm_mem_list_lock);
1874 	return nmd;
1875 
1876 error_free:
1877 	nm_os_free(nmd);
1878 error:
1879 	NM_MTX_UNLOCK(nm_mem_list_lock);
1880 	return NULL;
1881 }
1882 
1883 /* call with lock held */
1884 static int
1885 netmap_mem2_config(struct netmap_mem_d *nmd)
1886 {
1887 	int i;
1888 
1889 	if (!netmap_mem_params_changed(nmd->params))
1890 		goto out;
1891 
1892 	nm_prdis("reconfiguring");
1893 
1894 	if (nmd->flags & NETMAP_MEM_FINALIZED) {
1895 		/* reset previous allocation */
1896 		for (i = 0; i < NETMAP_POOLS_NR; i++) {
1897 			netmap_reset_obj_allocator(&nmd->pools[i]);
1898 		}
1899 		nmd->flags &= ~NETMAP_MEM_FINALIZED;
1900 	}
1901 
1902 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1903 		nmd->lasterr = netmap_config_obj_allocator(&nmd->pools[i],
1904 				nmd->params[i].num, nmd->params[i].size);
1905 		if (nmd->lasterr)
1906 			goto out;
1907 	}
1908 
1909 out:
1910 
1911 	return nmd->lasterr;
1912 }
1913 
1914 static int
1915 netmap_mem2_finalize(struct netmap_mem_d *nmd, struct netmap_adapter *na)
1916 {
1917 	if (nmd->flags & NETMAP_MEM_FINALIZED)
1918 		goto out;
1919 
1920 	if (netmap_mem_finalize_all(nmd))
1921 		goto out;
1922 
1923 	nmd->lasterr = 0;
1924 
1925 out:
1926 	return nmd->lasterr;
1927 }
1928 
1929 static void
1930 netmap_mem2_delete(struct netmap_mem_d *nmd)
1931 {
1932 	int i;
1933 
1934 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
1935 	    netmap_destroy_obj_allocator(&nmd->pools[i]);
1936 	}
1937 
1938 	NMA_LOCK_DESTROY(nmd);
1939 	if (nmd != &nm_mem)
1940 		nm_os_free(nmd);
1941 }
1942 
1943 #ifdef WITH_EXTMEM
1944 /* doubly linekd list of all existing external allocators */
1945 static struct netmap_mem_ext *netmap_mem_ext_list = NULL;
1946 NM_MTX_T nm_mem_ext_list_lock;
1947 #endif /* WITH_EXTMEM */
1948 
1949 int
1950 netmap_mem_init(void)
1951 {
1952 	nm_mem_blueprint = nm_mem;
1953 	NM_MTX_INIT(nm_mem_list_lock);
1954 	NMA_LOCK_INIT(&nm_mem);
1955 	netmap_mem_get(&nm_mem);
1956 #ifdef WITH_EXTMEM
1957 	NM_MTX_INIT(nm_mem_ext_list_lock);
1958 #endif /* WITH_EXTMEM */
1959 	return (0);
1960 }
1961 
1962 void
1963 netmap_mem_fini(void)
1964 {
1965 	netmap_mem_put(&nm_mem);
1966 }
1967 
1968 static int
1969 netmap_mem_ring_needed(struct netmap_kring *kring)
1970 {
1971 	return kring->ring == NULL &&
1972 		(kring->users > 0 ||
1973 		 (kring->nr_kflags & NKR_NEEDRING));
1974 }
1975 
1976 static int
1977 netmap_mem_ring_todelete(struct netmap_kring *kring)
1978 {
1979 	return kring->ring != NULL &&
1980 		kring->users == 0 &&
1981 		!(kring->nr_kflags & NKR_NEEDRING);
1982 }
1983 
1984 
1985 /* call with NMA_LOCK held *
1986  *
1987  * Allocate netmap rings and buffers for this card
1988  * The rings are contiguous, but have variable size.
1989  * The kring array must follow the layout described
1990  * in netmap_krings_create().
1991  */
1992 static int
1993 netmap_mem2_rings_create(struct netmap_mem_d *nmd, struct netmap_adapter *na)
1994 {
1995 	enum txrx t;
1996 	int error;
1997 
1998 	for_rx_tx(t) {
1999 		u_int i;
2000 
2001 		for (i = 0; i < netmap_all_rings(na, t); i++) {
2002 			struct netmap_kring *kring = NMR(na, t)[i];
2003 			struct netmap_ring *ring = kring->ring;
2004 			u_int len, ndesc;
2005 
2006 			if (!netmap_mem_ring_needed(kring)) {
2007 				/* unneeded, or already created by somebody else */
2008 				if (netmap_debug & NM_DEBUG_MEM)
2009 					nm_prinf("NOT creating ring %s (ring %p, users %d neekring %d)",
2010 						kring->name, ring, kring->users, kring->nr_kflags & NKR_NEEDRING);
2011 				continue;
2012 			}
2013 			if (netmap_debug & NM_DEBUG_MEM)
2014 				nm_prinf("creating %s", kring->name);
2015 			ndesc = kring->nkr_num_slots;
2016 			if (ndesc >= UINT_MAX / sizeof(struct netmap_slot)) {
2017 				error = EINVAL;
2018 				goto cleanup;
2019 			}
2020 			len = ndesc * sizeof(struct netmap_slot);
2021 			if (len + sizeof(struct netmap_ring) < len) {
2022 				error = EINVAL;
2023 				goto cleanup;
2024 			}
2025 			len += sizeof(struct netmap_ring);
2026 			ring = netmap_ring_malloc(nmd, len);
2027 			if (ring == NULL) {
2028 				nm_prerr("Cannot allocate %s_ring", nm_txrx2str(t));
2029 				error = ENOMEM;
2030 				goto cleanup;
2031 			}
2032 			nm_prdis("txring at %p", ring);
2033 			kring->ring = ring;
2034 			*(uint32_t *)(uintptr_t)&ring->num_slots = ndesc;
2035 			*(int64_t *)(uintptr_t)&ring->buf_ofs =
2036 			    (nmd->pools[NETMAP_IF_POOL].memtotal +
2037 				nmd->pools[NETMAP_RING_POOL].memtotal) -
2038 				netmap_ring_offset(nmd, ring);
2039 
2040 			/* copy values from kring */
2041 			ring->head = kring->rhead;
2042 			ring->cur = kring->rcur;
2043 			ring->tail = kring->rtail;
2044 			*(uint32_t *)(uintptr_t)&ring->nr_buf_size =
2045 				netmap_mem_bufsize(nmd);
2046 			nm_prdis("%s h %d c %d t %d", kring->name,
2047 				ring->head, ring->cur, ring->tail);
2048 			nm_prdis("initializing slots for %s_ring", nm_txrx2str(t));
2049 			if (!(kring->nr_kflags & NKR_FAKERING)) {
2050 				/* this is a real ring */
2051 				if (netmap_debug & NM_DEBUG_MEM)
2052 					nm_prinf("allocating buffers for %s", kring->name);
2053 				if (netmap_new_bufs(nmd, ring->slot, ndesc)) {
2054 					nm_prerr(
2055 					    "Cannot allocate buffers for %s_ring",
2056 					    nm_txrx2str(t));
2057 					error = ENOMEM;
2058 					goto cleanup;
2059 				}
2060 			} else {
2061 				/* this is a fake ring, set all indices to 0 */
2062 				if (netmap_debug & NM_DEBUG_MEM)
2063 					nm_prinf("NOT allocating buffers for %s", kring->name);
2064 				netmap_mem_set_ring(nmd, ring->slot, ndesc, 0);
2065 			}
2066 		        /* ring info */
2067 		        *(uint16_t *)(uintptr_t)&ring->ringid = kring->ring_id;
2068 		        *(uint16_t *)(uintptr_t)&ring->dir = kring->tx;
2069 		}
2070 	}
2071 
2072 	return 0;
2073 
2074 cleanup:
2075 	/* we cannot actually cleanup here, since we don't own kring->users
2076 	 * and kring->nr_klags & NKR_NEEDRING. The caller must decrement
2077 	 * the first or zero-out the second, then call netmap_free_rings()
2078 	 * to do the cleanup
2079 	 */
2080 
2081 	return error;
2082 }
2083 
2084 static void
2085 netmap_mem2_rings_delete(struct netmap_mem_d *nmd, struct netmap_adapter *na)
2086 {
2087 	enum txrx t;
2088 
2089 	for_rx_tx(t) {
2090 		u_int i;
2091 		for (i = 0; i < netmap_all_rings(na, t); i++) {
2092 			struct netmap_kring *kring = NMR(na, t)[i];
2093 			struct netmap_ring *ring = kring->ring;
2094 
2095 			if (!netmap_mem_ring_todelete(kring)) {
2096 				if (netmap_debug & NM_DEBUG_MEM)
2097 					nm_prinf("NOT deleting ring %s (ring %p, users %d neekring %d)",
2098 						kring->name, ring, kring->users, kring->nr_kflags & NKR_NEEDRING);
2099 				continue;
2100 			}
2101 			if (netmap_debug & NM_DEBUG_MEM)
2102 				nm_prinf("deleting ring %s", kring->name);
2103 			if (!(kring->nr_kflags & NKR_FAKERING)) {
2104 				nm_prdis("freeing bufs for %s", kring->name);
2105 				netmap_free_bufs(nmd, ring->slot, kring->nkr_num_slots);
2106 			} else {
2107 				nm_prdis("NOT freeing bufs for %s", kring->name);
2108 			}
2109 			netmap_ring_free(nmd, ring);
2110 			kring->ring = NULL;
2111 		}
2112 	}
2113 }
2114 
2115 /* call with NMA_LOCK held */
2116 /*
2117  * Allocate the per-fd structure netmap_if.
2118  *
2119  * We assume that the configuration stored in na
2120  * (number of tx/rx rings and descs) does not change while
2121  * the interface is in netmap mode.
2122  */
2123 static struct netmap_if *
2124 netmap_mem2_if_new(struct netmap_mem_d *nmd,
2125 		struct netmap_adapter *na, struct netmap_priv_d *priv)
2126 {
2127 	struct netmap_if *nifp;
2128 	ssize_t base; /* handy for relative offsets between rings and nifp */
2129 	u_int i, len, n[NR_TXRX], ntot;
2130 	enum txrx t;
2131 
2132 	ntot = 0;
2133 	for_rx_tx(t) {
2134 		/* account for the (eventually fake) host rings */
2135 		n[t] = netmap_all_rings(na, t);
2136 		ntot += n[t];
2137 	}
2138 	/*
2139 	 * the descriptor is followed inline by an array of offsets
2140 	 * to the tx and rx rings in the shared memory region.
2141 	 */
2142 
2143 	len = sizeof(struct netmap_if) + (ntot * sizeof(ssize_t));
2144 	nifp = netmap_if_malloc(nmd, len);
2145 	if (nifp == NULL) {
2146 		return NULL;
2147 	}
2148 
2149 	/* initialize base fields -- override const */
2150 	*(u_int *)(uintptr_t)&nifp->ni_tx_rings = na->num_tx_rings;
2151 	*(u_int *)(uintptr_t)&nifp->ni_rx_rings = na->num_rx_rings;
2152 	*(u_int *)(uintptr_t)&nifp->ni_host_tx_rings =
2153 		(na->num_host_tx_rings ? na->num_host_tx_rings : 1);
2154 	*(u_int *)(uintptr_t)&nifp->ni_host_rx_rings =
2155 		(na->num_host_rx_rings ? na->num_host_rx_rings : 1);
2156 	strlcpy(nifp->ni_name, na->name, sizeof(nifp->ni_name));
2157 
2158 	/*
2159 	 * fill the slots for the rx and tx rings. They contain the offset
2160 	 * between the ring and nifp, so the information is usable in
2161 	 * userspace to reach the ring from the nifp.
2162 	 */
2163 	base = netmap_if_offset(nmd, nifp);
2164 	for (i = 0; i < n[NR_TX]; i++) {
2165 		/* XXX instead of ofs == 0 maybe use the offset of an error
2166 		 * ring, like we do for buffers? */
2167 		ssize_t ofs = 0;
2168 
2169 		if (na->tx_rings[i]->ring != NULL && i >= priv->np_qfirst[NR_TX]
2170 				&& i < priv->np_qlast[NR_TX]) {
2171 			ofs = netmap_ring_offset(nmd,
2172 						 na->tx_rings[i]->ring) - base;
2173 		}
2174 		*(ssize_t *)(uintptr_t)&nifp->ring_ofs[i] = ofs;
2175 	}
2176 	for (i = 0; i < n[NR_RX]; i++) {
2177 		/* XXX instead of ofs == 0 maybe use the offset of an error
2178 		 * ring, like we do for buffers? */
2179 		ssize_t ofs = 0;
2180 
2181 		if (na->rx_rings[i]->ring != NULL && i >= priv->np_qfirst[NR_RX]
2182 				&& i < priv->np_qlast[NR_RX]) {
2183 			ofs = netmap_ring_offset(nmd,
2184 						 na->rx_rings[i]->ring) - base;
2185 		}
2186 		*(ssize_t *)(uintptr_t)&nifp->ring_ofs[i+n[NR_TX]] = ofs;
2187 	}
2188 
2189 	return (nifp);
2190 }
2191 
2192 static void
2193 netmap_mem2_if_delete(struct netmap_mem_d *nmd,
2194 		struct netmap_adapter *na, struct netmap_if *nifp)
2195 {
2196 	if (nifp == NULL)
2197 		/* nothing to do */
2198 		return;
2199 	if (nifp->ni_bufs_head)
2200 		netmap_extra_free(na, nifp->ni_bufs_head);
2201 	netmap_if_free(nmd, nifp);
2202 }
2203 
2204 static void
2205 netmap_mem2_deref(struct netmap_mem_d *nmd, struct netmap_adapter *na)
2206 {
2207 
2208 	if (netmap_debug & NM_DEBUG_MEM)
2209 		nm_prinf("active = %d", nmd->active);
2210 
2211 }
2212 
2213 const struct netmap_mem_ops netmap_mem_global_ops = {
2214 	.nmd_get_lut = netmap_mem2_get_lut,
2215 	.nmd_get_info = netmap_mem2_get_info,
2216 	.nmd_ofstophys = netmap_mem2_ofstophys,
2217 	.nmd_config = netmap_mem2_config,
2218 	.nmd_finalize = netmap_mem2_finalize,
2219 	.nmd_deref = netmap_mem2_deref,
2220 	.nmd_delete = netmap_mem2_delete,
2221 	.nmd_if_offset = netmap_mem2_if_offset,
2222 	.nmd_if_new = netmap_mem2_if_new,
2223 	.nmd_if_delete = netmap_mem2_if_delete,
2224 	.nmd_rings_create = netmap_mem2_rings_create,
2225 	.nmd_rings_delete = netmap_mem2_rings_delete
2226 };
2227 
2228 int
2229 netmap_mem_pools_info_get(struct nmreq_pools_info *req,
2230 				struct netmap_mem_d *nmd)
2231 {
2232 	int ret;
2233 
2234 	ret = netmap_mem_get_info(nmd, &req->nr_memsize, NULL,
2235 					&req->nr_mem_id);
2236 	if (ret) {
2237 		return ret;
2238 	}
2239 
2240 	NMA_LOCK(nmd);
2241 	req->nr_if_pool_offset = 0;
2242 	req->nr_if_pool_objtotal = nmd->pools[NETMAP_IF_POOL].objtotal;
2243 	req->nr_if_pool_objsize = nmd->pools[NETMAP_IF_POOL]._objsize;
2244 
2245 	req->nr_ring_pool_offset = nmd->pools[NETMAP_IF_POOL].memtotal;
2246 	req->nr_ring_pool_objtotal = nmd->pools[NETMAP_RING_POOL].objtotal;
2247 	req->nr_ring_pool_objsize = nmd->pools[NETMAP_RING_POOL]._objsize;
2248 
2249 	req->nr_buf_pool_offset = nmd->pools[NETMAP_IF_POOL].memtotal +
2250 			     nmd->pools[NETMAP_RING_POOL].memtotal;
2251 	req->nr_buf_pool_objtotal = nmd->pools[NETMAP_BUF_POOL].objtotal;
2252 	req->nr_buf_pool_objsize = nmd->pools[NETMAP_BUF_POOL]._objsize;
2253 	NMA_UNLOCK(nmd);
2254 
2255 	return 0;
2256 }
2257 
2258 #ifdef WITH_EXTMEM
2259 struct netmap_mem_ext {
2260 	struct netmap_mem_d up;
2261 
2262 	struct nm_os_extmem *os;
2263 	struct netmap_mem_ext *next, *prev;
2264 };
2265 
2266 /* call with nm_mem_list_lock held */
2267 static void
2268 netmap_mem_ext_register(struct netmap_mem_ext *e)
2269 {
2270 	NM_MTX_LOCK(nm_mem_ext_list_lock);
2271 	if (netmap_mem_ext_list)
2272 		netmap_mem_ext_list->prev = e;
2273 	e->next = netmap_mem_ext_list;
2274 	netmap_mem_ext_list = e;
2275 	e->prev = NULL;
2276 	NM_MTX_UNLOCK(nm_mem_ext_list_lock);
2277 }
2278 
2279 /* call with nm_mem_list_lock held */
2280 static void
2281 netmap_mem_ext_unregister(struct netmap_mem_ext *e)
2282 {
2283 	if (e->prev)
2284 		e->prev->next = e->next;
2285 	else
2286 		netmap_mem_ext_list = e->next;
2287 	if (e->next)
2288 		e->next->prev = e->prev;
2289 	e->prev = e->next = NULL;
2290 }
2291 
2292 static struct netmap_mem_ext *
2293 netmap_mem_ext_search(struct nm_os_extmem *os)
2294 {
2295 	struct netmap_mem_ext *e;
2296 
2297 	NM_MTX_LOCK(nm_mem_ext_list_lock);
2298 	for (e = netmap_mem_ext_list; e; e = e->next) {
2299 		if (nm_os_extmem_isequal(e->os, os)) {
2300 			netmap_mem_get(&e->up);
2301 			break;
2302 		}
2303 	}
2304 	NM_MTX_UNLOCK(nm_mem_ext_list_lock);
2305 	return e;
2306 }
2307 
2308 
2309 static void
2310 netmap_mem_ext_delete(struct netmap_mem_d *d)
2311 {
2312 	int i;
2313 	struct netmap_mem_ext *e =
2314 		(struct netmap_mem_ext *)d;
2315 
2316 	netmap_mem_ext_unregister(e);
2317 
2318 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
2319 		struct netmap_obj_pool *p = &d->pools[i];
2320 
2321 		if (p->lut) {
2322 			nm_free_lut(p->lut, p->objtotal);
2323 			p->lut = NULL;
2324 		}
2325 	}
2326 	if (e->os)
2327 		nm_os_extmem_delete(e->os);
2328 	netmap_mem2_delete(d);
2329 }
2330 
2331 static int
2332 netmap_mem_ext_config(struct netmap_mem_d *nmd)
2333 {
2334 	return 0;
2335 }
2336 
2337 struct netmap_mem_ops netmap_mem_ext_ops = {
2338 	.nmd_get_lut = netmap_mem2_get_lut,
2339 	.nmd_get_info = netmap_mem2_get_info,
2340 	.nmd_ofstophys = netmap_mem2_ofstophys,
2341 	.nmd_config = netmap_mem_ext_config,
2342 	.nmd_finalize = netmap_mem2_finalize,
2343 	.nmd_deref = netmap_mem2_deref,
2344 	.nmd_delete = netmap_mem_ext_delete,
2345 	.nmd_if_offset = netmap_mem2_if_offset,
2346 	.nmd_if_new = netmap_mem2_if_new,
2347 	.nmd_if_delete = netmap_mem2_if_delete,
2348 	.nmd_rings_create = netmap_mem2_rings_create,
2349 	.nmd_rings_delete = netmap_mem2_rings_delete
2350 };
2351 
2352 struct netmap_mem_d *
2353 netmap_mem_ext_create(uint64_t usrptr, struct nmreq_pools_info *pi, int *perror)
2354 {
2355 	int error = 0;
2356 	int i, j;
2357 	struct netmap_mem_ext *nme;
2358 	char *clust;
2359 	size_t off;
2360 	struct nm_os_extmem *os = NULL;
2361 	int nr_pages;
2362 
2363 	// XXX sanity checks
2364 	if (pi->nr_if_pool_objtotal == 0)
2365 		pi->nr_if_pool_objtotal = netmap_min_priv_params[NETMAP_IF_POOL].num;
2366 	if (pi->nr_if_pool_objsize == 0)
2367 		pi->nr_if_pool_objsize = netmap_min_priv_params[NETMAP_IF_POOL].size;
2368 	if (pi->nr_ring_pool_objtotal == 0)
2369 		pi->nr_ring_pool_objtotal = netmap_min_priv_params[NETMAP_RING_POOL].num;
2370 	if (pi->nr_ring_pool_objsize == 0)
2371 		pi->nr_ring_pool_objsize = netmap_min_priv_params[NETMAP_RING_POOL].size;
2372 	if (pi->nr_buf_pool_objtotal == 0)
2373 		pi->nr_buf_pool_objtotal = netmap_min_priv_params[NETMAP_BUF_POOL].num;
2374 	if (pi->nr_buf_pool_objsize == 0)
2375 		pi->nr_buf_pool_objsize = netmap_min_priv_params[NETMAP_BUF_POOL].size;
2376 	if (netmap_verbose & NM_DEBUG_MEM)
2377 		nm_prinf("if %d %d ring %d %d buf %d %d",
2378 			pi->nr_if_pool_objtotal, pi->nr_if_pool_objsize,
2379 			pi->nr_ring_pool_objtotal, pi->nr_ring_pool_objsize,
2380 			pi->nr_buf_pool_objtotal, pi->nr_buf_pool_objsize);
2381 
2382 	os = nm_os_extmem_create(usrptr, pi, &error);
2383 	if (os == NULL) {
2384 		nm_prerr("os extmem creation failed");
2385 		goto out;
2386 	}
2387 
2388 	nme = netmap_mem_ext_search(os);
2389 	if (nme) {
2390 		nm_os_extmem_delete(os);
2391 		return &nme->up;
2392 	}
2393 	if (netmap_verbose & NM_DEBUG_MEM)
2394 		nm_prinf("not found, creating new");
2395 
2396 	nme = _netmap_mem_private_new(sizeof(*nme),
2397 
2398 			(struct netmap_obj_params[]){
2399 				{ pi->nr_if_pool_objsize, pi->nr_if_pool_objtotal },
2400 				{ pi->nr_ring_pool_objsize, pi->nr_ring_pool_objtotal },
2401 				{ pi->nr_buf_pool_objsize, pi->nr_buf_pool_objtotal }},
2402 			-1,
2403 			&netmap_mem_ext_ops,
2404 			pi->nr_memsize,
2405 			&error);
2406 	if (nme == NULL)
2407 		goto out_unmap;
2408 
2409 	nr_pages = nm_os_extmem_nr_pages(os);
2410 
2411 	/* from now on pages will be released by nme destructor;
2412 	 * we let res = 0 to prevent release in out_unmap below
2413 	 */
2414 	nme->os = os;
2415 	os = NULL; /* pass ownership */
2416 
2417 	clust = nm_os_extmem_nextpage(nme->os);
2418 	off = 0;
2419 	for (i = 0; i < NETMAP_POOLS_NR; i++) {
2420 		struct netmap_obj_pool *p = &nme->up.pools[i];
2421 		struct netmap_obj_params *o = &nme->up.params[i];
2422 
2423 		p->_objsize = o->size;
2424 		p->_clustsize = o->size;
2425 		p->_clustentries = 1;
2426 
2427 		p->lut = nm_alloc_lut(o->num);
2428 		if (p->lut == NULL) {
2429 			error = ENOMEM;
2430 			goto out_delete;
2431 		}
2432 
2433 		p->bitmap_slots = (o->num + sizeof(uint32_t) - 1) / sizeof(uint32_t);
2434 		p->invalid_bitmap = nm_os_malloc(sizeof(uint32_t) * p->bitmap_slots);
2435 		if (p->invalid_bitmap == NULL) {
2436 			error = ENOMEM;
2437 			goto out_delete;
2438 		}
2439 
2440 		if (nr_pages == 0) {
2441 			p->objtotal = 0;
2442 			p->memtotal = 0;
2443 			p->objfree = 0;
2444 			continue;
2445 		}
2446 
2447 		for (j = 0; j < o->num && nr_pages > 0; j++) {
2448 			size_t noff;
2449 
2450 			p->lut[j].vaddr = clust + off;
2451 #if !defined(linux) && !defined(_WIN32)
2452 			p->lut[j].paddr = vtophys(p->lut[j].vaddr);
2453 #endif
2454 			nm_prdis("%s %d at %p", p->name, j, p->lut[j].vaddr);
2455 			noff = off + p->_objsize;
2456 			if (noff < PAGE_SIZE) {
2457 				off = noff;
2458 				continue;
2459 			}
2460 			nm_prdis("too big, recomputing offset...");
2461 			while (noff >= PAGE_SIZE) {
2462 				char *old_clust = clust;
2463 				noff -= PAGE_SIZE;
2464 				clust = nm_os_extmem_nextpage(nme->os);
2465 				nr_pages--;
2466 				nm_prdis("noff %zu page %p nr_pages %d", noff,
2467 						page_to_virt(*pages), nr_pages);
2468 				if (noff > 0 && !nm_isset(p->invalid_bitmap, j) &&
2469 					(nr_pages == 0 ||
2470 					 old_clust + PAGE_SIZE != clust))
2471 				{
2472 					/* out of space or non contiguous,
2473 					 * drop this object
2474 					 * */
2475 					p->invalid_bitmap[ (j>>5) ] |= 1U << (j & 31U);
2476 					nm_prdis("non contiguous at off %zu, drop", noff);
2477 				}
2478 				if (nr_pages == 0)
2479 					break;
2480 			}
2481 			off = noff;
2482 		}
2483 		p->objtotal = j;
2484 		p->numclusters = p->objtotal;
2485 		p->memtotal = j * (size_t)p->_objsize;
2486 		nm_prdis("%d memtotal %zu", j, p->memtotal);
2487 	}
2488 
2489 	netmap_mem_ext_register(nme);
2490 
2491 	return &nme->up;
2492 
2493 out_delete:
2494 	netmap_mem_put(&nme->up);
2495 out_unmap:
2496 	if (os)
2497 		nm_os_extmem_delete(os);
2498 out:
2499 	if (perror)
2500 		*perror = error;
2501 	return NULL;
2502 
2503 }
2504 #endif /* WITH_EXTMEM */
2505 
2506 
2507 #ifdef WITH_PTNETMAP
2508 struct mem_pt_if {
2509 	struct mem_pt_if *next;
2510 	if_t ifp;
2511 	unsigned int nifp_offset;
2512 };
2513 
2514 /* Netmap allocator for ptnetmap guests. */
2515 struct netmap_mem_ptg {
2516 	struct netmap_mem_d up;
2517 
2518 	vm_paddr_t nm_paddr;            /* physical address in the guest */
2519 	void *nm_addr;                  /* virtual address in the guest */
2520 	struct netmap_lut buf_lut;      /* lookup table for BUF pool in the guest */
2521 	nm_memid_t host_mem_id;         /* allocator identifier in the host */
2522 	struct ptnetmap_memdev *ptn_dev;/* ptnetmap memdev */
2523 	struct mem_pt_if *pt_ifs;	/* list of interfaces in passthrough */
2524 };
2525 
2526 /* Link a passthrough interface to a passthrough netmap allocator. */
2527 static int
2528 netmap_mem_pt_guest_ifp_add(struct netmap_mem_d *nmd, if_t ifp,
2529 			    unsigned int nifp_offset)
2530 {
2531 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2532 	struct mem_pt_if *ptif = nm_os_malloc(sizeof(*ptif));
2533 
2534 	if (!ptif) {
2535 		return ENOMEM;
2536 	}
2537 
2538 	NMA_LOCK(nmd);
2539 
2540 	ptif->ifp = ifp;
2541 	ptif->nifp_offset = nifp_offset;
2542 
2543 	if (ptnmd->pt_ifs) {
2544 		ptif->next = ptnmd->pt_ifs;
2545 	}
2546 	ptnmd->pt_ifs = ptif;
2547 
2548 	NMA_UNLOCK(nmd);
2549 
2550 	nm_prinf("ifp=%s,nifp_offset=%u",
2551 		if_name(ptif->ifp), ptif->nifp_offset);
2552 
2553 	return 0;
2554 }
2555 
2556 /* Called with NMA_LOCK(nmd) held. */
2557 static struct mem_pt_if *
2558 netmap_mem_pt_guest_ifp_lookup(struct netmap_mem_d *nmd, if_t ifp)
2559 {
2560 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2561 	struct mem_pt_if *curr;
2562 
2563 	for (curr = ptnmd->pt_ifs; curr; curr = curr->next) {
2564 		if (curr->ifp == ifp) {
2565 			return curr;
2566 		}
2567 	}
2568 
2569 	return NULL;
2570 }
2571 
2572 /* Unlink a passthrough interface from a passthrough netmap allocator. */
2573 int
2574 netmap_mem_pt_guest_ifp_del(struct netmap_mem_d *nmd, if_t ifp)
2575 {
2576 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2577 	struct mem_pt_if *prev = NULL;
2578 	struct mem_pt_if *curr;
2579 	int ret = -1;
2580 
2581 	NMA_LOCK(nmd);
2582 
2583 	for (curr = ptnmd->pt_ifs; curr; curr = curr->next) {
2584 		if (curr->ifp == ifp) {
2585 			if (prev) {
2586 				prev->next = curr->next;
2587 			} else {
2588 				ptnmd->pt_ifs = curr->next;
2589 			}
2590 			nm_prinf("removed (ifp=%s,nifp_offset=%u)",
2591 			  if_name(curr->ifp), curr->nifp_offset);
2592 			nm_os_free(curr);
2593 			ret = 0;
2594 			break;
2595 		}
2596 		prev = curr;
2597 	}
2598 
2599 	NMA_UNLOCK(nmd);
2600 
2601 	return ret;
2602 }
2603 
2604 static int
2605 netmap_mem_pt_guest_get_lut(struct netmap_mem_d *nmd, struct netmap_lut *lut)
2606 {
2607 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2608 
2609 	if (!(nmd->flags & NETMAP_MEM_FINALIZED)) {
2610 		return EINVAL;
2611 	}
2612 
2613 	*lut = ptnmd->buf_lut;
2614 	return 0;
2615 }
2616 
2617 static int
2618 netmap_mem_pt_guest_get_info(struct netmap_mem_d *nmd, uint64_t *size,
2619 			     u_int *memflags, uint16_t *id)
2620 {
2621 	int error = 0;
2622 
2623 	error = nmd->ops->nmd_config(nmd);
2624 	if (error)
2625 		goto out;
2626 
2627 	if (size)
2628 		*size = nmd->nm_totalsize;
2629 	if (memflags)
2630 		*memflags = nmd->flags;
2631 	if (id)
2632 		*id = nmd->nm_id;
2633 
2634 out:
2635 
2636 	return error;
2637 }
2638 
2639 static vm_paddr_t
2640 netmap_mem_pt_guest_ofstophys(struct netmap_mem_d *nmd, vm_ooffset_t off)
2641 {
2642 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2643 	vm_paddr_t paddr;
2644 	/* if the offset is valid, just return csb->base_addr + off */
2645 	paddr = (vm_paddr_t)(ptnmd->nm_paddr + off);
2646 	nm_prdis("off %lx padr %lx", off, (unsigned long)paddr);
2647 	return paddr;
2648 }
2649 
2650 static int
2651 netmap_mem_pt_guest_config(struct netmap_mem_d *nmd)
2652 {
2653 	/* nothing to do, we are configured on creation
2654 	 * and configuration never changes thereafter
2655 	 */
2656 	return 0;
2657 }
2658 
2659 static int
2660 netmap_mem_pt_guest_finalize(struct netmap_mem_d *nmd, struct netmap_adapter *na)
2661 {
2662 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2663 	uint64_t mem_size;
2664 	uint32_t bufsize;
2665 	uint32_t nbuffers;
2666 	uint32_t poolofs;
2667 	vm_paddr_t paddr;
2668 	char *vaddr;
2669 	int i;
2670 	int error = 0;
2671 
2672 	if (nmd->flags & NETMAP_MEM_FINALIZED)
2673 		goto out;
2674 
2675 	if (ptnmd->ptn_dev == NULL) {
2676 		nm_prerr("ptnetmap memdev not attached");
2677 		error = ENOMEM;
2678 		goto out;
2679 	}
2680 	/* Map memory through ptnetmap-memdev BAR. */
2681 	error = nm_os_pt_memdev_iomap(ptnmd->ptn_dev, &ptnmd->nm_paddr,
2682 				      &ptnmd->nm_addr, &mem_size);
2683 	if (error)
2684 		goto out;
2685 
2686 	/* Initialize the lut using the information contained in the
2687 	 * ptnetmap memory device. */
2688 	bufsize = nm_os_pt_memdev_ioread(ptnmd->ptn_dev,
2689 					 PTNET_MDEV_IO_BUF_POOL_OBJSZ);
2690 	nbuffers = nm_os_pt_memdev_ioread(ptnmd->ptn_dev,
2691 					 PTNET_MDEV_IO_BUF_POOL_OBJNUM);
2692 
2693 	/* allocate the lut */
2694 	if (ptnmd->buf_lut.lut == NULL) {
2695 		nm_prinf("allocating lut");
2696 		ptnmd->buf_lut.lut = nm_alloc_lut(nbuffers);
2697 		if (ptnmd->buf_lut.lut == NULL) {
2698 			nm_prerr("lut allocation failed");
2699 			return ENOMEM;
2700 		}
2701 	}
2702 
2703 	/* we have physically contiguous memory mapped through PCI BAR */
2704 	poolofs = nm_os_pt_memdev_ioread(ptnmd->ptn_dev,
2705 					 PTNET_MDEV_IO_BUF_POOL_OFS);
2706 	vaddr = (char *)(ptnmd->nm_addr) + poolofs;
2707 	paddr = ptnmd->nm_paddr + poolofs;
2708 
2709 	for (i = 0; i < nbuffers; i++) {
2710 		ptnmd->buf_lut.lut[i].vaddr = vaddr;
2711 		vaddr += bufsize;
2712 		paddr += bufsize;
2713 	}
2714 
2715 	ptnmd->buf_lut.objtotal = nbuffers;
2716 	ptnmd->buf_lut.objsize = bufsize;
2717 	nmd->nm_totalsize = mem_size;
2718 
2719 	/* Initialize these fields as are needed by
2720 	 * netmap_mem_bufsize().
2721 	 * XXX please improve this, why do we need this
2722 	 * replication? maybe we nmd->pools[] should no be
2723 	 * there for the guest allocator? */
2724 	nmd->pools[NETMAP_BUF_POOL]._objsize = bufsize;
2725 	nmd->pools[NETMAP_BUF_POOL]._objtotal = nbuffers;
2726 
2727 	nmd->flags |= NETMAP_MEM_FINALIZED;
2728 out:
2729 	return error;
2730 }
2731 
2732 static void
2733 netmap_mem_pt_guest_deref(struct netmap_mem_d *nmd, struct netmap_adapter *na)
2734 {
2735 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2736 
2737 	if (nmd->active == 1 &&
2738 		(nmd->flags & NETMAP_MEM_FINALIZED)) {
2739 	    nmd->flags  &= ~NETMAP_MEM_FINALIZED;
2740 	    /* unmap ptnetmap-memdev memory */
2741 	    if (ptnmd->ptn_dev) {
2742 		nm_os_pt_memdev_iounmap(ptnmd->ptn_dev);
2743 	    }
2744 	    ptnmd->nm_addr = NULL;
2745 	    ptnmd->nm_paddr = 0;
2746 	}
2747 }
2748 
2749 static ssize_t
2750 netmap_mem_pt_guest_if_offset(struct netmap_mem_d *nmd, const void *vaddr)
2751 {
2752 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2753 
2754 	return (const char *)(vaddr) - (char *)(ptnmd->nm_addr);
2755 }
2756 
2757 static void
2758 netmap_mem_pt_guest_delete(struct netmap_mem_d *nmd)
2759 {
2760 	if (nmd == NULL)
2761 		return;
2762 	if (netmap_verbose)
2763 		nm_prinf("deleting %p", nmd);
2764 	if (nmd->active > 0)
2765 		nm_prerr("bug: deleting mem allocator with active=%d!", nmd->active);
2766 	if (netmap_verbose)
2767 		nm_prinf("done deleting %p", nmd);
2768 	NMA_LOCK_DESTROY(nmd);
2769 	nm_os_free(nmd);
2770 }
2771 
2772 static struct netmap_if *
2773 netmap_mem_pt_guest_if_new(struct netmap_mem_d *nmd,
2774 		struct netmap_adapter *na, struct netmap_priv_d *priv)
2775 {
2776 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2777 	struct mem_pt_if *ptif;
2778 	struct netmap_if *nifp = NULL;
2779 
2780 	ptif = netmap_mem_pt_guest_ifp_lookup(nmd, na->ifp);
2781 	if (ptif == NULL) {
2782 		nm_prerr("interface %s is not in passthrough", na->name);
2783 		goto out;
2784 	}
2785 
2786 	nifp = (struct netmap_if *)((char *)(ptnmd->nm_addr) +
2787 				    ptif->nifp_offset);
2788 out:
2789 	return nifp;
2790 }
2791 
2792 static void
2793 netmap_mem_pt_guest_if_delete(struct netmap_mem_d * nmd,
2794 		struct netmap_adapter *na, struct netmap_if *nifp)
2795 {
2796 	struct mem_pt_if *ptif;
2797 
2798 	ptif = netmap_mem_pt_guest_ifp_lookup(nmd, na->ifp);
2799 	if (ptif == NULL) {
2800 		nm_prerr("interface %s is not in passthrough", na->name);
2801 	}
2802 }
2803 
2804 static int
2805 netmap_mem_pt_guest_rings_create(struct netmap_mem_d *nmd,
2806 		struct netmap_adapter *na)
2807 {
2808 	struct netmap_mem_ptg *ptnmd = (struct netmap_mem_ptg *)nmd;
2809 	struct mem_pt_if *ptif;
2810 	struct netmap_if *nifp;
2811 	int i, error = -1;
2812 
2813 	ptif = netmap_mem_pt_guest_ifp_lookup(nmd, na->ifp);
2814 	if (ptif == NULL) {
2815 		nm_prerr("interface %s is not in passthrough", na->name);
2816 		goto out;
2817 	}
2818 
2819 
2820 	/* point each kring to the corresponding backend ring */
2821 	nifp = (struct netmap_if *)((char *)ptnmd->nm_addr + ptif->nifp_offset);
2822 	for (i = 0; i < netmap_all_rings(na, NR_TX); i++) {
2823 		struct netmap_kring *kring = na->tx_rings[i];
2824 		if (kring->ring)
2825 			continue;
2826 		kring->ring = (struct netmap_ring *)
2827 			((char *)nifp + nifp->ring_ofs[i]);
2828 	}
2829 	for (i = 0; i < netmap_all_rings(na, NR_RX); i++) {
2830 		struct netmap_kring *kring = na->rx_rings[i];
2831 		if (kring->ring)
2832 			continue;
2833 		kring->ring = (struct netmap_ring *)
2834 			((char *)nifp +
2835 			 nifp->ring_ofs[netmap_all_rings(na, NR_TX) + i]);
2836 	}
2837 
2838 	error = 0;
2839 out:
2840 	return error;
2841 }
2842 
2843 static void
2844 netmap_mem_pt_guest_rings_delete(struct netmap_mem_d *nmd, struct netmap_adapter *na)
2845 {
2846 #if 0
2847 	enum txrx t;
2848 
2849 	for_rx_tx(t) {
2850 		u_int i;
2851 		for (i = 0; i < nma_get_nrings(na, t) + 1; i++) {
2852 			struct netmap_kring *kring = &NMR(na, t)[i];
2853 
2854 			kring->ring = NULL;
2855 		}
2856 	}
2857 #endif
2858 	(void)nmd;
2859 	(void)na;
2860 }
2861 
2862 static struct netmap_mem_ops netmap_mem_pt_guest_ops = {
2863 	.nmd_get_lut = netmap_mem_pt_guest_get_lut,
2864 	.nmd_get_info = netmap_mem_pt_guest_get_info,
2865 	.nmd_ofstophys = netmap_mem_pt_guest_ofstophys,
2866 	.nmd_config = netmap_mem_pt_guest_config,
2867 	.nmd_finalize = netmap_mem_pt_guest_finalize,
2868 	.nmd_deref = netmap_mem_pt_guest_deref,
2869 	.nmd_if_offset = netmap_mem_pt_guest_if_offset,
2870 	.nmd_delete = netmap_mem_pt_guest_delete,
2871 	.nmd_if_new = netmap_mem_pt_guest_if_new,
2872 	.nmd_if_delete = netmap_mem_pt_guest_if_delete,
2873 	.nmd_rings_create = netmap_mem_pt_guest_rings_create,
2874 	.nmd_rings_delete = netmap_mem_pt_guest_rings_delete
2875 };
2876 
2877 /* Called with nm_mem_list_lock held. */
2878 static struct netmap_mem_d *
2879 netmap_mem_pt_guest_find_memid(nm_memid_t mem_id)
2880 {
2881 	struct netmap_mem_d *mem = NULL;
2882 	struct netmap_mem_d *scan = netmap_last_mem_d;
2883 
2884 	do {
2885 		/* find ptnetmap allocator through host ID */
2886 		if (scan->ops->nmd_deref == netmap_mem_pt_guest_deref &&
2887 			((struct netmap_mem_ptg *)(scan))->host_mem_id == mem_id) {
2888 			mem = scan;
2889 			mem->refcount++;
2890 			NM_DBG_REFC(mem, __FUNCTION__, __LINE__);
2891 			break;
2892 		}
2893 		scan = scan->next;
2894 	} while (scan != netmap_last_mem_d);
2895 
2896 	return mem;
2897 }
2898 
2899 /* Called with nm_mem_list_lock held. */
2900 static struct netmap_mem_d *
2901 netmap_mem_pt_guest_create(nm_memid_t mem_id)
2902 {
2903 	struct netmap_mem_ptg *ptnmd;
2904 	int err = 0;
2905 
2906 	ptnmd = nm_os_malloc(sizeof(struct netmap_mem_ptg));
2907 	if (ptnmd == NULL) {
2908 		err = ENOMEM;
2909 		goto error;
2910 	}
2911 
2912 	ptnmd->up.ops = &netmap_mem_pt_guest_ops;
2913 	ptnmd->host_mem_id = mem_id;
2914 	ptnmd->pt_ifs = NULL;
2915 
2916 	/* Assign new id in the guest (We have the lock) */
2917 	err = nm_mem_assign_id_locked(&ptnmd->up, -1, -1);
2918 	if (err)
2919 		goto error;
2920 
2921 	ptnmd->up.flags &= ~NETMAP_MEM_FINALIZED;
2922 	ptnmd->up.flags |= NETMAP_MEM_IO;
2923 
2924 	NMA_LOCK_INIT(&ptnmd->up);
2925 
2926 	snprintf(ptnmd->up.name, NM_MEM_NAMESZ, "%d", ptnmd->up.nm_id);
2927 
2928 
2929 	return &ptnmd->up;
2930 error:
2931 	netmap_mem_pt_guest_delete(&ptnmd->up);
2932 	return NULL;
2933 }
2934 
2935 /*
2936  * find host id in guest allocators and create guest allocator
2937  * if it is not there
2938  */
2939 static struct netmap_mem_d *
2940 netmap_mem_pt_guest_get(nm_memid_t mem_id)
2941 {
2942 	struct netmap_mem_d *nmd;
2943 
2944 	NM_MTX_LOCK(nm_mem_list_lock);
2945 	nmd = netmap_mem_pt_guest_find_memid(mem_id);
2946 	if (nmd == NULL) {
2947 		nmd = netmap_mem_pt_guest_create(mem_id);
2948 	}
2949 	NM_MTX_UNLOCK(nm_mem_list_lock);
2950 
2951 	return nmd;
2952 }
2953 
2954 /*
2955  * The guest allocator can be created by ptnetmap_memdev (during the device
2956  * attach) or by ptnetmap device (ptnet), during the netmap_attach.
2957  *
2958  * The order is not important (we have different order in LINUX and FreeBSD).
2959  * The first one, creates the device, and the second one simply attaches it.
2960  */
2961 
2962 /* Called when ptnetmap_memdev is attaching, to attach a new allocator in
2963  * the guest */
2964 struct netmap_mem_d *
2965 netmap_mem_pt_guest_attach(struct ptnetmap_memdev *ptn_dev, nm_memid_t mem_id)
2966 {
2967 	struct netmap_mem_d *nmd;
2968 	struct netmap_mem_ptg *ptnmd;
2969 
2970 	nmd = netmap_mem_pt_guest_get(mem_id);
2971 
2972 	/* assign this device to the guest allocator */
2973 	if (nmd) {
2974 		ptnmd = (struct netmap_mem_ptg *)nmd;
2975 		ptnmd->ptn_dev = ptn_dev;
2976 	}
2977 
2978 	return nmd;
2979 }
2980 
2981 /* Called when ptnet device is attaching */
2982 struct netmap_mem_d *
2983 netmap_mem_pt_guest_new(if_t ifp,
2984 			unsigned int nifp_offset,
2985 			unsigned int memid)
2986 {
2987 	struct netmap_mem_d *nmd;
2988 
2989 	if (ifp == NULL) {
2990 		return NULL;
2991 	}
2992 
2993 	nmd = netmap_mem_pt_guest_get((nm_memid_t)memid);
2994 
2995 	if (nmd) {
2996 		netmap_mem_pt_guest_ifp_add(nmd, ifp, nifp_offset);
2997 	}
2998 
2999 	return nmd;
3000 }
3001 
3002 #endif /* WITH_PTNETMAP */
3003