Unmaps a virtual address range (1GB/2MB/4KB according to actual page level) from the page table. */
| 247 | |
| 248 | /* Unmaps a virtual address range (1GB/2MB/4KB according to actual page level) from the page table. */ |
| 249 | static size_t _unmap_area(struct rt_aspace *aspace, void *v_addr) |
| 250 | { |
| 251 | rt_ubase_t loop_va = __UMASKVALUE((rt_ubase_t)v_addr, PAGE_OFFSET_MASK); |
| 252 | size_t unmapped = 0; |
| 253 | |
| 254 | int i = 0; |
| 255 | rt_ubase_t lvl_off[3]; |
| 256 | rt_ubase_t *lvl_entry[3]; |
| 257 | lvl_off[0] = (rt_ubase_t)GET_L1(loop_va); |
| 258 | lvl_off[1] = (rt_ubase_t)GET_L2(loop_va); |
| 259 | lvl_off[2] = (rt_ubase_t)GET_L3(loop_va); |
| 260 | unmapped = 1 << (ARCH_PAGE_SHIFT + ARCH_INDEX_WIDTH * 2ul); |
| 261 | |
| 262 | rt_ubase_t *pentry; |
| 263 | lvl_entry[i] = ((rt_ubase_t *)aspace->page_table + lvl_off[i]); |
| 264 | pentry = lvl_entry[i]; |
| 265 | |
| 266 | /* check if lvl_entry[0] is valid. if no, return 0 directly. */ |
| 267 | if (!PTE_USED(*pentry)) |
| 268 | { |
| 269 | return 0; |
| 270 | } |
| 271 | |
| 272 | /* find leaf page table entry */ |
| 273 | while (PTE_USED(*pentry) && !PAGE_IS_LEAF(*pentry)) |
| 274 | { |
| 275 | i += 1; |
| 276 | |
| 277 | if (i >= 3) |
| 278 | { |
| 279 | unmapped = 0; |
| 280 | break; |
| 281 | } |
| 282 | |
| 283 | lvl_entry[i] = ((rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*pentry), PV_OFFSET) + |
| 284 | lvl_off[i]); |
| 285 | pentry = lvl_entry[i]; |
| 286 | unmapped >>= ARCH_INDEX_WIDTH; |
| 287 | } |
| 288 | |
| 289 | /* clear PTE & setup its */ |
| 290 | if (PTE_USED(*pentry)) |
| 291 | { |
| 292 | _unmap_pte(pentry, lvl_entry, i); |
| 293 | } |
| 294 | else |
| 295 | { |
| 296 | unmapped = 0; /* invalid pte, return 0. */ |
| 297 | } |
| 298 | |
| 299 | return unmapped; |
| 300 | } |
| 301 | |
| 302 | /** |
| 303 | * @brief Unmaps a range of virtual memory addresses from the specified address space. |
no test coverage detected