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