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