mmu.c 18 KB

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