xref: /nrf52832-nimble/rt-thread/libcpu/arm/realview-a8-vmm/mmu.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2012-01-10     bernard      porting to AM1808
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <rthw.h>
13*10465441SEvalZero #include <board.h>
14*10465441SEvalZero 
15*10465441SEvalZero #include "cp15.h"
16*10465441SEvalZero 
17*10465441SEvalZero #define DESC_SEC       (0x2)
18*10465441SEvalZero #define CB             (3<<2)  //cache_on, write_back
19*10465441SEvalZero #define CNB            (2<<2)  //cache_on, write_through
20*10465441SEvalZero #define NCB            (1<<2)  //cache_off,WR_BUF on
21*10465441SEvalZero #define NCNB           (0<<2)  //cache_off,WR_BUF off
22*10465441SEvalZero #define AP_RW          (3<<10) //supervisor=RW, user=RW
23*10465441SEvalZero #define AP_RO          (2<<10) //supervisor=RW, user=RO
24*10465441SEvalZero #define XN             (1<<4)  // eXecute Never
25*10465441SEvalZero 
26*10465441SEvalZero #define DOMAIN_FAULT   (0x0)
27*10465441SEvalZero #define DOMAIN_CHK     (0x1)
28*10465441SEvalZero #define DOMAIN_NOTCHK  (0x3)
29*10465441SEvalZero #define DOMAIN0        (0x0<<5)
30*10465441SEvalZero #define DOMAIN1        (0x1<<5)
31*10465441SEvalZero 
32*10465441SEvalZero #define DOMAIN0_ATTR   (DOMAIN_CHK<<0)
33*10465441SEvalZero #define DOMAIN1_ATTR   (DOMAIN_FAULT<<2)
34*10465441SEvalZero 
35*10465441SEvalZero /* Read/Write, cache, write back */
36*10465441SEvalZero #define RW_CB          (AP_RW|DOMAIN0|CB|DESC_SEC)
37*10465441SEvalZero /* Read/Write, cache, write through */
38*10465441SEvalZero #define RW_CNB         (AP_RW|DOMAIN0|CNB|DESC_SEC)
39*10465441SEvalZero /* Read/Write without cache and write buffer */
40*10465441SEvalZero #define RW_NCNB        (AP_RW|DOMAIN0|NCNB|DESC_SEC)
41*10465441SEvalZero /* Read/Write without cache and write buffer, no execute */
42*10465441SEvalZero #define RW_NCNBXN      (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN)
43*10465441SEvalZero /* Read/Write without cache and write buffer */
44*10465441SEvalZero #define RW_FAULT       (AP_RW|DOMAIN1|NCNB|DESC_SEC)
45*10465441SEvalZero 
46*10465441SEvalZero /* dump 2nd level page table */
rt_hw_cpu_dump_page_table_2nd(rt_uint32_t * ptb)47*10465441SEvalZero void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
48*10465441SEvalZero {
49*10465441SEvalZero     int i;
50*10465441SEvalZero     int fcnt = 0;
51*10465441SEvalZero 
52*10465441SEvalZero     for (i = 0; i < 256; i++)
53*10465441SEvalZero     {
54*10465441SEvalZero         rt_uint32_t pte2 = ptb[i];
55*10465441SEvalZero         if ((pte2 & 0x3) == 0)
56*10465441SEvalZero         {
57*10465441SEvalZero             if (fcnt == 0)
58*10465441SEvalZero                 rt_kprintf("    ");
59*10465441SEvalZero             rt_kprintf("%04x: ", i);
60*10465441SEvalZero             fcnt++;
61*10465441SEvalZero             if (fcnt == 16)
62*10465441SEvalZero             {
63*10465441SEvalZero                 rt_kprintf("fault\n");
64*10465441SEvalZero                 fcnt = 0;
65*10465441SEvalZero             }
66*10465441SEvalZero             continue;
67*10465441SEvalZero         }
68*10465441SEvalZero         if (fcnt != 0)
69*10465441SEvalZero         {
70*10465441SEvalZero             rt_kprintf("fault\n");
71*10465441SEvalZero             fcnt = 0;
72*10465441SEvalZero         }
73*10465441SEvalZero 
74*10465441SEvalZero         rt_kprintf("    %04x: %x: ", i, pte2);
75*10465441SEvalZero         if ((pte2 & 0x3) == 0x1)
76*10465441SEvalZero         {
77*10465441SEvalZero             rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n",
78*10465441SEvalZero                        ((pte2 >> 7) | (pte2 >> 4))& 0xf,
79*10465441SEvalZero                        (pte2 >> 15) & 0x1,
80*10465441SEvalZero                        ((pte2 >> 10) | (pte2 >> 2)) & 0x1f);
81*10465441SEvalZero         }
82*10465441SEvalZero         else
83*10465441SEvalZero         {
84*10465441SEvalZero             rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n",
85*10465441SEvalZero                        ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1,
86*10465441SEvalZero                        ((pte2 >> 4) | (pte2 >> 2)) & 0x1f);
87*10465441SEvalZero         }
88*10465441SEvalZero     }
89*10465441SEvalZero }
90*10465441SEvalZero 
rt_hw_cpu_dump_page_table(rt_uint32_t * ptb)91*10465441SEvalZero void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
92*10465441SEvalZero {
93*10465441SEvalZero     int i;
94*10465441SEvalZero     int fcnt = 0;
95*10465441SEvalZero 
96*10465441SEvalZero     rt_kprintf("page table@%p\n", ptb);
97*10465441SEvalZero     for (i = 0; i < 1024*4; i++)
98*10465441SEvalZero     {
99*10465441SEvalZero         rt_uint32_t pte1 = ptb[i];
100*10465441SEvalZero         if ((pte1 & 0x3) == 0)
101*10465441SEvalZero         {
102*10465441SEvalZero             rt_kprintf("%03x: ", i);
103*10465441SEvalZero             fcnt++;
104*10465441SEvalZero             if (fcnt == 16)
105*10465441SEvalZero             {
106*10465441SEvalZero                 rt_kprintf("fault\n");
107*10465441SEvalZero                 fcnt = 0;
108*10465441SEvalZero             }
109*10465441SEvalZero             continue;
110*10465441SEvalZero         }
111*10465441SEvalZero         if (fcnt != 0)
112*10465441SEvalZero         {
113*10465441SEvalZero             rt_kprintf("fault\n");
114*10465441SEvalZero             fcnt = 0;
115*10465441SEvalZero         }
116*10465441SEvalZero 
117*10465441SEvalZero         rt_kprintf("%03x: %08x: ", i, pte1);
118*10465441SEvalZero         if ((pte1 & 0x3) == 0x3)
119*10465441SEvalZero         {
120*10465441SEvalZero             rt_kprintf("LPAE\n");
121*10465441SEvalZero         }
122*10465441SEvalZero         else if ((pte1 & 0x3) == 0x1)
123*10465441SEvalZero         {
124*10465441SEvalZero             rt_kprintf("pte,ns:%d,domain:%d\n",
125*10465441SEvalZero                        (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
126*10465441SEvalZero             /*
127*10465441SEvalZero              *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
128*10465441SEvalZero              *                               - 0x80000000 + 0xC0000000));
129*10465441SEvalZero              */
130*10465441SEvalZero         }
131*10465441SEvalZero         else if (pte1 & (1 << 18))
132*10465441SEvalZero         {
133*10465441SEvalZero             rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
134*10465441SEvalZero                        (pte1 >> 19) & 0x1,
135*10465441SEvalZero                        ((pte1 >> 13) | (pte1 >> 10))& 0xf,
136*10465441SEvalZero                        (pte1 >> 4) & 0x1,
137*10465441SEvalZero                        ((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
138*10465441SEvalZero         }
139*10465441SEvalZero         else
140*10465441SEvalZero         {
141*10465441SEvalZero             rt_kprintf("section,ns:%d,ap:%x,"
142*10465441SEvalZero                        "xn:%d,texcb:%02x,domain:%d\n",
143*10465441SEvalZero                        (pte1 >> 19) & 0x1,
144*10465441SEvalZero                        ((pte1 >> 13) | (pte1 >> 10))& 0xf,
145*10465441SEvalZero                        (pte1 >> 4) & 0x1,
146*10465441SEvalZero                        (((pte1 & (0x7 << 12)) >> 10) |
147*10465441SEvalZero                         ((pte1 &        0x0c) >>  2)) & 0x1f,
148*10465441SEvalZero                        (pte1 >> 5) & 0xf);
149*10465441SEvalZero         }
150*10465441SEvalZero     }
151*10465441SEvalZero }
152*10465441SEvalZero 
153*10465441SEvalZero /* level1 page table, each entry for 1MB memory. */
154*10465441SEvalZero volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024)));
rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,rt_uint32_t vaddrEnd,rt_uint32_t paddrStart,rt_uint32_t attr)155*10465441SEvalZero void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,
156*10465441SEvalZero                       rt_uint32_t vaddrEnd,
157*10465441SEvalZero                       rt_uint32_t paddrStart,
158*10465441SEvalZero                       rt_uint32_t attr)
159*10465441SEvalZero {
160*10465441SEvalZero     volatile rt_uint32_t *pTT;
161*10465441SEvalZero     volatile int i, nSec;
162*10465441SEvalZero     pTT  = (rt_uint32_t *)MMUTable + (vaddrStart >> 20);
163*10465441SEvalZero     nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
164*10465441SEvalZero     for(i = 0; i <= nSec; i++)
165*10465441SEvalZero     {
166*10465441SEvalZero         *pTT = attr | (((paddrStart >> 20) + i) << 20);
167*10465441SEvalZero         pTT++;
168*10465441SEvalZero     }
169*10465441SEvalZero }
170*10465441SEvalZero 
rt_hw_set_domain_register(unsigned long domain_val)171*10465441SEvalZero unsigned long rt_hw_set_domain_register(unsigned long domain_val)
172*10465441SEvalZero {
173*10465441SEvalZero     unsigned long old_domain;
174*10465441SEvalZero 
175*10465441SEvalZero     asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain));
176*10465441SEvalZero     asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory");
177*10465441SEvalZero 
178*10465441SEvalZero     return old_domain;
179*10465441SEvalZero }
180*10465441SEvalZero 
rt_hw_mmu_init(void)181*10465441SEvalZero void rt_hw_mmu_init(void)
182*10465441SEvalZero {
183*10465441SEvalZero     rt_hw_cpu_dcache_disable();
184*10465441SEvalZero     rt_hw_cpu_icache_disable();
185*10465441SEvalZero     rt_cpu_mmu_disable();
186*10465441SEvalZero 
187*10465441SEvalZero     /* set page table */
188*10465441SEvalZero     /* 4G 1:1 memory */
189*10465441SEvalZero     rt_hw_mmu_setmtt(0, 0xffffffff-1, 0, RW_CB);
190*10465441SEvalZero     /* IO memory region */
191*10465441SEvalZero     rt_hw_mmu_setmtt(0x44000000, 0x80000000-1, 0x44000000, RW_NCNBXN);
192*10465441SEvalZero 
193*10465441SEvalZero     /*rt_hw_cpu_dump_page_table(MMUTable);*/
194*10465441SEvalZero     rt_hw_set_domain_register(0x55555555);
195*10465441SEvalZero 
196*10465441SEvalZero     rt_cpu_tlb_set(MMUTable);
197*10465441SEvalZero 
198*10465441SEvalZero     rt_cpu_mmu_enable();
199*10465441SEvalZero 
200*10465441SEvalZero     rt_hw_cpu_icache_enable();
201*10465441SEvalZero     rt_hw_cpu_dcache_enable();
202*10465441SEvalZero }
203*10465441SEvalZero 
204