mmu.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "arm.h"
  7. #define L1X(va) FEXT((va), 20, 12)
  8. #define L2X(va) FEXT((va), 12, 8)
  9. enum {
  10. L1lo = UZERO/MiB, /* L1X(UZERO)? */
  11. L1hi = (USTKTOP+MiB-1)/MiB, /* L1X(USTKTOP+MiB-1)? */
  12. };
  13. #define ISHOLE(pte) ((pte) == 0)
  14. /* dump level 1 page table at virtual addr l1 */
  15. void
  16. mmudump(PTE *l1)
  17. {
  18. int i, type, rngtype;
  19. uintptr pa, startva, startpa;
  20. uvlong va, endva;
  21. PTE pte;
  22. print("\n");
  23. endva = startva = startpa = 0;
  24. rngtype = 0;
  25. /* dump first level of ptes */
  26. for (va = i = 0; i < 4096; i++) {
  27. pte = l1[i];
  28. pa = pte & ~(MB - 1);
  29. type = pte & (Fine|Section|Coarse);
  30. if (ISHOLE(pte)) {
  31. if (endva != 0) { /* open range? close it */
  32. print("l1 maps va (%#lux-%#llux) -> pa %#lux type %#ux\n",
  33. startva, endva-1, startpa, rngtype);
  34. endva = 0;
  35. }
  36. } else {
  37. if (endva == 0) { /* no open range? start one */
  38. startva = va;
  39. startpa = pa;
  40. rngtype = type;
  41. }
  42. endva = va + MB; /* continue the open range */
  43. }
  44. va += MB;
  45. }
  46. if (endva != 0) /* close an open range */
  47. print("l1 maps va (%#lux-%#llux) -> pa %#lux type %#ux\n",
  48. startva, endva-1, startpa, rngtype);
  49. }
  50. void
  51. mmuinit(void)
  52. {
  53. PTE *l1, *l2;
  54. uintptr pa, fpa;
  55. pa = ttbget();
  56. l1 = KADDR(pa);
  57. /* identity-map i/o registers */
  58. l1[L1X(VIRTIO)] = PHYSIO|Dom0|L1AP(Krw)|Section;
  59. /* identity-map nand flash */
  60. for (fpa = PHYSNAND; fpa < PHYSNAND + FLASHSIZE; fpa += MiB)
  61. l1[L1X(fpa)] = fpa|Dom0|L1AP(Krw)|Section;
  62. for (fpa = 0xf9000000; fpa < 0xf9000000 + 8*MB; fpa += MiB)
  63. l1[L1X(fpa)] = fpa|Dom0|L1AP(Krw)|Section|Cached|Buffered;
  64. /* identity-map spi flash */
  65. for (fpa = PHYSSPIFLASH; fpa < PHYSSPIFLASH + FLASHSIZE; fpa += MiB)
  66. l1[L1X(fpa)] = fpa|Dom0|L1AP(Krw)|Section|Cached|Buffered;
  67. for (fpa = 0xf8000000; fpa < 0xf8000000 + 16*MB; fpa += MiB)
  68. l1[L1X(fpa)] = fpa|Dom0|L1AP(Krw)|Section|Cached|Buffered;
  69. /* map high vectors to start of dram, but only 4K, not 1MB */
  70. pa -= MACHSIZE+2*1024;
  71. l2 = KADDR(pa);
  72. memset(l2, 0, 1024);
  73. /* vectors step on u-boot, but so do page tables */
  74. l2[L2X(HVECTORS)] = PHYSDRAM|L2AP(Krw)|Small;
  75. l1[L1X(HVECTORS)] = pa|Dom0|Coarse; /* vectors -> ttb-machsize-2k */
  76. mmuinvalidate();
  77. cacheuwbinv();
  78. m->mmul1 = l1;
  79. // mmudump(l1); /* DEBUG */
  80. }
  81. static void
  82. mmul2empty(Proc* proc, int clear)
  83. {
  84. PTE *l1;
  85. Page **l2, *page;
  86. l1 = m->mmul1;
  87. l2 = &proc->mmul2;
  88. for(page = *l2; page != nil; page = page->next){
  89. if(clear)
  90. memset(UINT2PTR(page->va), 0, BY2PG);
  91. l1[page->daddr] = Fault;
  92. l2 = &page->next;
  93. }
  94. *l2 = proc->mmul2cache;
  95. proc->mmul2cache = proc->mmul2;
  96. proc->mmul2 = nil;
  97. }
  98. static void
  99. mmul1empty(void)
  100. {
  101. #ifdef notdef
  102. there's a bug in here
  103. PTE *l1;
  104. /* clean out any user mappings still in l1 */
  105. if(m->mmul1lo > L1lo){
  106. if(m->mmul1lo == 1)
  107. m->mmul1[L1lo] = Fault;
  108. else
  109. memset(&m->mmul1[L1lo], 0, m->mmul1lo*sizeof(PTE));
  110. m->mmul1lo = L1lo;
  111. }
  112. if(m->mmul1hi < L1hi){
  113. l1 = &m->mmul1[m->mmul1hi];
  114. if((L1hi - m->mmul1hi) == 1)
  115. *l1 = Fault;
  116. else
  117. memset(l1, 0, (L1hi - m->mmul1hi)*sizeof(PTE));
  118. m->mmul1hi = L1hi;
  119. }
  120. #else
  121. memset(&m->mmul1[L1lo], 0, (L1hi - L1lo)*sizeof(PTE));
  122. #endif /* notdef */
  123. }
  124. void
  125. mmuswitch(Proc* proc)
  126. {
  127. int x;
  128. PTE *l1;
  129. Page *page;
  130. /* do kprocs get here and if so, do they need to? */
  131. if(m->mmupid == proc->pid && !proc->newtlb)
  132. return;
  133. m->mmupid = proc->pid;
  134. /* write back dirty and invalidate caches */
  135. cacheuwbinv();
  136. if(proc->newtlb){
  137. mmul2empty(proc, 1);
  138. proc->newtlb = 0;
  139. }
  140. mmul1empty();
  141. /* move in new map */
  142. l1 = m->mmul1;
  143. for(page = proc->mmul2; page != nil; page = page->next){
  144. x = page->daddr;
  145. l1[x] = PPN(page->pa)|Dom0|Coarse;
  146. /* know here that L1lo < x < L1hi */
  147. if(x+1 - m->mmul1lo < m->mmul1hi - x)
  148. m->mmul1lo = x+1;
  149. else
  150. m->mmul1hi = x;
  151. }
  152. /* make sure map is in memory */
  153. /* could be smarter about how much? */
  154. cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
  155. /* lose any possible stale tlb entries */
  156. mmuinvalidate();
  157. // mmudump(l1);
  158. //print("mmuswitch l1lo %d l1hi %d %d\n",
  159. // m->mmul1lo, m->mmul1hi, proc->kp);
  160. }
  161. void
  162. flushmmu(void)
  163. {
  164. int s;
  165. s = splhi();
  166. up->newtlb = 1;
  167. mmuswitch(up);
  168. splx(s);
  169. }
  170. void
  171. mmurelease(Proc* proc)
  172. {
  173. Page *page, *next;
  174. /* write back dirty and invalidate caches */
  175. cacheuwbinv();
  176. mmul2empty(proc, 0);
  177. for(page = proc->mmul2cache; page != nil; page = next){
  178. next = page->next;
  179. if(--page->ref)
  180. panic("mmurelease: page->ref %d", page->ref);
  181. pagechainhead(page);
  182. }
  183. if(proc->mmul2cache && palloc.r.p)
  184. wakeup(&palloc.r);
  185. proc->mmul2cache = nil;
  186. mmul1empty();
  187. /* make sure map is in memory */
  188. /* could be smarter about how much? */
  189. cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
  190. /* lose any possible stale tlb entries */
  191. mmuinvalidate();
  192. }
  193. void
  194. putmmu(uintptr va, uintptr pa, Page* page)
  195. {
  196. int x;
  197. Page *pg;
  198. PTE *l1, *pte;
  199. x = L1X(va);
  200. l1 = &m->mmul1[x];
  201. //print("putmmu(%#p, %#p, %#p) ", va, pa, page->pa);
  202. //print("mmul1 %#p l1 %#p *l1 %#ux x %d pid %d\n",
  203. // m->mmul1, l1, *l1, x, up->pid);
  204. if(*l1 == Fault){
  205. /* wasteful - l2 pages only have 256 entries - fix */
  206. if(up->mmul2cache == nil){
  207. /* auxpg since we don't need much? memset if so */
  208. pg = newpage(1, 0, 0);
  209. pg->va = VA(kmap(pg));
  210. }
  211. else{
  212. pg = up->mmul2cache;
  213. up->mmul2cache = pg->next;
  214. memset(UINT2PTR(pg->va), 0, BY2PG);
  215. }
  216. pg->daddr = x;
  217. pg->next = up->mmul2;
  218. up->mmul2 = pg;
  219. *l1 = PPN(pg->pa)|Dom0|Coarse;
  220. //print("l1 %#p *l1 %#ux x %d pid %d\n", l1, *l1, x, up->pid);
  221. if(x >= m->mmul1lo && x < m->mmul1hi){
  222. if(x+1 - m->mmul1lo < m->mmul1hi - x)
  223. m->mmul1lo = x+1;
  224. else
  225. m->mmul1hi = x;
  226. }
  227. }
  228. pte = UINT2PTR(KADDR(PPN(*l1)));
  229. //print("pte %#p index %ld %#ux\n", pte, L2X(va), *(pte+L2X(va)));
  230. /* protection bits are
  231. * PTERONLY|PTEVALID;
  232. * PTEWRITE|PTEVALID;
  233. * PTEWRITE|PTEUNCACHED|PTEVALID;
  234. */
  235. x = Small;
  236. if(!(pa & PTEUNCACHED))
  237. x |= Cached|Buffered;
  238. if(pa & PTEWRITE)
  239. x |= L2AP(Urw);
  240. else
  241. x |= L2AP(Uro);
  242. pte[L2X(va)] = PPN(pa)|x;
  243. /* clear out the current entry */
  244. mmuinvalidateaddr(PPN(va));
  245. /* write back dirty entries - we need this because the pio() in
  246. * fault.c is writing via a different virt addr and won't clean
  247. * its changes out of the dcache. Page coloring doesn't work
  248. * on this mmu because the virtual cache is set associative
  249. * rather than direct mapped.
  250. */
  251. cachedwbinv();
  252. if(page->cachectl[0] == PG_TXTFLUSH){
  253. /* pio() sets PG_TXTFLUSH whenever a text pg has been written */
  254. cacheiinv();
  255. page->cachectl[0] = PG_NOFLUSH;
  256. }
  257. //print("putmmu %#p %#p %#p\n", va, pa, PPN(pa)|x);
  258. }
  259. void*
  260. mmuuncache(void* v, usize size)
  261. {
  262. int x;
  263. PTE *pte;
  264. uintptr va;
  265. /*
  266. * Simple helper for ucalloc().
  267. * Uncache a Section, must already be
  268. * valid in the MMU.
  269. */
  270. va = PTR2UINT(v);
  271. assert(!(va & (1*MiB-1)) && size == 1*MiB);
  272. x = L1X(va);
  273. pte = &m->mmul1[x];
  274. if((*pte & (Fine|Section|Coarse)) != Section)
  275. return nil;
  276. *pte &= ~(Cached|Buffered);
  277. mmuinvalidateaddr(va);
  278. cachedwbinvse(pte, 4);
  279. return v;
  280. }
  281. uintptr
  282. mmukmap(uintptr va, uintptr pa, usize size)
  283. {
  284. int x;
  285. PTE *pte;
  286. /*
  287. * Stub.
  288. */
  289. assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB);
  290. x = L1X(va);
  291. pte = &m->mmul1[x];
  292. if(*pte != Fault)
  293. return 0;
  294. *pte = pa|Dom0|L1AP(Krw)|Section;
  295. mmuinvalidateaddr(va);
  296. cachedwbinvse(pte, 4);
  297. return va;
  298. }
  299. uintptr
  300. mmukunmap(uintptr va, uintptr pa, usize size)
  301. {
  302. int x;
  303. PTE *pte;
  304. /*
  305. * Stub.
  306. */
  307. assert(!(va & (1*MiB-1)) && !(pa & (1*MiB-1)) && size == 1*MiB);
  308. x = L1X(va);
  309. pte = &m->mmul1[x];
  310. if(*pte != (pa|Dom0|L1AP(Krw)|Section))
  311. return 0;
  312. *pte = Fault;
  313. mmuinvalidateaddr(va);
  314. cachedwbinvse(pte, 4);
  315. return va;
  316. }
  317. /*
  318. * Return the number of bytes that can be accessed via KADDR(pa).
  319. * If pa is not a valid argument to KADDR, return 0.
  320. */
  321. uintptr
  322. cankaddr(uintptr pa)
  323. {
  324. int i;
  325. uintptr bank;
  326. bank = PHYSDRAM;
  327. for(i = 0; i < 1; i++){
  328. if(pa >= bank && pa < bank+512*MiB)
  329. return bank+512*MiB - pa;
  330. bank += 512*MiB;
  331. }
  332. return 0;
  333. }
  334. /* from 386 */
  335. void*
  336. vmap(uintptr pa, usize size)
  337. {
  338. uintptr pae, va;
  339. usize o, osize;
  340. /*
  341. * XXX - replace with new vm stuff.
  342. * Crock after crock - the first 4MB is mapped with 2MB pages
  343. * so catch that and return good values because the current mmukmap
  344. * will fail.
  345. */
  346. if(pa+size < 4*MiB)
  347. return UINT2PTR(kseg0|pa);
  348. osize = size;
  349. o = pa & (BY2PG-1);
  350. pa -= o;
  351. size += o;
  352. size = ROUNDUP(size, PGSIZE);
  353. va = kseg0|pa;
  354. pae = mmukmap(va, pa, size);
  355. if(pae == 0 || pae-size != pa)
  356. panic("vmap(%#p, %ld) called from %#p: mmukmap fails %#p",
  357. pa+o, osize, getcallerpc(&pa), pae);
  358. return UINT2PTR(va+o);
  359. }
  360. /* from 386 */
  361. void
  362. vunmap(void* v, usize size)
  363. {
  364. /*
  365. * XXX - replace with new vm stuff.
  366. * Can't do this until do real vmap for all space that
  367. * might be used, e.g. stuff below 1MB which is currently
  368. * mapped automagically at boot but that isn't used (or
  369. * at least shouldn't be used) by the kernel.
  370. upafree(PADDR(v), size);
  371. */
  372. USED(v, size);
  373. }
  374. /*
  375. * Notes.
  376. * Everything is in domain 0;
  377. * domain 0 access bits in the DAC register are set
  378. * to Client, which means access is controlled by the
  379. * permission values set in the PTE.
  380. *
  381. * L1 access control for the kernel is set to 1 (RW,
  382. * no user mode access);
  383. * L2 access control for the kernel is set to 1 (ditto)
  384. * for all 4 AP sets;
  385. * L1 user mode access is never set;
  386. * L2 access control for user mode is set to either
  387. * 2 (RO) or 3 (RW) depending on whether text or data,
  388. * for all 4 AP sets.
  389. * (To get kernel RO set AP to 0 and S bit in control
  390. * register c1).
  391. * Coarse L1 page-tables are used. They have 256 entries
  392. * and so consume 1024 bytes per table.
  393. * Small L2 page-tables are used. They have 1024 entries
  394. * and so consume 4096 bytes per table.
  395. *
  396. * 4KiB. That's the size of 1) a page, 2) the
  397. * size allocated for an L2 page-table page (note only 1KiB
  398. * is needed per L2 page - to be dealt with later) and
  399. * 3) the size of the area in L1 needed to hold the PTEs
  400. * to map 1GiB of user space (0 -> 0x3fffffff, 1024 entries).
  401. */