mmu.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  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, KM_USER0);
  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, KM_USER0);
  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. 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, KM_USER0);
  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, KM_USER0);
  286. spin_unlock(lock);
  287. pt->count = 0;
  288. pt->pd = pd;
  289. pt->index = 0;
  290. return pt;
  291. }
  292. 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, KM_USER0);
  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, KM_USER0);
  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, KM_USER0);
  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, KM_USER0);
  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, KM_USER0);
  347. if (pt->count == 0) {
  348. v = kmap_atomic(pd->p, KM_USER0);
  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, KM_USER0);
  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, KM_USER0);
  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, KM_USER0);
  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. /* Returns the physical address of the PD shared by sgx/msvdx */
  407. uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
  408. {
  409. struct psb_mmu_pd *pd;
  410. pd = psb_mmu_get_default_pd(driver);
  411. return page_to_pfn(pd->p) << PAGE_SHIFT;
  412. }
  413. void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
  414. {
  415. psb_mmu_free_pagedir(driver->default_pd);
  416. kfree(driver);
  417. }
  418. struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
  419. int trap_pagefaults,
  420. int invalid_type,
  421. struct drm_psb_private *dev_priv)
  422. {
  423. struct psb_mmu_driver *driver;
  424. driver = kmalloc(sizeof(*driver), GFP_KERNEL);
  425. if (!driver)
  426. return NULL;
  427. driver->dev_priv = dev_priv;
  428. driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
  429. invalid_type);
  430. if (!driver->default_pd)
  431. goto out_err1;
  432. spin_lock_init(&driver->lock);
  433. init_rwsem(&driver->sem);
  434. down_write(&driver->sem);
  435. driver->register_map = registers;
  436. atomic_set(&driver->needs_tlbflush, 1);
  437. driver->has_clflush = 0;
  438. if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
  439. uint32_t tfms, misc, cap0, cap4, clflush_size;
  440. /*
  441. * clflush size is determined at kernel setup for x86_64
  442. * but not for i386. We have to do it here.
  443. */
  444. cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
  445. clflush_size = ((misc >> 8) & 0xff) * 8;
  446. driver->has_clflush = 1;
  447. driver->clflush_add =
  448. PAGE_SIZE * clflush_size / sizeof(uint32_t);
  449. driver->clflush_mask = driver->clflush_add - 1;
  450. driver->clflush_mask = ~driver->clflush_mask;
  451. }
  452. up_write(&driver->sem);
  453. return driver;
  454. out_err1:
  455. kfree(driver);
  456. return NULL;
  457. }
  458. static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
  459. unsigned long address, uint32_t num_pages,
  460. uint32_t desired_tile_stride,
  461. uint32_t hw_tile_stride)
  462. {
  463. struct psb_mmu_pt *pt;
  464. uint32_t rows = 1;
  465. uint32_t i;
  466. unsigned long addr;
  467. unsigned long end;
  468. unsigned long next;
  469. unsigned long add;
  470. unsigned long row_add;
  471. unsigned long clflush_add = pd->driver->clflush_add;
  472. unsigned long clflush_mask = pd->driver->clflush_mask;
  473. if (!pd->driver->has_clflush) {
  474. /*ttm_tt_cache_flush(&pd->p, num_pages);*/
  475. psb_pages_clflush(pd->driver, &pd->p, num_pages);
  476. return;
  477. }
  478. if (hw_tile_stride)
  479. rows = num_pages / desired_tile_stride;
  480. else
  481. desired_tile_stride = num_pages;
  482. add = desired_tile_stride << PAGE_SHIFT;
  483. row_add = hw_tile_stride << PAGE_SHIFT;
  484. mb();
  485. for (i = 0; i < rows; ++i) {
  486. addr = address;
  487. end = addr + add;
  488. do {
  489. next = psb_pd_addr_end(addr, end);
  490. pt = psb_mmu_pt_map_lock(pd, addr);
  491. if (!pt)
  492. continue;
  493. do {
  494. psb_clflush(&pt->v
  495. [psb_mmu_pt_index(addr)]);
  496. } while (addr +=
  497. clflush_add,
  498. (addr & clflush_mask) < next);
  499. psb_mmu_pt_unmap_unlock(pt);
  500. } while (addr = next, next != end);
  501. address += row_add;
  502. }
  503. mb();
  504. }
  505. void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
  506. unsigned long address, uint32_t num_pages)
  507. {
  508. struct psb_mmu_pt *pt;
  509. unsigned long addr;
  510. unsigned long end;
  511. unsigned long next;
  512. unsigned long f_address = address;
  513. down_read(&pd->driver->sem);
  514. addr = address;
  515. end = addr + (num_pages << PAGE_SHIFT);
  516. do {
  517. next = psb_pd_addr_end(addr, end);
  518. pt = psb_mmu_pt_alloc_map_lock(pd, addr);
  519. if (!pt)
  520. goto out;
  521. do {
  522. psb_mmu_invalidate_pte(pt, addr);
  523. --pt->count;
  524. } while (addr += PAGE_SIZE, addr < next);
  525. psb_mmu_pt_unmap_unlock(pt);
  526. } while (addr = next, next != end);
  527. out:
  528. if (pd->hw_context != -1)
  529. psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
  530. up_read(&pd->driver->sem);
  531. if (pd->hw_context != -1)
  532. psb_mmu_flush(pd->driver, 0);
  533. return;
  534. }
  535. void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
  536. uint32_t num_pages, uint32_t desired_tile_stride,
  537. uint32_t hw_tile_stride)
  538. {
  539. struct psb_mmu_pt *pt;
  540. uint32_t rows = 1;
  541. uint32_t i;
  542. unsigned long addr;
  543. unsigned long end;
  544. unsigned long next;
  545. unsigned long add;
  546. unsigned long row_add;
  547. unsigned long f_address = address;
  548. if (hw_tile_stride)
  549. rows = num_pages / desired_tile_stride;
  550. else
  551. desired_tile_stride = num_pages;
  552. add = desired_tile_stride << PAGE_SHIFT;
  553. row_add = hw_tile_stride << PAGE_SHIFT;
  554. /* down_read(&pd->driver->sem); */
  555. /* Make sure we only need to flush this processor's cache */
  556. for (i = 0; i < rows; ++i) {
  557. addr = address;
  558. end = addr + add;
  559. do {
  560. next = psb_pd_addr_end(addr, end);
  561. pt = psb_mmu_pt_map_lock(pd, addr);
  562. if (!pt)
  563. continue;
  564. do {
  565. psb_mmu_invalidate_pte(pt, addr);
  566. --pt->count;
  567. } while (addr += PAGE_SIZE, addr < next);
  568. psb_mmu_pt_unmap_unlock(pt);
  569. } while (addr = next, next != end);
  570. address += row_add;
  571. }
  572. if (pd->hw_context != -1)
  573. psb_mmu_flush_ptes(pd, f_address, num_pages,
  574. desired_tile_stride, hw_tile_stride);
  575. /* up_read(&pd->driver->sem); */
  576. if (pd->hw_context != -1)
  577. psb_mmu_flush(pd->driver, 0);
  578. }
  579. int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
  580. unsigned long address, uint32_t num_pages,
  581. int type)
  582. {
  583. struct psb_mmu_pt *pt;
  584. uint32_t pte;
  585. unsigned long addr;
  586. unsigned long end;
  587. unsigned long next;
  588. unsigned long f_address = address;
  589. int ret = 0;
  590. down_read(&pd->driver->sem);
  591. addr = address;
  592. end = addr + (num_pages << PAGE_SHIFT);
  593. do {
  594. next = psb_pd_addr_end(addr, end);
  595. pt = psb_mmu_pt_alloc_map_lock(pd, addr);
  596. if (!pt) {
  597. ret = -ENOMEM;
  598. goto out;
  599. }
  600. do {
  601. pte = psb_mmu_mask_pte(start_pfn++, type);
  602. psb_mmu_set_pte(pt, addr, pte);
  603. pt->count++;
  604. } while (addr += PAGE_SIZE, addr < next);
  605. psb_mmu_pt_unmap_unlock(pt);
  606. } while (addr = next, next != end);
  607. out:
  608. if (pd->hw_context != -1)
  609. psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
  610. up_read(&pd->driver->sem);
  611. if (pd->hw_context != -1)
  612. psb_mmu_flush(pd->driver, 1);
  613. return ret;
  614. }
  615. int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
  616. unsigned long address, uint32_t num_pages,
  617. uint32_t desired_tile_stride,
  618. uint32_t hw_tile_stride, int type)
  619. {
  620. struct psb_mmu_pt *pt;
  621. uint32_t rows = 1;
  622. uint32_t i;
  623. uint32_t pte;
  624. unsigned long addr;
  625. unsigned long end;
  626. unsigned long next;
  627. unsigned long add;
  628. unsigned long row_add;
  629. unsigned long f_address = address;
  630. int ret = 0;
  631. if (hw_tile_stride) {
  632. if (num_pages % desired_tile_stride != 0)
  633. return -EINVAL;
  634. rows = num_pages / desired_tile_stride;
  635. } else {
  636. desired_tile_stride = num_pages;
  637. }
  638. add = desired_tile_stride << PAGE_SHIFT;
  639. row_add = hw_tile_stride << PAGE_SHIFT;
  640. down_read(&pd->driver->sem);
  641. for (i = 0; i < rows; ++i) {
  642. addr = address;
  643. end = addr + add;
  644. do {
  645. next = psb_pd_addr_end(addr, end);
  646. pt = psb_mmu_pt_alloc_map_lock(pd, addr);
  647. if (!pt) {
  648. ret = -ENOMEM;
  649. goto out;
  650. }
  651. do {
  652. pte =
  653. psb_mmu_mask_pte(page_to_pfn(*pages++),
  654. type);
  655. psb_mmu_set_pte(pt, addr, pte);
  656. pt->count++;
  657. } while (addr += PAGE_SIZE, addr < next);
  658. psb_mmu_pt_unmap_unlock(pt);
  659. } while (addr = next, next != end);
  660. address += row_add;
  661. }
  662. out:
  663. if (pd->hw_context != -1)
  664. psb_mmu_flush_ptes(pd, f_address, num_pages,
  665. desired_tile_stride, hw_tile_stride);
  666. up_read(&pd->driver->sem);
  667. if (pd->hw_context != -1)
  668. psb_mmu_flush(pd->driver, 1);
  669. return ret;
  670. }
  671. int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
  672. unsigned long *pfn)
  673. {
  674. int ret;
  675. struct psb_mmu_pt *pt;
  676. uint32_t tmp;
  677. spinlock_t *lock = &pd->driver->lock;
  678. down_read(&pd->driver->sem);
  679. pt = psb_mmu_pt_map_lock(pd, virtual);
  680. if (!pt) {
  681. uint32_t *v;
  682. spin_lock(lock);
  683. v = kmap_atomic(pd->p, KM_USER0);
  684. tmp = v[psb_mmu_pd_index(virtual)];
  685. kunmap_atomic(v, KM_USER0);
  686. spin_unlock(lock);
  687. if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
  688. !(pd->invalid_pte & PSB_PTE_VALID)) {
  689. ret = -EINVAL;
  690. goto out;
  691. }
  692. ret = 0;
  693. *pfn = pd->invalid_pte >> PAGE_SHIFT;
  694. goto out;
  695. }
  696. tmp = pt->v[psb_mmu_pt_index(virtual)];
  697. if (!(tmp & PSB_PTE_VALID)) {
  698. ret = -EINVAL;
  699. } else {
  700. ret = 0;
  701. *pfn = tmp >> PAGE_SHIFT;
  702. }
  703. psb_mmu_pt_unmap_unlock(pt);
  704. out:
  705. up_read(&pd->driver->sem);
  706. return ret;
  707. }