mmu.c (17535B)
1// SPDX-License-Identifier: GPL-2.0-only 2/************************************************************************** 3 * Copyright (c) 2007, Intel Corporation. 4 * 5 **************************************************************************/ 6 7#include <linux/highmem.h> 8 9#include "mmu.h" 10#include "psb_drv.h" 11#include "psb_reg.h" 12 13/* 14 * Code for the SGX MMU: 15 */ 16 17/* 18 * clflush on one processor only: 19 * clflush should apparently flush the cache line on all processors in an 20 * SMP system. 21 */ 22 23/* 24 * kmap atomic: 25 * The usage of the slots must be completely encapsulated within a spinlock, and 26 * no other functions that may be using the locks for other purposed may be 27 * called from within the locked region. 28 * Since the slots are per processor, this will guarantee that we are the only 29 * user. 30 */ 31 32/* 33 * TODO: Inserting ptes from an interrupt handler: 34 * This may be desirable for some SGX functionality where the GPU can fault in 35 * needed pages. For that, we need to make an atomic insert_pages function, that 36 * may fail. 37 * If it fails, the caller need to insert the page using a workqueue function, 38 * but on average it should be fast. 39 */ 40 41static inline uint32_t psb_mmu_pt_index(uint32_t offset) 42{ 43 return (offset >> PSB_PTE_SHIFT) & 0x3FF; 44} 45 46static inline uint32_t psb_mmu_pd_index(uint32_t offset) 47{ 48 return offset >> PSB_PDE_SHIFT; 49} 50 51static inline void psb_clflush(void *addr) 52{ 53 __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); 54} 55 56static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, void *addr) 57{ 58 if (!driver->has_clflush) 59 return; 60 61 mb(); 62 psb_clflush(addr); 63 mb(); 64} 65 66static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, int force) 67{ 68 struct drm_device *dev = driver->dev; 69 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 70 71 if (atomic_read(&driver->needs_tlbflush) || force) { 72 uint32_t val = PSB_RSGX32(PSB_CR_BIF_CTRL); 73 PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL); 74 75 /* Make sure data cache is turned off before enabling it */ 76 wmb(); 77 PSB_WSGX32(val & ~_PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL); 78 (void)PSB_RSGX32(PSB_CR_BIF_CTRL); 79 if (driver->msvdx_mmu_invaldc) 80 atomic_set(driver->msvdx_mmu_invaldc, 1); 81 } 82 atomic_set(&driver->needs_tlbflush, 0); 83} 84 85#if 0 86static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) 87{ 88 down_write(&driver->sem); 89 psb_mmu_flush_pd_locked(driver, force); 90 up_write(&driver->sem); 91} 92#endif 93 94void psb_mmu_flush(struct psb_mmu_driver *driver) 95{ 96 struct drm_device *dev = driver->dev; 97 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 98 uint32_t val; 99 100 down_write(&driver->sem); 101 val = PSB_RSGX32(PSB_CR_BIF_CTRL); 102 if (atomic_read(&driver->needs_tlbflush)) 103 PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL); 104 else 105 PSB_WSGX32(val | _PSB_CB_CTRL_FLUSH, PSB_CR_BIF_CTRL); 106 107 /* Make sure data cache is turned off and MMU is flushed before 108 restoring bank interface control register */ 109 wmb(); 110 PSB_WSGX32(val & ~(_PSB_CB_CTRL_FLUSH | _PSB_CB_CTRL_INVALDC), 111 PSB_CR_BIF_CTRL); 112 (void)PSB_RSGX32(PSB_CR_BIF_CTRL); 113 114 atomic_set(&driver->needs_tlbflush, 0); 115 if (driver->msvdx_mmu_invaldc) 116 atomic_set(driver->msvdx_mmu_invaldc, 1); 117 up_write(&driver->sem); 118} 119 120void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) 121{ 122 struct drm_device *dev = pd->driver->dev; 123 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 124 uint32_t offset = (hw_context == 0) ? PSB_CR_BIF_DIR_LIST_BASE0 : 125 PSB_CR_BIF_DIR_LIST_BASE1 + hw_context * 4; 126 127 down_write(&pd->driver->sem); 128 PSB_WSGX32(page_to_pfn(pd->p) << PAGE_SHIFT, offset); 129 wmb(); 130 psb_mmu_flush_pd_locked(pd->driver, 1); 131 pd->hw_context = hw_context; 132 up_write(&pd->driver->sem); 133 134} 135 136static inline unsigned long psb_pd_addr_end(unsigned long addr, 137 unsigned long end) 138{ 139 addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; 140 return (addr < end) ? addr : end; 141} 142 143static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type) 144{ 145 uint32_t mask = PSB_PTE_VALID; 146 147 if (type & PSB_MMU_CACHED_MEMORY) 148 mask |= PSB_PTE_CACHED; 149 if (type & PSB_MMU_RO_MEMORY) 150 mask |= PSB_PTE_RO; 151 if (type & PSB_MMU_WO_MEMORY) 152 mask |= PSB_PTE_WO; 153 154 return (pfn << PAGE_SHIFT) | mask; 155} 156 157struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, 158 int trap_pagefaults, int invalid_type) 159{ 160 struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL); 161 uint32_t *v; 162 int i; 163 164 if (!pd) 165 return NULL; 166 167 pd->p = alloc_page(GFP_DMA32); 168 if (!pd->p) 169 goto out_err1; 170 pd->dummy_pt = alloc_page(GFP_DMA32); 171 if (!pd->dummy_pt) 172 goto out_err2; 173 pd->dummy_page = alloc_page(GFP_DMA32); 174 if (!pd->dummy_page) 175 goto out_err3; 176 177 if (!trap_pagefaults) { 178 pd->invalid_pde = psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), 179 invalid_type); 180 pd->invalid_pte = psb_mmu_mask_pte(page_to_pfn(pd->dummy_page), 181 invalid_type); 182 } else { 183 pd->invalid_pde = 0; 184 pd->invalid_pte = 0; 185 } 186 187 v = kmap_local_page(pd->dummy_pt); 188 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) 189 v[i] = pd->invalid_pte; 190 191 kunmap_local(v); 192 193 v = kmap_local_page(pd->p); 194 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) 195 v[i] = pd->invalid_pde; 196 197 kunmap_local(v); 198 199 clear_page(kmap(pd->dummy_page)); 200 kunmap(pd->dummy_page); 201 202 pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024); 203 if (!pd->tables) 204 goto out_err4; 205 206 pd->hw_context = -1; 207 pd->pd_mask = PSB_PTE_VALID; 208 pd->driver = driver; 209 210 return pd; 211 212out_err4: 213 __free_page(pd->dummy_page); 214out_err3: 215 __free_page(pd->dummy_pt); 216out_err2: 217 __free_page(pd->p); 218out_err1: 219 kfree(pd); 220 return NULL; 221} 222 223static void psb_mmu_free_pt(struct psb_mmu_pt *pt) 224{ 225 __free_page(pt->p); 226 kfree(pt); 227} 228 229void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) 230{ 231 struct psb_mmu_driver *driver = pd->driver; 232 struct drm_device *dev = driver->dev; 233 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 234 struct psb_mmu_pt *pt; 235 int i; 236 237 down_write(&driver->sem); 238 if (pd->hw_context != -1) { 239 PSB_WSGX32(0, PSB_CR_BIF_DIR_LIST_BASE0 + pd->hw_context * 4); 240 psb_mmu_flush_pd_locked(driver, 1); 241 } 242 243 /* Should take the spinlock here, but we don't need to do that 244 since we have the semaphore in write mode. */ 245 246 for (i = 0; i < 1024; ++i) { 247 pt = pd->tables[i]; 248 if (pt) 249 psb_mmu_free_pt(pt); 250 } 251 252 vfree(pd->tables); 253 __free_page(pd->dummy_page); 254 __free_page(pd->dummy_pt); 255 __free_page(pd->p); 256 kfree(pd); 257 up_write(&driver->sem); 258} 259 260static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) 261{ 262 struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL); 263 void *v; 264 uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT; 265 uint32_t clflush_count = PAGE_SIZE / clflush_add; 266 spinlock_t *lock = &pd->driver->lock; 267 uint8_t *clf; 268 uint32_t *ptes; 269 int i; 270 271 if (!pt) 272 return NULL; 273 274 pt->p = alloc_page(GFP_DMA32); 275 if (!pt->p) { 276 kfree(pt); 277 return NULL; 278 } 279 280 spin_lock(lock); 281 282 v = kmap_atomic(pt->p); 283 clf = (uint8_t *) v; 284 ptes = (uint32_t *) v; 285 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) 286 *ptes++ = pd->invalid_pte; 287 288 if (pd->driver->has_clflush && pd->hw_context != -1) { 289 mb(); 290 for (i = 0; i < clflush_count; ++i) { 291 psb_clflush(clf); 292 clf += clflush_add; 293 } 294 mb(); 295 } 296 kunmap_atomic(v); 297 spin_unlock(lock); 298 299 pt->count = 0; 300 pt->pd = pd; 301 pt->index = 0; 302 303 return pt; 304} 305 306static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, 307 unsigned long addr) 308{ 309 uint32_t index = psb_mmu_pd_index(addr); 310 struct psb_mmu_pt *pt; 311 uint32_t *v; 312 spinlock_t *lock = &pd->driver->lock; 313 314 spin_lock(lock); 315 pt = pd->tables[index]; 316 while (!pt) { 317 spin_unlock(lock); 318 pt = psb_mmu_alloc_pt(pd); 319 if (!pt) 320 return NULL; 321 spin_lock(lock); 322 323 if (pd->tables[index]) { 324 spin_unlock(lock); 325 psb_mmu_free_pt(pt); 326 spin_lock(lock); 327 pt = pd->tables[index]; 328 continue; 329 } 330 331 v = kmap_atomic(pd->p); 332 pd->tables[index] = pt; 333 v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask; 334 pt->index = index; 335 kunmap_atomic((void *) v); 336 337 if (pd->hw_context != -1) { 338 psb_mmu_clflush(pd->driver, (void *)&v[index]); 339 atomic_set(&pd->driver->needs_tlbflush, 1); 340 } 341 } 342 pt->v = kmap_atomic(pt->p); 343 return pt; 344} 345 346static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd, 347 unsigned long addr) 348{ 349 uint32_t index = psb_mmu_pd_index(addr); 350 struct psb_mmu_pt *pt; 351 spinlock_t *lock = &pd->driver->lock; 352 353 spin_lock(lock); 354 pt = pd->tables[index]; 355 if (!pt) { 356 spin_unlock(lock); 357 return NULL; 358 } 359 pt->v = kmap_atomic(pt->p); 360 return pt; 361} 362 363static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt) 364{ 365 struct psb_mmu_pd *pd = pt->pd; 366 uint32_t *v; 367 368 kunmap_atomic(pt->v); 369 if (pt->count == 0) { 370 v = kmap_atomic(pd->p); 371 v[pt->index] = pd->invalid_pde; 372 pd->tables[pt->index] = NULL; 373 374 if (pd->hw_context != -1) { 375 psb_mmu_clflush(pd->driver, (void *)&v[pt->index]); 376 atomic_set(&pd->driver->needs_tlbflush, 1); 377 } 378 kunmap_atomic(v); 379 spin_unlock(&pd->driver->lock); 380 psb_mmu_free_pt(pt); 381 return; 382 } 383 spin_unlock(&pd->driver->lock); 384} 385 386static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, unsigned long addr, 387 uint32_t pte) 388{ 389 pt->v[psb_mmu_pt_index(addr)] = pte; 390} 391 392static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, 393 unsigned long addr) 394{ 395 pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; 396} 397 398struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) 399{ 400 struct psb_mmu_pd *pd; 401 402 down_read(&driver->sem); 403 pd = driver->default_pd; 404 up_read(&driver->sem); 405 406 return pd; 407} 408 409void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) 410{ 411 struct drm_device *dev = driver->dev; 412 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 413 414 PSB_WSGX32(driver->bif_ctrl, PSB_CR_BIF_CTRL); 415 psb_mmu_free_pagedir(driver->default_pd); 416 kfree(driver); 417} 418 419struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev, 420 int trap_pagefaults, 421 int invalid_type, 422 atomic_t *msvdx_mmu_invaldc) 423{ 424 struct psb_mmu_driver *driver; 425 struct drm_psb_private *dev_priv = to_drm_psb_private(dev); 426 427 driver = kmalloc(sizeof(*driver), GFP_KERNEL); 428 429 if (!driver) 430 return NULL; 431 432 driver->dev = dev; 433 driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, 434 invalid_type); 435 if (!driver->default_pd) 436 goto out_err1; 437 438 spin_lock_init(&driver->lock); 439 init_rwsem(&driver->sem); 440 down_write(&driver->sem); 441 atomic_set(&driver->needs_tlbflush, 1); 442 driver->msvdx_mmu_invaldc = msvdx_mmu_invaldc; 443 444 driver->bif_ctrl = PSB_RSGX32(PSB_CR_BIF_CTRL); 445 PSB_WSGX32(driver->bif_ctrl | _PSB_CB_CTRL_CLEAR_FAULT, 446 PSB_CR_BIF_CTRL); 447 PSB_WSGX32(driver->bif_ctrl & ~_PSB_CB_CTRL_CLEAR_FAULT, 448 PSB_CR_BIF_CTRL); 449 450 driver->has_clflush = 0; 451 452 if (boot_cpu_has(X86_FEATURE_CLFLUSH)) { 453 uint32_t tfms, misc, cap0, cap4, clflush_size; 454 455 /* 456 * clflush size is determined at kernel setup for x86_64 but not 457 * for i386. We have to do it here. 458 */ 459 460 cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); 461 clflush_size = ((misc >> 8) & 0xff) * 8; 462 driver->has_clflush = 1; 463 driver->clflush_add = 464 PAGE_SIZE * clflush_size / sizeof(uint32_t); 465 driver->clflush_mask = driver->clflush_add - 1; 466 driver->clflush_mask = ~driver->clflush_mask; 467 } 468 469 up_write(&driver->sem); 470 return driver; 471 472out_err1: 473 kfree(driver); 474 return NULL; 475} 476 477static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, unsigned long address, 478 uint32_t num_pages, uint32_t desired_tile_stride, 479 uint32_t hw_tile_stride) 480{ 481 struct psb_mmu_pt *pt; 482 uint32_t rows = 1; 483 uint32_t i; 484 unsigned long addr; 485 unsigned long end; 486 unsigned long next; 487 unsigned long add; 488 unsigned long row_add; 489 unsigned long clflush_add = pd->driver->clflush_add; 490 unsigned long clflush_mask = pd->driver->clflush_mask; 491 492 if (!pd->driver->has_clflush) 493 return; 494 495 if (hw_tile_stride) 496 rows = num_pages / desired_tile_stride; 497 else 498 desired_tile_stride = num_pages; 499 500 add = desired_tile_stride << PAGE_SHIFT; 501 row_add = hw_tile_stride << PAGE_SHIFT; 502 mb(); 503 for (i = 0; i < rows; ++i) { 504 505 addr = address; 506 end = addr + add; 507 508 do { 509 next = psb_pd_addr_end(addr, end); 510 pt = psb_mmu_pt_map_lock(pd, addr); 511 if (!pt) 512 continue; 513 do { 514 psb_clflush(&pt->v[psb_mmu_pt_index(addr)]); 515 } while (addr += clflush_add, 516 (addr & clflush_mask) < next); 517 518 psb_mmu_pt_unmap_unlock(pt); 519 } while (addr = next, next != end); 520 address += row_add; 521 } 522 mb(); 523} 524 525void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, 526 unsigned long address, uint32_t num_pages) 527{ 528 struct psb_mmu_pt *pt; 529 unsigned long addr; 530 unsigned long end; 531 unsigned long next; 532 unsigned long f_address = address; 533 534 down_read(&pd->driver->sem); 535 536 addr = address; 537 end = addr + (num_pages << PAGE_SHIFT); 538 539 do { 540 next = psb_pd_addr_end(addr, end); 541 pt = psb_mmu_pt_alloc_map_lock(pd, addr); 542 if (!pt) 543 goto out; 544 do { 545 psb_mmu_invalidate_pte(pt, addr); 546 --pt->count; 547 } while (addr += PAGE_SIZE, addr < next); 548 psb_mmu_pt_unmap_unlock(pt); 549 550 } while (addr = next, next != end); 551 552out: 553 if (pd->hw_context != -1) 554 psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); 555 556 up_read(&pd->driver->sem); 557 558 if (pd->hw_context != -1) 559 psb_mmu_flush(pd->driver); 560 561 return; 562} 563 564void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address, 565 uint32_t num_pages, uint32_t desired_tile_stride, 566 uint32_t hw_tile_stride) 567{ 568 struct psb_mmu_pt *pt; 569 uint32_t rows = 1; 570 uint32_t i; 571 unsigned long addr; 572 unsigned long end; 573 unsigned long next; 574 unsigned long add; 575 unsigned long row_add; 576 unsigned long f_address = address; 577 578 if (hw_tile_stride) 579 rows = num_pages / desired_tile_stride; 580 else 581 desired_tile_stride = num_pages; 582 583 add = desired_tile_stride << PAGE_SHIFT; 584 row_add = hw_tile_stride << PAGE_SHIFT; 585 586 down_read(&pd->driver->sem); 587 588 /* Make sure we only need to flush this processor's cache */ 589 590 for (i = 0; i < rows; ++i) { 591 592 addr = address; 593 end = addr + add; 594 595 do { 596 next = psb_pd_addr_end(addr, end); 597 pt = psb_mmu_pt_map_lock(pd, addr); 598 if (!pt) 599 continue; 600 do { 601 psb_mmu_invalidate_pte(pt, addr); 602 --pt->count; 603 604 } while (addr += PAGE_SIZE, addr < next); 605 psb_mmu_pt_unmap_unlock(pt); 606 607 } while (addr = next, next != end); 608 address += row_add; 609 } 610 if (pd->hw_context != -1) 611 psb_mmu_flush_ptes(pd, f_address, num_pages, 612 desired_tile_stride, hw_tile_stride); 613 614 up_read(&pd->driver->sem); 615 616 if (pd->hw_context != -1) 617 psb_mmu_flush(pd->driver); 618} 619 620int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, 621 unsigned long address, uint32_t num_pages, 622 int type) 623{ 624 struct psb_mmu_pt *pt; 625 uint32_t pte; 626 unsigned long addr; 627 unsigned long end; 628 unsigned long next; 629 unsigned long f_address = address; 630 int ret = -ENOMEM; 631 632 down_read(&pd->driver->sem); 633 634 addr = address; 635 end = addr + (num_pages << PAGE_SHIFT); 636 637 do { 638 next = psb_pd_addr_end(addr, end); 639 pt = psb_mmu_pt_alloc_map_lock(pd, addr); 640 if (!pt) { 641 ret = -ENOMEM; 642 goto out; 643 } 644 do { 645 pte = psb_mmu_mask_pte(start_pfn++, type); 646 psb_mmu_set_pte(pt, addr, pte); 647 pt->count++; 648 } while (addr += PAGE_SIZE, addr < next); 649 psb_mmu_pt_unmap_unlock(pt); 650 651 } while (addr = next, next != end); 652 ret = 0; 653 654out: 655 if (pd->hw_context != -1) 656 psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); 657 658 up_read(&pd->driver->sem); 659 660 if (pd->hw_context != -1) 661 psb_mmu_flush(pd->driver); 662 663 return ret; 664} 665 666int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, 667 unsigned long address, uint32_t num_pages, 668 uint32_t desired_tile_stride, uint32_t hw_tile_stride, 669 int type) 670{ 671 struct psb_mmu_pt *pt; 672 uint32_t rows = 1; 673 uint32_t i; 674 uint32_t pte; 675 unsigned long addr; 676 unsigned long end; 677 unsigned long next; 678 unsigned long add; 679 unsigned long row_add; 680 unsigned long f_address = address; 681 int ret = -ENOMEM; 682 683 if (hw_tile_stride) { 684 if (num_pages % desired_tile_stride != 0) 685 return -EINVAL; 686 rows = num_pages / desired_tile_stride; 687 } else { 688 desired_tile_stride = num_pages; 689 } 690 691 add = desired_tile_stride << PAGE_SHIFT; 692 row_add = hw_tile_stride << PAGE_SHIFT; 693 694 down_read(&pd->driver->sem); 695 696 for (i = 0; i < rows; ++i) { 697 698 addr = address; 699 end = addr + add; 700 701 do { 702 next = psb_pd_addr_end(addr, end); 703 pt = psb_mmu_pt_alloc_map_lock(pd, addr); 704 if (!pt) 705 goto out; 706 do { 707 pte = psb_mmu_mask_pte(page_to_pfn(*pages++), 708 type); 709 psb_mmu_set_pte(pt, addr, pte); 710 pt->count++; 711 } while (addr += PAGE_SIZE, addr < next); 712 psb_mmu_pt_unmap_unlock(pt); 713 714 } while (addr = next, next != end); 715 716 address += row_add; 717 } 718 719 ret = 0; 720out: 721 if (pd->hw_context != -1) 722 psb_mmu_flush_ptes(pd, f_address, num_pages, 723 desired_tile_stride, hw_tile_stride); 724 725 up_read(&pd->driver->sem); 726 727 if (pd->hw_context != -1) 728 psb_mmu_flush(pd->driver); 729 730 return ret; 731} 732 733int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, 734 unsigned long *pfn) 735{ 736 int ret; 737 struct psb_mmu_pt *pt; 738 uint32_t tmp; 739 spinlock_t *lock = &pd->driver->lock; 740 741 down_read(&pd->driver->sem); 742 pt = psb_mmu_pt_map_lock(pd, virtual); 743 if (!pt) { 744 uint32_t *v; 745 746 spin_lock(lock); 747 v = kmap_atomic(pd->p); 748 tmp = v[psb_mmu_pd_index(virtual)]; 749 kunmap_atomic(v); 750 spin_unlock(lock); 751 752 if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) || 753 !(pd->invalid_pte & PSB_PTE_VALID)) { 754 ret = -EINVAL; 755 goto out; 756 } 757 ret = 0; 758 *pfn = pd->invalid_pte >> PAGE_SHIFT; 759 goto out; 760 } 761 tmp = pt->v[psb_mmu_pt_index(virtual)]; 762 if (!(tmp & PSB_PTE_VALID)) { 763 ret = -EINVAL; 764 } else { 765 ret = 0; 766 *pfn = tmp >> PAGE_SHIFT; 767 } 768 psb_mmu_pt_unmap_unlock(pt); 769out: 770 up_read(&pd->driver->sem); 771 return ret; 772}