mmu.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*
  2. * File : mmu.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. */
  23. #include "mmu.h"
  24. #include "rtthread.h"
  25. #ifdef __CC_ARM
  26. void mmu_setttbase(rt_uint32_t i)
  27. {
  28. register rt_uint32_t value;
  29. /* Invalidates all TLBs.Domain access is selected as
  30. * client by configuring domain access register,
  31. * in that case access controlled by permission value
  32. * set by page table entry
  33. */
  34. value = 0;
  35. __asm
  36. {
  37. mcr p15, 0, value, c8, c7, 0
  38. }
  39. value = 0x55555555;
  40. __asm
  41. {
  42. mcr p15, 0, value, c3, c0, 0
  43. mcr p15, 0, i, c2, c0, 0
  44. }
  45. }
  46. void mmu_set_domain(rt_uint32_t i)
  47. {
  48. __asm
  49. {
  50. mcr p15,0, i, c3, c0, 0
  51. }
  52. }
  53. void mmu_enable()
  54. {
  55. register rt_uint32_t value;
  56. __asm
  57. {
  58. mrc p15, 0, value, c1, c0, 0
  59. orr value, value, #0x01
  60. mcr p15, 0, value, c1, c0, 0
  61. }
  62. }
  63. void mmu_disable()
  64. {
  65. register rt_uint32_t value;
  66. __asm
  67. {
  68. mrc p15, 0, value, c1, c0, 0
  69. bic value, value, #0x01
  70. mcr p15, 0, value, c1, c0, 0
  71. }
  72. }
  73. void mmu_enable_icache()
  74. {
  75. register rt_uint32_t value;
  76. __asm
  77. {
  78. mrc p15, 0, value, c1, c0, 0
  79. orr value, value, #0x1000
  80. mcr p15, 0, value, c1, c0, 0
  81. }
  82. }
  83. void mmu_enable_dcache()
  84. {
  85. register rt_uint32_t value;
  86. __asm
  87. {
  88. mrc p15, 0, value, c1, c0, 0
  89. orr value, value, #0x04
  90. mcr p15, 0, value, c1, c0, 0
  91. }
  92. }
  93. void mmu_disable_icache()
  94. {
  95. register rt_uint32_t value;
  96. __asm
  97. {
  98. mrc p15, 0, value, c1, c0, 0
  99. bic value, value, #0x1000
  100. mcr p15, 0, value, c1, c0, 0
  101. }
  102. }
  103. void mmu_disable_dcache()
  104. {
  105. register rt_uint32_t value;
  106. __asm
  107. {
  108. mrc p15, 0, value, c1, c0, 0
  109. bic value, value, #0x04
  110. mcr p15, 0, value, c1, c0, 0
  111. }
  112. }
  113. void mmu_enable_alignfault()
  114. {
  115. register rt_uint32_t value;
  116. __asm
  117. {
  118. mrc p15, 0, value, c1, c0, 0
  119. orr value, value, #0x02
  120. mcr p15, 0, value, c1, c0, 0
  121. }
  122. }
  123. void mmu_disable_alignfault()
  124. {
  125. register rt_uint32_t value;
  126. __asm
  127. {
  128. mrc p15, 0, value, c1, c0, 0
  129. bic value, value, #0x02
  130. mcr p15, 0, value, c1, c0, 0
  131. }
  132. }
  133. void mmu_clean_invalidated_cache_index(int index)
  134. {
  135. __asm
  136. {
  137. mcr p15, 0, index, c7, c14, 2
  138. }
  139. }
  140. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  141. {
  142. unsigned int ptr;
  143. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  144. while(ptr < buffer + size)
  145. {
  146. __asm
  147. {
  148. MCR p15, 0, ptr, c7, c14, 1
  149. }
  150. ptr += CACHE_LINE_SIZE;
  151. }
  152. }
  153. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  154. {
  155. unsigned int ptr;
  156. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  157. while (ptr < buffer + size)
  158. {
  159. __asm
  160. {
  161. MCR p15, 0, ptr, c7, c10, 1
  162. }
  163. ptr += CACHE_LINE_SIZE;
  164. }
  165. }
  166. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  167. {
  168. unsigned int ptr;
  169. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  170. while (ptr < buffer + size)
  171. {
  172. __asm
  173. {
  174. MCR p15, 0, ptr, c7, c6, 1
  175. }
  176. ptr += CACHE_LINE_SIZE;
  177. }
  178. }
  179. void mmu_invalidate_tlb()
  180. {
  181. register rt_uint32_t value;
  182. value = 0;
  183. __asm
  184. {
  185. mcr p15, 0, value, c8, c7, 0
  186. }
  187. }
  188. void mmu_invalidate_icache()
  189. {
  190. register rt_uint32_t value;
  191. value = 0;
  192. __asm
  193. {
  194. mcr p15, 0, value, c7, c5, 0
  195. }
  196. }
  197. void mmu_invalidate_dcache_all()
  198. {
  199. register rt_uint32_t value;
  200. value = 0;
  201. __asm
  202. {
  203. mcr p15, 0, value, c7, c6, 0
  204. }
  205. }
  206. #elif defined(__GNUC__)
  207. void mmu_setttbase(register rt_uint32_t i)
  208. {
  209. //register rt_uint32_t value;
  210. /* Invalidates all TLBs.Domain access is selected as
  211. * client by configuring domain access register,
  212. * in that case access controlled by permission value
  213. * set by page table entry
  214. */
  215. #if 0
  216. value = 0;
  217. asm ("mcr p15, 0, %0, c8,c7, 0"::"r"(value));
  218. value = 0x55555555;
  219. asm ("mcr p15, 0, %0, c3,c0, 0"::"r"(value));
  220. asm ("mcr p15, 0, %0, c2,c0, 0"::"r"(i));
  221. #endif
  222. asm (
  223. "mrc p15,0,r0,c1,c0,0 \r\n"
  224. "mov r1,#0x800000 \r\n"
  225. "orr r0,r0,r1 @ disable Subpage AP bits \r\n"
  226. "mcr p15,0,r0,c1,c0,0 @ write value back \r\n"
  227. "mov r0,#0x0 \r\n"
  228. "mcr p15,0,r0,c2,c0,2 @ W \r\n"
  229. );
  230. asm("mcr p15,0,%0,c2,c0,0"::"r"(i));
  231. }
  232. void mmu_set_domain(register rt_uint32_t i)
  233. {
  234. asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i));
  235. }
  236. void mmu_enable()
  237. {
  238. register rt_uint32_t i;
  239. /* read control register */
  240. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  241. i |= 0x1;
  242. /* write back to control register */
  243. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  244. }
  245. void mmu_disable()
  246. {
  247. register rt_uint32_t i;
  248. /* read control register */
  249. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  250. i &= ~0x1;
  251. /* write back to control register */
  252. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  253. }
  254. void mmu_enable_icache()
  255. {
  256. register rt_uint32_t i;
  257. /* read control register */
  258. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  259. i |= (1 << 12);
  260. /* write back to control register */
  261. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  262. }
  263. void mmu_enable_dcache()
  264. {
  265. register rt_uint32_t i;
  266. /* read control register */
  267. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  268. i |= (1 << 2);
  269. /* write back to control register */
  270. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  271. }
  272. void mmu_disable_icache()
  273. {
  274. register rt_uint32_t i;
  275. /* read control register */
  276. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  277. i &= ~(1 << 12);
  278. /* write back to control register */
  279. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  280. }
  281. void mmu_disable_dcache()
  282. {
  283. register rt_uint32_t i;
  284. /* read control register */
  285. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  286. i &= ~(1 << 2);
  287. /* write back to control register */
  288. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  289. }
  290. void mmu_enable_alignfault()
  291. {
  292. register rt_uint32_t i;
  293. /* read control register */
  294. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  295. i |= (1 << 1);
  296. /* write back to control register */
  297. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  298. }
  299. void mmu_disable_alignfault()
  300. {
  301. register rt_uint32_t i;
  302. /* read control register */
  303. asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
  304. i &= ~(1 << 1);
  305. /* write back to control register */
  306. asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
  307. }
  308. void mmu_clean_invalidated_cache_index(int index)
  309. {
  310. asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index));
  311. }
  312. void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
  313. {
  314. unsigned int ptr;
  315. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  316. while(ptr < buffer + size)
  317. {
  318. asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr));
  319. ptr += CACHE_LINE_SIZE;
  320. }
  321. }
  322. void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
  323. {
  324. unsigned int ptr;
  325. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  326. while (ptr < buffer + size)
  327. {
  328. asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr));
  329. ptr += CACHE_LINE_SIZE;
  330. }
  331. }
  332. void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
  333. {
  334. unsigned int ptr;
  335. ptr = buffer & ~(CACHE_LINE_SIZE - 1);
  336. while (ptr < buffer + size)
  337. {
  338. asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr));
  339. ptr += CACHE_LINE_SIZE;
  340. }
  341. }
  342. void mmu_invalidate_tlb()
  343. {
  344. asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0));
  345. }
  346. void mmu_invalidate_icache()
  347. {
  348. asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
  349. }
  350. void mmu_invalidate_dcache_all()
  351. {
  352. asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (0));
  353. }
  354. #endif
  355. /* level1 page table */
  356. //static volatile unsigned int _page_table[4*1024] __attribute__((aligned(16*1024)));
  357. #define ARM1176_GCC_ALIGN(bits) __attribute__((aligned(1UL<<bits)))
  358. #define ARM1176_MMU_TTB_ALIGNMENT 14
  359. static volatile unsigned int _page_table[4096]
  360. ARM1176_GCC_ALIGN(ARM1176_MMU_TTB_ALIGNMENT) __attribute__ ((section(".nocache_buffer"))) = { 0x000011E2UL };
  361. void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd, rt_uint32_t paddrStart, rt_uint32_t attr)
  362. {
  363. volatile rt_uint32_t *pTT;
  364. volatile int i,nSec;
  365. pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20);
  366. nSec=(vaddrEnd>>20)-(vaddrStart>>20);
  367. for(i=0;i<=nSec;i++)
  368. {
  369. *pTT = attr |(((paddrStart>>20)+i)<<20);
  370. pTT++;
  371. }
  372. }
  373. void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
  374. {
  375. int i;
  376. int fcnt = 0;
  377. rt_kprintf("page table@%p\n", ptb);
  378. for (i = 0; i < 1024*4; i++)
  379. {
  380. rt_uint32_t pte1 = ptb[i];
  381. if ((pte1 & 0x3) == 0)
  382. {
  383. rt_kprintf("%03x: ", i);
  384. fcnt++;
  385. if (fcnt == 16)
  386. {
  387. rt_kprintf("fault\n");
  388. fcnt = 0;
  389. }
  390. continue;
  391. }
  392. if (fcnt != 0)
  393. {
  394. rt_kprintf("fault\n");
  395. fcnt = 0;
  396. }
  397. rt_kprintf("%03x: %08x: ", i, pte1);
  398. if ((pte1 & 0x3) == 0x3)
  399. {
  400. rt_kprintf("LPAE\n");
  401. }
  402. else if ((pte1 & 0x3) == 0x1)
  403. {
  404. rt_kprintf("pte,ns:%d,domain:%d\n",
  405. (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
  406. /*
  407. *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
  408. * - 0x80000000 + 0xC0000000));
  409. */
  410. }
  411. else if (pte1 & (1 << 18))
  412. {
  413. rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
  414. (pte1 >> 19) & 0x1,
  415. ((pte1 >> 13) | (pte1 >> 10))& 0xf,
  416. (pte1 >> 4) & 0x1,
  417. ((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
  418. }
  419. else
  420. {
  421. rt_kprintf("section,ns:%d,ap:%x,"
  422. "xn:%d,texcb:%02x,domain:%d\n",
  423. (pte1 >> 19) & 0x1,
  424. ((pte1 >> 13) | (pte1 >> 10))& 0xf,
  425. (pte1 >> 4) & 0x1,
  426. (((pte1 & (0x7 << 12)) >> 10) |
  427. ((pte1 & 0x0c) >> 2)) & 0x1f,
  428. (pte1 >> 5) & 0xf);
  429. }
  430. }
  431. }
  432. void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
  433. {
  434. /* disable I/D cache */
  435. mmu_disable_dcache();
  436. mmu_disable_icache();
  437. mmu_disable();
  438. mmu_invalidate_tlb();
  439. /* set page table */
  440. for (; size > 0; size--)
  441. {
  442. mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
  443. mdesc->paddr_start, mdesc->attr);
  444. mdesc++;
  445. }
  446. /* set MMU table address */
  447. mmu_setttbase((rt_uint32_t)_page_table);
  448. /* enables MMU */
  449. mmu_enable();
  450. /* enable Instruction Cache */
  451. mmu_enable_icache();
  452. /* enable Data Cache */
  453. mmu_enable_dcache();
  454. mmu_invalidate_icache();
  455. mmu_invalidate_dcache_all();
  456. }