| 10474 | } |
| 10475 | |
| 10476 | static void |
| 10477 | pmap_large_map_wb_large(vm_offset_t sva, vm_offset_t eva) |
| 10478 | { |
| 10479 | volatile u_long *pe; |
| 10480 | u_long p; |
| 10481 | vm_offset_t va; |
| 10482 | vm_size_t inc; |
| 10483 | bool seen_other; |
| 10484 | |
| 10485 | for (va = sva; va < eva; va += inc) { |
| 10486 | inc = 0; |
| 10487 | if ((amd_feature & AMDID_PAGE1GB) != 0) { |
| 10488 | pe = (volatile u_long *)pmap_large_map_pdpe(va); |
| 10489 | p = *pe; |
| 10490 | if ((p & X86_PG_PS) != 0) |
| 10491 | inc = NBPDP; |
| 10492 | } |
| 10493 | if (inc == 0) { |
| 10494 | pe = (volatile u_long *)pmap_large_map_pde(va); |
| 10495 | p = *pe; |
| 10496 | if ((p & X86_PG_PS) != 0) |
| 10497 | inc = NBPDR; |
| 10498 | } |
| 10499 | if (inc == 0) { |
| 10500 | pe = (volatile u_long *)pmap_large_map_pte(va); |
| 10501 | p = *pe; |
| 10502 | inc = PAGE_SIZE; |
| 10503 | } |
| 10504 | seen_other = false; |
| 10505 | for (;;) { |
| 10506 | if ((p & X86_PG_AVAIL1) != 0) { |
| 10507 | /* |
| 10508 | * Spin-wait for the end of a parallel |
| 10509 | * write-back. |
| 10510 | */ |
| 10511 | cpu_spinwait(); |
| 10512 | p = *pe; |
| 10513 | |
| 10514 | /* |
| 10515 | * If we saw other write-back |
| 10516 | * occuring, we cannot rely on PG_M to |
| 10517 | * indicate state of the cache. The |
| 10518 | * PG_M bit is cleared before the |
| 10519 | * flush to avoid ignoring new writes, |
| 10520 | * and writes which are relevant for |
| 10521 | * us might happen after. |
| 10522 | */ |
| 10523 | seen_other = true; |
| 10524 | continue; |
| 10525 | } |
| 10526 | |
| 10527 | if ((p & X86_PG_M) != 0 || seen_other) { |
| 10528 | if (!atomic_fcmpset_long(pe, &p, |
| 10529 | (p & ~X86_PG_M) | X86_PG_AVAIL1)) |
| 10530 | /* |
| 10531 | * If we saw PG_M without |
| 10532 | * PG_AVAIL1, and then on the |
| 10533 | * next attempt we do not |
no test coverage detected