* Perform the pmap work for mincore(2). If the page is not both referenced and * modified by this pmap, returns its physical address so that the caller can * find other mappings. */
| 6436 | * find other mappings. |
| 6437 | */ |
| 6438 | int |
| 6439 | pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *pap) |
| 6440 | { |
| 6441 | pt_entry_t *pte, tpte; |
| 6442 | vm_paddr_t mask, pa; |
| 6443 | int lvl, val; |
| 6444 | bool managed; |
| 6445 | |
| 6446 | PMAP_ASSERT_STAGE1(pmap); |
| 6447 | PMAP_LOCK(pmap); |
| 6448 | pte = pmap_pte(pmap, addr, &lvl); |
| 6449 | if (pte != NULL) { |
| 6450 | tpte = pmap_load(pte); |
| 6451 | |
| 6452 | switch (lvl) { |
| 6453 | case 3: |
| 6454 | mask = L3_OFFSET; |
| 6455 | break; |
| 6456 | case 2: |
| 6457 | mask = L2_OFFSET; |
| 6458 | break; |
| 6459 | case 1: |
| 6460 | mask = L1_OFFSET; |
| 6461 | break; |
| 6462 | default: |
| 6463 | panic("pmap_mincore: invalid level %d", lvl); |
| 6464 | } |
| 6465 | |
| 6466 | managed = (tpte & ATTR_SW_MANAGED) != 0; |
| 6467 | val = MINCORE_INCORE; |
| 6468 | if (lvl != 3) |
| 6469 | val |= MINCORE_PSIND(3 - lvl); |
| 6470 | if ((managed && pmap_pte_dirty(pmap, tpte)) || (!managed && |
| 6471 | (tpte & ATTR_S1_AP_RW_BIT) == ATTR_S1_AP(ATTR_S1_AP_RW))) |
| 6472 | val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER; |
| 6473 | if ((tpte & ATTR_AF) == ATTR_AF) |
| 6474 | val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER; |
| 6475 | |
| 6476 | pa = (tpte & ~ATTR_MASK) | (addr & mask); |
| 6477 | } else { |
| 6478 | managed = false; |
| 6479 | val = 0; |
| 6480 | } |
| 6481 | |
| 6482 | if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) != |
| 6483 | (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) { |
| 6484 | *pap = pa; |
| 6485 | } |
| 6486 | PMAP_UNLOCK(pmap); |
| 6487 | return (val); |
| 6488 | } |
| 6489 | |
| 6490 | /* |
| 6491 | * Garbage collect every ASID that is neither active on a processor nor |
nothing calls this directly
no test coverage detected