| 138 | } |
| 139 | |
| 140 | static int _kernel_map_4K(unsigned long *lv0_tbl, void *vaddr, void *paddr, unsigned long attr) |
| 141 | { |
| 142 | int ret = 0; |
| 143 | int level; |
| 144 | unsigned long *cur_lv_tbl = lv0_tbl; |
| 145 | unsigned long page; |
| 146 | unsigned long off; |
| 147 | rt_ubase_t va = (rt_ubase_t)vaddr; |
| 148 | rt_ubase_t pa = (rt_ubase_t)paddr; |
| 149 | int level_shift = MMU_ADDRESS_BITS; |
| 150 | |
| 151 | if (va & ARCH_PAGE_MASK) |
| 152 | { |
| 153 | return MMU_MAP_ERROR_VANOTALIGN; |
| 154 | } |
| 155 | if (pa & ARCH_PAGE_MASK) |
| 156 | { |
| 157 | return MMU_MAP_ERROR_PANOTALIGN; |
| 158 | } |
| 159 | for (level = 0; level < MMU_TBL_PAGE_4k_LEVEL; level++) |
| 160 | { |
| 161 | off = (va >> level_shift); |
| 162 | off &= MMU_LEVEL_MASK; |
| 163 | if (!(cur_lv_tbl[off] & MMU_TYPE_USED)) |
| 164 | { |
| 165 | page = (unsigned long)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE); |
| 166 | if (!page) |
| 167 | { |
| 168 | ret = MMU_MAP_ERROR_NOPAGE; |
| 169 | goto err; |
| 170 | } |
| 171 | rt_memset((void *)page, 0, ARCH_PAGE_SIZE); |
| 172 | rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)page, ARCH_PAGE_SIZE); |
| 173 | cur_lv_tbl[off] = (page + PV_OFFSET) | MMU_TYPE_TABLE; |
| 174 | rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, cur_lv_tbl + off, sizeof(void *)); |
| 175 | } |
| 176 | else |
| 177 | { |
| 178 | page = cur_lv_tbl[off]; |
| 179 | page &= MMU_ADDRESS_MASK; |
| 180 | /* page to va */ |
| 181 | page -= PV_OFFSET; |
| 182 | rt_page_ref_inc((void *)page, 0); |
| 183 | } |
| 184 | page = cur_lv_tbl[off]; |
| 185 | if ((page & MMU_TYPE_MASK) == MMU_TYPE_BLOCK) |
| 186 | { |
| 187 | /* is block! error! */ |
| 188 | ret = MMU_MAP_ERROR_CONFLICT; |
| 189 | goto err; |
| 190 | } |
| 191 | cur_lv_tbl = (unsigned long *)(page & MMU_ADDRESS_MASK); |
| 192 | cur_lv_tbl = (unsigned long *)((unsigned long)cur_lv_tbl - PV_OFFSET); |
| 193 | level_shift -= MMU_LEVEL_SHIFT; |
| 194 | } |
| 195 | /* now is level page */ |
| 196 | attr &= MMU_ATTRIB_MASK; |
| 197 | pa |= (attr | MMU_TYPE_PAGE); /* page */ |
nothing calls this directly
no test coverage detected