Implement pud_free_pmd_page() and pmd_free_pte_page() on x86, which clear a given pud/pmd entry and free up lower level page table(s). The address range associated with the pud/pmd entry must have been purged by INVLPG.
Unified · Split
| @@ -712,7 +712,22 @@ int pmd_clear_huge(pmd_t *pmd) · 711 unmodified lines | |||
| 712 | */ | 712 | */ |
| 713 | int pud_free_pmd_page(pud_t *pud) | 713 | int pud_free_pmd_page(pud_t *pud) |
| 714 | { | 714 | { |
| 715 | return pud_none(*pud); | 715 | pmd_t *pmd; |
| 716 | int i; | ||
| 717 | |||
| 718 | if (pud_none(*pud)) | ||
| 719 | return 1; | ||
| 720 | |||
| 721 | pmd = (pmd_t *)pud_page_vaddr(*pud); | ||
| 722 | |||
| 723 | for (i = 0; i < PTRS_PER_PMD; i++) | ||
| 724 | if (!pmd_free_pte_page(&pmd[i])) | ||
| 725 | return 0; | ||
| 726 | |||
| 727 | pud_clear(pud); | ||
| 728 | free_page((unsigned long)pmd); | ||
| 729 | |||
| 730 | return 1; | ||
| 716 | } | 731 | } |
| 717 | 732 | ||
| 718 | /** | 733 | /** |
| @@ -724,6 +739,15 @@ int pud_free_pmd_page(pud_t *pud) · 5 unmodified lines | |||
| 724 | */ | 739 | */ |
| 725 | int pmd_free_pte_page(pmd_t *pmd) | 740 | int pmd_free_pte_page(pmd_t *pmd) |
| 726 | { | 741 | { |
| 727 | return pmd_none(*pmd); | 742 | pte_t *pte; |
| 743 | |||
| 744 | if (pmd_none(*pmd)) | ||
| 745 | return 1; | ||
| 746 | |||
| 747 | pte = (pte_t *)pmd_page_vaddr(*pmd); | ||
| 748 | pmd_clear(pmd); | ||
| 749 | free_page((unsigned long)pte); | ||
| 750 | |||
| 751 | return 1; | ||
| 728 | } | 752 | } |
| 729 | #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ | 753 | #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ |