tlb.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  3. * Licensed under the GPL
  4. */
  5. #include <linux/mm.h>
  6. #include <linux/module.h>
  7. #include <linux/sched.h>
  8. #include <asm/pgtable.h>
  9. #include <asm/tlbflush.h>
  10. #include <as-layout.h>
  11. #include <mem_user.h>
  12. #include <os.h>
  13. #include <skas.h>
  14. struct host_vm_change {
  15. struct host_vm_op {
  16. enum { NONE, MMAP, MUNMAP, MPROTECT } type;
  17. union {
  18. struct {
  19. unsigned long addr;
  20. unsigned long len;
  21. unsigned int prot;
  22. int fd;
  23. __u64 offset;
  24. } mmap;
  25. struct {
  26. unsigned long addr;
  27. unsigned long len;
  28. } munmap;
  29. struct {
  30. unsigned long addr;
  31. unsigned long len;
  32. unsigned int prot;
  33. } mprotect;
  34. } u;
  35. } ops[1];
  36. int index;
  37. struct mm_id *id;
  38. void *data;
  39. int force;
  40. };
  41. #define INIT_HVC(mm, force) \
  42. ((struct host_vm_change) \
  43. { .ops = { { .type = NONE } }, \
  44. .id = &mm->context.id, \
  45. .data = NULL, \
  46. .index = 0, \
  47. .force = force })
  48. static int do_ops(struct host_vm_change *hvc, int end,
  49. int finished)
  50. {
  51. struct host_vm_op *op;
  52. int i, ret = 0;
  53. for (i = 0; i < end && !ret; i++) {
  54. op = &hvc->ops[i];
  55. switch (op->type) {
  56. case MMAP:
  57. ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
  58. op->u.mmap.prot, op->u.mmap.fd,
  59. op->u.mmap.offset, finished, &hvc->data);
  60. break;
  61. case MUNMAP:
  62. ret = unmap(hvc->id, op->u.munmap.addr,
  63. op->u.munmap.len, finished, &hvc->data);
  64. break;
  65. case MPROTECT:
  66. ret = protect(hvc->id, op->u.mprotect.addr,
  67. op->u.mprotect.len, op->u.mprotect.prot,
  68. finished, &hvc->data);
  69. break;
  70. default:
  71. printk(KERN_ERR "Unknown op type %d in do_ops\n",
  72. op->type);
  73. BUG();
  74. break;
  75. }
  76. }
  77. return ret;
  78. }
  79. static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
  80. unsigned int prot, struct host_vm_change *hvc)
  81. {
  82. __u64 offset;
  83. struct host_vm_op *last;
  84. int fd, ret = 0;
  85. fd = phys_mapping(phys, &offset);
  86. if (hvc->index != 0) {
  87. last = &hvc->ops[hvc->index - 1];
  88. if ((last->type == MMAP) &&
  89. (last->u.mmap.addr + last->u.mmap.len == virt) &&
  90. (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&
  91. (last->u.mmap.offset + last->u.mmap.len == offset)) {
  92. last->u.mmap.len += len;
  93. return 0;
  94. }
  95. }
  96. if (hvc->index == ARRAY_SIZE(hvc->ops)) {
  97. ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
  98. hvc->index = 0;
  99. }
  100. hvc->ops[hvc->index++] = ((struct host_vm_op)
  101. { .type = MMAP,
  102. .u = { .mmap = { .addr = virt,
  103. .len = len,
  104. .prot = prot,
  105. .fd = fd,
  106. .offset = offset }
  107. } });
  108. return ret;
  109. }
  110. static int add_munmap(unsigned long addr, unsigned long len,
  111. struct host_vm_change *hvc)
  112. {
  113. struct host_vm_op *last;
  114. int ret = 0;
  115. if (hvc->index != 0) {
  116. last = &hvc->ops[hvc->index - 1];
  117. if ((last->type == MUNMAP) &&
  118. (last->u.munmap.addr + last->u.mmap.len == addr)) {
  119. last->u.munmap.len += len;
  120. return 0;
  121. }
  122. }
  123. if (hvc->index == ARRAY_SIZE(hvc->ops)) {
  124. ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
  125. hvc->index = 0;
  126. }
  127. hvc->ops[hvc->index++] = ((struct host_vm_op)
  128. { .type = MUNMAP,
  129. .u = { .munmap = { .addr = addr,
  130. .len = len } } });
  131. return ret;
  132. }
  133. static int add_mprotect(unsigned long addr, unsigned long len,
  134. unsigned int prot, struct host_vm_change *hvc)
  135. {
  136. struct host_vm_op *last;
  137. int ret = 0;
  138. if (hvc->index != 0) {
  139. last = &hvc->ops[hvc->index - 1];
  140. if ((last->type == MPROTECT) &&
  141. (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
  142. (last->u.mprotect.prot == prot)) {
  143. last->u.mprotect.len += len;
  144. return 0;
  145. }
  146. }
  147. if (hvc->index == ARRAY_SIZE(hvc->ops)) {
  148. ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0);
  149. hvc->index = 0;
  150. }
  151. hvc->ops[hvc->index++] = ((struct host_vm_op)
  152. { .type = MPROTECT,
  153. .u = { .mprotect = { .addr = addr,
  154. .len = len,
  155. .prot = prot } } });
  156. return ret;
  157. }
  158. #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
  159. static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
  160. unsigned long end,
  161. struct host_vm_change *hvc)
  162. {
  163. pte_t *pte;
  164. int r, w, x, prot, ret = 0;
  165. pte = pte_offset_kernel(pmd, addr);
  166. do {
  167. if ((addr >= STUB_START) && (addr < STUB_END))
  168. continue;
  169. r = pte_read(*pte);
  170. w = pte_write(*pte);
  171. x = pte_exec(*pte);
  172. if (!pte_young(*pte)) {
  173. r = 0;
  174. w = 0;
  175. } else if (!pte_dirty(*pte))
  176. w = 0;
  177. prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
  178. (x ? UM_PROT_EXEC : 0));
  179. if (hvc->force || pte_newpage(*pte)) {
  180. if (pte_present(*pte))
  181. ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
  182. PAGE_SIZE, prot, hvc);
  183. else
  184. ret = add_munmap(addr, PAGE_SIZE, hvc);
  185. } else if (pte_newprot(*pte))
  186. ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
  187. *pte = pte_mkuptodate(*pte);
  188. } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
  189. return ret;
  190. }
  191. static inline int update_pmd_range(pud_t *pud, unsigned long addr,
  192. unsigned long end,
  193. struct host_vm_change *hvc)
  194. {
  195. pmd_t *pmd;
  196. unsigned long next;
  197. int ret = 0;
  198. pmd = pmd_offset(pud, addr);
  199. do {
  200. next = pmd_addr_end(addr, end);
  201. if (!pmd_present(*pmd)) {
  202. if (hvc->force || pmd_newpage(*pmd)) {
  203. ret = add_munmap(addr, next - addr, hvc);
  204. pmd_mkuptodate(*pmd);
  205. }
  206. }
  207. else ret = update_pte_range(pmd, addr, next, hvc);
  208. } while (pmd++, addr = next, ((addr < end) && !ret));
  209. return ret;
  210. }
  211. static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
  212. unsigned long end,
  213. struct host_vm_change *hvc)
  214. {
  215. pud_t *pud;
  216. unsigned long next;
  217. int ret = 0;
  218. pud = pud_offset(pgd, addr);
  219. do {
  220. next = pud_addr_end(addr, end);
  221. if (!pud_present(*pud)) {
  222. if (hvc->force || pud_newpage(*pud)) {
  223. ret = add_munmap(addr, next - addr, hvc);
  224. pud_mkuptodate(*pud);
  225. }
  226. }
  227. else ret = update_pmd_range(pud, addr, next, hvc);
  228. } while (pud++, addr = next, ((addr < end) && !ret));
  229. return ret;
  230. }
  231. void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
  232. unsigned long end_addr, int force)
  233. {
  234. pgd_t *pgd;
  235. struct host_vm_change hvc;
  236. unsigned long addr = start_addr, next;
  237. int ret = 0;
  238. hvc = INIT_HVC(mm, force);
  239. pgd = pgd_offset(mm, addr);
  240. do {
  241. next = pgd_addr_end(addr, end_addr);
  242. if (!pgd_present(*pgd)) {
  243. if (force || pgd_newpage(*pgd)) {
  244. ret = add_munmap(addr, next - addr, &hvc);
  245. pgd_mkuptodate(*pgd);
  246. }
  247. }
  248. else ret = update_pud_range(pgd, addr, next, &hvc);
  249. } while (pgd++, addr = next, ((addr < end_addr) && !ret));
  250. if (!ret)
  251. ret = do_ops(&hvc, hvc.index, 1);
  252. /* This is not an else because ret is modified above */
  253. if (ret) {
  254. printk(KERN_ERR "fix_range_common: failed, killing current "
  255. "process\n");
  256. force_sig(SIGKILL, current);
  257. }
  258. }
  259. static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
  260. {
  261. struct mm_struct *mm;
  262. pgd_t *pgd;
  263. pud_t *pud;
  264. pmd_t *pmd;
  265. pte_t *pte;
  266. unsigned long addr, last;
  267. int updated = 0, err;
  268. mm = &init_mm;
  269. for (addr = start; addr < end;) {
  270. pgd = pgd_offset(mm, addr);
  271. if (!pgd_present(*pgd)) {
  272. last = ADD_ROUND(addr, PGDIR_SIZE);
  273. if (last > end)
  274. last = end;
  275. if (pgd_newpage(*pgd)) {
  276. updated = 1;
  277. err = os_unmap_memory((void *) addr,
  278. last - addr);
  279. if (err < 0)
  280. panic("munmap failed, errno = %d\n",
  281. -err);
  282. }
  283. addr = last;
  284. continue;
  285. }
  286. pud = pud_offset(pgd, addr);
  287. if (!pud_present(*pud)) {
  288. last = ADD_ROUND(addr, PUD_SIZE);
  289. if (last > end)
  290. last = end;
  291. if (pud_newpage(*pud)) {
  292. updated = 1;
  293. err = os_unmap_memory((void *) addr,
  294. last - addr);
  295. if (err < 0)
  296. panic("munmap failed, errno = %d\n",
  297. -err);
  298. }
  299. addr = last;
  300. continue;
  301. }
  302. pmd = pmd_offset(pud, addr);
  303. if (!pmd_present(*pmd)) {
  304. last = ADD_ROUND(addr, PMD_SIZE);
  305. if (last > end)
  306. last = end;
  307. if (pmd_newpage(*pmd)) {
  308. updated = 1;
  309. err = os_unmap_memory((void *) addr,
  310. last - addr);
  311. if (err < 0)
  312. panic("munmap failed, errno = %d\n",
  313. -err);
  314. }
  315. addr = last;
  316. continue;
  317. }
  318. pte = pte_offset_kernel(pmd, addr);
  319. if (!pte_present(*pte) || pte_newpage(*pte)) {
  320. updated = 1;
  321. err = os_unmap_memory((void *) addr,
  322. PAGE_SIZE);
  323. if (err < 0)
  324. panic("munmap failed, errno = %d\n",
  325. -err);
  326. if (pte_present(*pte))
  327. map_memory(addr,
  328. pte_val(*pte) & PAGE_MASK,
  329. PAGE_SIZE, 1, 1, 1);
  330. }
  331. else if (pte_newprot(*pte)) {
  332. updated = 1;
  333. os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
  334. }
  335. addr += PAGE_SIZE;
  336. }
  337. return updated;
  338. }
  339. void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
  340. {
  341. pgd_t *pgd;
  342. pud_t *pud;
  343. pmd_t *pmd;
  344. pte_t *pte;
  345. struct mm_struct *mm = vma->vm_mm;
  346. void *flush = NULL;
  347. int r, w, x, prot, err = 0;
  348. struct mm_id *mm_id;
  349. address &= PAGE_MASK;
  350. pgd = pgd_offset(mm, address);
  351. if (!pgd_present(*pgd))
  352. goto kill;
  353. pud = pud_offset(pgd, address);
  354. if (!pud_present(*pud))
  355. goto kill;
  356. pmd = pmd_offset(pud, address);
  357. if (!pmd_present(*pmd))
  358. goto kill;
  359. pte = pte_offset_kernel(pmd, address);
  360. r = pte_read(*pte);
  361. w = pte_write(*pte);
  362. x = pte_exec(*pte);
  363. if (!pte_young(*pte)) {
  364. r = 0;
  365. w = 0;
  366. } else if (!pte_dirty(*pte)) {
  367. w = 0;
  368. }
  369. mm_id = &mm->context.id;
  370. prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
  371. (x ? UM_PROT_EXEC : 0));
  372. if (pte_newpage(*pte)) {
  373. if (pte_present(*pte)) {
  374. unsigned long long offset;
  375. int fd;
  376. fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
  377. err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
  378. 1, &flush);
  379. }
  380. else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
  381. }
  382. else if (pte_newprot(*pte))
  383. err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
  384. if (err)
  385. goto kill;
  386. *pte = pte_mkuptodate(*pte);
  387. return;
  388. kill:
  389. printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address);
  390. force_sig(SIGKILL, current);
  391. }
  392. pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
  393. {
  394. return pgd_offset(mm, address);
  395. }
  396. pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
  397. {
  398. return pud_offset(pgd, address);
  399. }
  400. pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
  401. {
  402. return pmd_offset(pud, address);
  403. }
  404. pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
  405. {
  406. return pte_offset_kernel(pmd, address);
  407. }
  408. pte_t *addr_pte(struct task_struct *task, unsigned long addr)
  409. {
  410. pgd_t *pgd = pgd_offset(task->mm, addr);
  411. pud_t *pud = pud_offset(pgd, addr);
  412. pmd_t *pmd = pmd_offset(pud, addr);
  413. return pte_offset_map(pmd, addr);
  414. }
  415. void flush_tlb_all(void)
  416. {
  417. flush_tlb_mm(current->mm);
  418. }
  419. void flush_tlb_kernel_range(unsigned long start, unsigned long end)
  420. {
  421. flush_tlb_kernel_range_common(start, end);
  422. }
  423. void flush_tlb_kernel_vm(void)
  424. {
  425. flush_tlb_kernel_range_common(start_vm, end_vm);
  426. }
  427. void __flush_tlb_one(unsigned long addr)
  428. {
  429. flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
  430. }
  431. static void fix_range(struct mm_struct *mm, unsigned long start_addr,
  432. unsigned long end_addr, int force)
  433. {
  434. fix_range_common(mm, start_addr, end_addr, force);
  435. }
  436. void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
  437. unsigned long end)
  438. {
  439. if (vma->vm_mm == NULL)
  440. flush_tlb_kernel_range_common(start, end);
  441. else fix_range(vma->vm_mm, start, end, 0);
  442. }
  443. EXPORT_SYMBOL(flush_tlb_range);
  444. void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
  445. unsigned long end)
  446. {
  447. /*
  448. * Don't bother flushing if this address space is about to be
  449. * destroyed.
  450. */
  451. if (atomic_read(&mm->mm_users) == 0)
  452. return;
  453. fix_range(mm, start, end, 0);
  454. }
  455. void flush_tlb_mm(struct mm_struct *mm)
  456. {
  457. struct vm_area_struct *vma = mm->mmap;
  458. while (vma != NULL) {
  459. fix_range(mm, vma->vm_start, vma->vm_end, 0);
  460. vma = vma->vm_next;
  461. }
  462. }
  463. void force_flush_all(void)
  464. {
  465. struct mm_struct *mm = current->mm;
  466. struct vm_area_struct *vma = mm->mmap;
  467. while (vma != NULL) {
  468. fix_range(mm, vma->vm_start, vma->vm_end, 1);
  469. vma = vma->vm_next;
  470. }
  471. }