FILE
rxe_odp.c
File preview with syntax highlighting.
linux-6.19.14/drivers/infiniband/sw/rxe/rxe_odp.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* 3 * Copyright (c) 2022-2023 Fujitsu Ltd. All rights reserved. 4 */ 5 6#include <linux/hmm.h> 7#include <linux/libnvdimm.h> 8 9#include <rdma/ib_umem_odp.h> 10 11#include "rxe.h" 12 13static bool rxe_ib_invalidate_range(struct mmu_interval_notifier *mni, 14 const struct mmu_notifier_range *range, 15 unsigned long cur_seq) 16{ 17 struct ib_umem_odp *umem_odp = 18 container_of(mni, struct ib_umem_odp, notifier); 19 unsigned long start, end; 20 21 if (!mmu_notifier_range_blockable(range)) 22 return false; 23 24 mutex_lock(&umem_odp->umem_mutex); 25 mmu_interval_set_seq(mni, cur_seq); 26 27 start = max_t(u64, ib_umem_start(umem_odp), range->start); 28 end = min_t(u64, ib_umem_end(umem_odp), range->end); 29 30 /* update umem_odp->map.pfn_list */ 31 ib_umem_odp_unmap_dma_pages(umem_odp, start, end); 32 33 mutex_unlock(&umem_odp->umem_mutex); 34 return true; 35} 36 37const struct mmu_interval_notifier_ops rxe_mn_ops = { 38 .invalidate = rxe_ib_invalidate_range, 39}; 40 41#define RXE_PAGEFAULT_DEFAULT 0 42#define RXE_PAGEFAULT_RDONLY BIT(0) 43#define RXE_PAGEFAULT_SNAPSHOT BIT(1) 44static int rxe_odp_do_pagefault_and_lock(struct rxe_mr *mr, u64 user_va, int bcnt, u32 flags) 45{ 46 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 47 bool fault = !(flags & RXE_PAGEFAULT_SNAPSHOT); 48 u64 access_mask = 0; 49 int np; 50 51 if (umem_odp->umem.writable && !(flags & RXE_PAGEFAULT_RDONLY)) 52 access_mask |= HMM_PFN_WRITE; 53 54 /* 55 * ib_umem_odp_map_dma_and_lock() locks umem_mutex on success. 56 * Callers must release the lock later to let invalidation handler 57 * do its work again. 58 */ 59 np = ib_umem_odp_map_dma_and_lock(umem_odp, user_va, bcnt, 60 access_mask, fault); 61 return np; 62} 63 64static int rxe_odp_init_pages(struct rxe_mr *mr) 65{ 66 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 67 int ret; 68 69 ret = rxe_odp_do_pagefault_and_lock(mr, mr->umem->address, 70 mr->umem->length, 71 RXE_PAGEFAULT_SNAPSHOT); 72 73 if (ret >= 0) 74 mutex_unlock(&umem_odp->umem_mutex); 75 76 return ret >= 0 ? 0 : ret; 77} 78 79int rxe_odp_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, 80 u64 iova, int access_flags, struct rxe_mr *mr) 81{ 82 struct ib_umem_odp *umem_odp; 83 int err; 84 85 if (!IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) 86 return -EOPNOTSUPP; 87 88 rxe_mr_init(access_flags, mr); 89 90 if (!start && length == U64_MAX) { 91 if (iova != 0) 92 return -EINVAL; 93 if (!(rxe->attr.odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT)) 94 return -EINVAL; 95 96 /* Never reach here, for implicit ODP is not implemented. */ 97 } 98 99 umem_odp = ib_umem_odp_get(&rxe->ib_dev, start, length, access_flags, 100 &rxe_mn_ops); 101 if (IS_ERR(umem_odp)) { 102 rxe_dbg_mr(mr, "Unable to create umem_odp err = %d\n", 103 (int)PTR_ERR(umem_odp)); 104 return PTR_ERR(umem_odp); 105 } 106 107 umem_odp->private = mr; 108 109 mr->umem = &umem_odp->umem; 110 mr->access = access_flags; 111 mr->ibmr.length = length; 112 mr->ibmr.iova = iova; 113 mr->page_offset = ib_umem_offset(&umem_odp->umem); 114 115 err = rxe_odp_init_pages(mr); 116 if (err) { 117 ib_umem_odp_release(umem_odp); 118 return err; 119 } 120 121 mr->state = RXE_MR_STATE_VALID; 122 mr->ibmr.type = IB_MR_TYPE_USER; 123 124 return err; 125} 126 127static inline bool rxe_check_pagefault(struct ib_umem_odp *umem_odp, u64 iova, 128 int length) 129{ 130 bool need_fault = false; 131 u64 addr; 132 int idx; 133 134 addr = iova & (~(BIT(umem_odp->page_shift) - 1)); 135 136 /* Skim through all pages that are to be accessed. */ 137 while (addr < iova + length) { 138 idx = (addr - ib_umem_start(umem_odp)) >> umem_odp->page_shift; 139 140 if (!(umem_odp->map.pfn_list[idx] & HMM_PFN_VALID)) { 141 need_fault = true; 142 break; 143 } 144 145 addr += BIT(umem_odp->page_shift); 146 } 147 return need_fault; 148} 149 150static unsigned long rxe_odp_iova_to_index(struct ib_umem_odp *umem_odp, u64 iova) 151{ 152 return (iova - ib_umem_start(umem_odp)) >> umem_odp->page_shift; 153} 154 155static unsigned long rxe_odp_iova_to_page_offset(struct ib_umem_odp *umem_odp, u64 iova) 156{ 157 return iova & (BIT(umem_odp->page_shift) - 1); 158} 159 160static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, u32 flags) 161{ 162 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 163 bool need_fault; 164 int err; 165 166 if (unlikely(length < 1)) 167 return -EINVAL; 168 169 mutex_lock(&umem_odp->umem_mutex); 170 171 need_fault = rxe_check_pagefault(umem_odp, iova, length); 172 if (need_fault) { 173 mutex_unlock(&umem_odp->umem_mutex); 174 175 /* umem_mutex is locked on success. */ 176 err = rxe_odp_do_pagefault_and_lock(mr, iova, length, 177 flags); 178 if (err < 0) 179 return err; 180 181 need_fault = rxe_check_pagefault(umem_odp, iova, length); 182 if (need_fault) { 183 mutex_unlock(&umem_odp->umem_mutex); 184 return -EFAULT; 185 } 186 } 187 188 return 0; 189} 190 191static int __rxe_odp_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, 192 int length, enum rxe_mr_copy_dir dir) 193{ 194 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 195 struct page *page; 196 int idx, bytes; 197 size_t offset; 198 u8 *user_va; 199 200 idx = rxe_odp_iova_to_index(umem_odp, iova); 201 offset = rxe_odp_iova_to_page_offset(umem_odp, iova); 202 203 while (length > 0) { 204 u8 *src, *dest; 205 206 page = hmm_pfn_to_page(umem_odp->map.pfn_list[idx]); 207 user_va = kmap_local_page(page); 208 209 src = (dir == RXE_TO_MR_OBJ) ? addr : user_va; 210 dest = (dir == RXE_TO_MR_OBJ) ? user_va : addr; 211 212 bytes = BIT(umem_odp->page_shift) - offset; 213 if (bytes > length) 214 bytes = length; 215 216 memcpy(dest, src, bytes); 217 kunmap_local(user_va); 218 219 length -= bytes; 220 idx++; 221 offset = 0; 222 } 223 224 return 0; 225} 226 227int rxe_odp_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length, 228 enum rxe_mr_copy_dir dir) 229{ 230 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 231 u32 flags = RXE_PAGEFAULT_DEFAULT; 232 int err; 233 234 if (length == 0) 235 return 0; 236 237 if (unlikely(!mr->umem->is_odp)) 238 return -EOPNOTSUPP; 239 240 switch (dir) { 241 case RXE_TO_MR_OBJ: 242 break; 243 244 case RXE_FROM_MR_OBJ: 245 flags |= RXE_PAGEFAULT_RDONLY; 246 break; 247 248 default: 249 return -EINVAL; 250 } 251 252 err = rxe_odp_map_range_and_lock(mr, iova, length, flags); 253 if (err) 254 return err; 255 256 err = __rxe_odp_mr_copy(mr, iova, addr, length, dir); 257 258 mutex_unlock(&umem_odp->umem_mutex); 259 260 return err; 261} 262 263static enum resp_states rxe_odp_do_atomic_op(struct rxe_mr *mr, u64 iova, 264 int opcode, u64 compare, 265 u64 swap_add, u64 *orig_val) 266{ 267 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 268 unsigned int page_offset; 269 struct page *page; 270 unsigned int idx; 271 u64 value; 272 u64 *va; 273 int err; 274 275 if (unlikely(mr->state != RXE_MR_STATE_VALID)) { 276 rxe_dbg_mr(mr, "mr not in valid state\n"); 277 return RESPST_ERR_RKEY_VIOLATION; 278 } 279 280 err = mr_check_range(mr, iova, sizeof(value)); 281 if (err) { 282 rxe_dbg_mr(mr, "iova out of range\n"); 283 return RESPST_ERR_RKEY_VIOLATION; 284 } 285 286 page_offset = rxe_odp_iova_to_page_offset(umem_odp, iova); 287 if (unlikely(page_offset & 0x7)) { 288 rxe_dbg_mr(mr, "iova not aligned\n"); 289 return RESPST_ERR_MISALIGNED_ATOMIC; 290 } 291 292 idx = rxe_odp_iova_to_index(umem_odp, iova); 293 page = hmm_pfn_to_page(umem_odp->map.pfn_list[idx]); 294 295 va = kmap_local_page(page); 296 297 spin_lock_bh(&atomic_ops_lock); 298 value = *orig_val = va[page_offset >> 3]; 299 300 if (opcode == IB_OPCODE_RC_COMPARE_SWAP) { 301 if (value == compare) 302 va[page_offset >> 3] = swap_add; 303 } else { 304 value += swap_add; 305 va[page_offset >> 3] = value; 306 } 307 spin_unlock_bh(&atomic_ops_lock); 308 309 kunmap_local(va); 310 311 return RESPST_NONE; 312} 313 314enum resp_states rxe_odp_atomic_op(struct rxe_mr *mr, u64 iova, int opcode, 315 u64 compare, u64 swap_add, u64 *orig_val) 316{ 317 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 318 int err; 319 320 err = rxe_odp_map_range_and_lock(mr, iova, sizeof(char), 321 RXE_PAGEFAULT_DEFAULT); 322 if (err < 0) 323 return RESPST_ERR_RKEY_VIOLATION; 324 325 err = rxe_odp_do_atomic_op(mr, iova, opcode, compare, swap_add, 326 orig_val); 327 mutex_unlock(&umem_odp->umem_mutex); 328 329 return err; 330} 331 332int rxe_odp_flush_pmem_iova(struct rxe_mr *mr, u64 iova, 333 unsigned int length) 334{ 335 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 336 unsigned int page_offset; 337 unsigned long index; 338 struct page *page; 339 unsigned int bytes; 340 int err; 341 u8 *va; 342 343 err = rxe_odp_map_range_and_lock(mr, iova, length, 344 RXE_PAGEFAULT_DEFAULT); 345 if (err) 346 return err; 347 348 while (length > 0) { 349 index = rxe_odp_iova_to_index(umem_odp, iova); 350 page_offset = rxe_odp_iova_to_page_offset(umem_odp, iova); 351 352 page = hmm_pfn_to_page(umem_odp->map.pfn_list[index]); 353 354 bytes = min_t(unsigned int, length, 355 mr_page_size(mr) - page_offset); 356 357 va = kmap_local_page(page); 358 arch_wb_cache_pmem(va + page_offset, bytes); 359 kunmap_local(va); 360 361 length -= bytes; 362 iova += bytes; 363 } 364 365 mutex_unlock(&umem_odp->umem_mutex); 366 367 return 0; 368} 369 370enum resp_states rxe_odp_do_atomic_write(struct rxe_mr *mr, u64 iova, u64 value) 371{ 372 struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem); 373 unsigned int page_offset; 374 unsigned long index; 375 struct page *page; 376 int err; 377 u64 *va; 378 379 /* See IBA oA19-28 */ 380 err = mr_check_range(mr, iova, sizeof(value)); 381 if (unlikely(err)) { 382 rxe_dbg_mr(mr, "iova out of range\n"); 383 return RESPST_ERR_RKEY_VIOLATION; 384 } 385 386 err = rxe_odp_map_range_and_lock(mr, iova, sizeof(value), 387 RXE_PAGEFAULT_DEFAULT); 388 if (err) 389 return RESPST_ERR_RKEY_VIOLATION; 390 391 page_offset = rxe_odp_iova_to_page_offset(umem_odp, iova); 392 /* See IBA A19.4.2 */ 393 if (unlikely(page_offset & 0x7)) { 394 mutex_unlock(&umem_odp->umem_mutex); 395 rxe_dbg_mr(mr, "misaligned address\n"); 396 return RESPST_ERR_MISALIGNED_ATOMIC; 397 } 398 399 index = rxe_odp_iova_to_index(umem_odp, iova); 400 page = hmm_pfn_to_page(umem_odp->map.pfn_list[index]); 401 402 va = kmap_local_page(page); 403 /* Do atomic write after all prior operations have completed */ 404 smp_store_release(&va[page_offset >> 3], value); 405 kunmap_local(va); 406 407 mutex_unlock(&umem_odp->umem_mutex); 408 409 return RESPST_NONE; 410} 411 412struct prefetch_mr_work { 413 struct work_struct work; 414 u32 pf_flags; 415 u32 num_sge; 416 struct { 417 u64 io_virt; 418 struct rxe_mr *mr; 419 size_t length; 420 } frags[]; 421}; 422 423static void rxe_ib_prefetch_mr_work(struct work_struct *w) 424{ 425 struct prefetch_mr_work *work = 426 container_of(w, struct prefetch_mr_work, work); 427 int ret; 428 u32 i; 429 430 /* 431 * We rely on IB/core that work is executed 432 * if we have num_sge != 0 only. 433 */ 434 WARN_ON(!work->num_sge); 435 for (i = 0; i < work->num_sge; ++i) { 436 struct ib_umem_odp *umem_odp; 437 438 ret = rxe_odp_do_pagefault_and_lock(work->frags[i].mr, 439 work->frags[i].io_virt, 440 work->frags[i].length, 441 work->pf_flags); 442 if (ret < 0) { 443 rxe_dbg_mr(work->frags[i].mr, 444 "failed to prefetch the mr\n"); 445 goto deref; 446 } 447 448 umem_odp = to_ib_umem_odp(work->frags[i].mr->umem); 449 mutex_unlock(&umem_odp->umem_mutex); 450 451deref: 452 rxe_put(work->frags[i].mr); 453 } 454 455 kvfree(work); 456} 457 458static int rxe_ib_prefetch_sg_list(struct ib_pd *ibpd, 459 enum ib_uverbs_advise_mr_advice advice, 460 u32 pf_flags, struct ib_sge *sg_list, 461 u32 num_sge) 462{ 463 struct rxe_pd *pd = container_of(ibpd, struct rxe_pd, ibpd); 464 int ret = 0; 465 u32 i; 466 467 for (i = 0; i < num_sge; ++i) { 468 struct rxe_mr *mr; 469 struct ib_umem_odp *umem_odp; 470 471 mr = lookup_mr(pd, IB_ACCESS_LOCAL_WRITE, 472 sg_list[i].lkey, RXE_LOOKUP_LOCAL); 473 474 if (!mr) { 475 rxe_dbg_pd(pd, "mr with lkey %x not found\n", 476 sg_list[i].lkey); 477 return -EINVAL; 478 } 479 480 if (advice == IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_WRITE && 481 !mr->umem->writable) { 482 rxe_dbg_mr(mr, "missing write permission\n"); 483 rxe_put(mr); 484 return -EPERM; 485 } 486 487 ret = rxe_odp_do_pagefault_and_lock( 488 mr, sg_list[i].addr, sg_list[i].length, pf_flags); 489 if (ret < 0) { 490 rxe_dbg_mr(mr, "failed to prefetch the mr\n"); 491 rxe_put(mr); 492 return ret; 493 } 494 495 umem_odp = to_ib_umem_odp(mr->umem); 496 mutex_unlock(&umem_odp->umem_mutex); 497 498 rxe_put(mr); 499 } 500 501 return 0; 502} 503 504static int rxe_ib_advise_mr_prefetch(struct ib_pd *ibpd, 505 enum ib_uverbs_advise_mr_advice advice, 506 u32 flags, struct ib_sge *sg_list, 507 u32 num_sge) 508{ 509 struct rxe_pd *pd = container_of(ibpd, struct rxe_pd, ibpd); 510 u32 pf_flags = RXE_PAGEFAULT_DEFAULT; 511 struct prefetch_mr_work *work; 512 struct rxe_mr *mr; 513 u32 i; 514 515 if (advice == IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH) 516 pf_flags |= RXE_PAGEFAULT_RDONLY; 517 518 if (advice == IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_NO_FAULT) 519 pf_flags |= RXE_PAGEFAULT_SNAPSHOT; 520 521 /* Synchronous call */ 522 if (flags & IB_UVERBS_ADVISE_MR_FLAG_FLUSH) 523 return rxe_ib_prefetch_sg_list(ibpd, advice, pf_flags, sg_list, 524 num_sge); 525 526 /* Asynchronous call is "best-effort" and allowed to fail */ 527 work = kvzalloc(struct_size(work, frags, num_sge), GFP_KERNEL); 528 if (!work) 529 return -ENOMEM; 530 531 INIT_WORK(&work->work, rxe_ib_prefetch_mr_work); 532 work->pf_flags = pf_flags; 533 work->num_sge = num_sge; 534 535 for (i = 0; i < num_sge; ++i) { 536 /* Takes a reference, which will be released in the queued work */ 537 mr = lookup_mr(pd, IB_ACCESS_LOCAL_WRITE, 538 sg_list[i].lkey, RXE_LOOKUP_LOCAL); 539 if (!mr) { 540 mr = ERR_PTR(-EINVAL); 541 goto err; 542 } 543 544 work->frags[i].io_virt = sg_list[i].addr; 545 work->frags[i].length = sg_list[i].length; 546 work->frags[i].mr = mr; 547 } 548 549 queue_work(system_unbound_wq, &work->work); 550 551 return 0; 552 553 err: 554 /* rollback reference counts for the invalid request */ 555 while (i > 0) { 556 i--; 557 rxe_put(work->frags[i].mr); 558 } 559 560 kvfree(work); 561 562 return PTR_ERR(mr); 563} 564 565int rxe_ib_advise_mr(struct ib_pd *ibpd, 566 enum ib_uverbs_advise_mr_advice advice, 567 u32 flags, 568 struct ib_sge *sg_list, 569 u32 num_sge, 570 struct uverbs_attr_bundle *attrs) 571{ 572 if (advice != IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH && 573 advice != IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_WRITE && 574 advice != IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_NO_FAULT) 575 return -EOPNOTSUPP; 576 577 return rxe_ib_advise_mr_prefetch(ibpd, advice, flags, 578 sg_list, num_sge); 579}
~/
Read-only file preview.