* Super fast pmap_pte2 routine best used when scanning * the pv lists. This eliminates many coarse-grained * invltlb calls. Note that many of the pv list * scans are across different pmaps. It is very wasteful * to do an entire tlb flush for checking a single mapping. * * If the given pmap is not the current pmap, pvh_global_lock * must be held and curthread pinned to a CPU. */
| 1909 | * must be held and curthread pinned to a CPU. |
| 1910 | */ |
| 1911 | static pt2_entry_t * |
| 1912 | pmap_pte2_quick(pmap_t pmap, vm_offset_t va) |
| 1913 | { |
| 1914 | pt1_entry_t pte1; |
| 1915 | vm_paddr_t pt2pg_pa; |
| 1916 | |
| 1917 | pte1 = pte1_load(pmap_pte1(pmap, va)); |
| 1918 | if (pte1_is_section(pte1)) |
| 1919 | panic("%s: attempt to map PTE1", __func__); |
| 1920 | if (pte1_is_link(pte1)) { |
| 1921 | /* Are we current address space or kernel? */ |
| 1922 | if (pmap_is_current(pmap)) |
| 1923 | return (pt2map_entry(va)); |
| 1924 | rw_assert(&pvh_global_lock, RA_WLOCKED); |
| 1925 | KASSERT(curthread->td_pinned > 0, |
| 1926 | ("%s: curthread not pinned", __func__)); |
| 1927 | /* Note that L2 page table size is not equal to PAGE_SIZE. */ |
| 1928 | pt2pg_pa = trunc_page(pte1_link_pa(pte1)); |
| 1929 | if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) { |
| 1930 | pte2_store(PMAP1, PTE2_KPT(pt2pg_pa)); |
| 1931 | #ifdef SMP |
| 1932 | PMAP1cpu = PCPU_GET(cpuid); |
| 1933 | #endif |
| 1934 | tlb_flush_local((vm_offset_t)PADDR1); |
| 1935 | PMAP1changed++; |
| 1936 | } else |
| 1937 | #ifdef SMP |
| 1938 | if (PMAP1cpu != PCPU_GET(cpuid)) { |
| 1939 | PMAP1cpu = PCPU_GET(cpuid); |
| 1940 | tlb_flush_local((vm_offset_t)PADDR1); |
| 1941 | PMAP1changedcpu++; |
| 1942 | } else |
| 1943 | #endif |
| 1944 | PMAP1unchanged++; |
| 1945 | return (PADDR1 + (arm32_btop(va) & (NPTE2_IN_PG - 1))); |
| 1946 | } |
| 1947 | return (NULL); |
| 1948 | } |
| 1949 | |
| 1950 | /* |
| 1951 | * Routine: pmap_extract |
no test coverage detected