mmu.c 11 KB

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