diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 60 |
1 files changed, 28 insertions, 32 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 8b72923f1d35..af11a2890235 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -800,17 +800,11 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap, | |||
800 | 800 | ||
801 | #define PAGE_INUSE 0xFD | 801 | #define PAGE_INUSE 0xFD |
802 | 802 | ||
803 | static void __meminit free_pagetable(struct page *page, int order, | 803 | static void __meminit free_pagetable(struct page *page, int order) |
804 | struct vmem_altmap *altmap) | ||
805 | { | 804 | { |
806 | unsigned long magic; | 805 | unsigned long magic; |
807 | unsigned int nr_pages = 1 << order; | 806 | unsigned int nr_pages = 1 << order; |
808 | 807 | ||
809 | if (altmap) { | ||
810 | vmem_altmap_free(altmap, nr_pages); | ||
811 | return; | ||
812 | } | ||
813 | |||
814 | /* bootmem page has reserved flag */ | 808 | /* bootmem page has reserved flag */ |
815 | if (PageReserved(page)) { | 809 | if (PageReserved(page)) { |
816 | __ClearPageReserved(page); | 810 | __ClearPageReserved(page); |
@@ -826,9 +820,17 @@ static void __meminit free_pagetable(struct page *page, int order, | |||
826 | free_pages((unsigned long)page_address(page), order); | 820 | free_pages((unsigned long)page_address(page), order); |
827 | } | 821 | } |
828 | 822 | ||
829 | static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd, | 823 | static void __meminit free_hugepage_table(struct page *page, |
830 | struct vmem_altmap *altmap) | 824 | struct vmem_altmap *altmap) |
831 | { | 825 | { |
826 | if (altmap) | ||
827 | vmem_altmap_free(altmap, PMD_SIZE / PAGE_SIZE); | ||
828 | else | ||
829 | free_pagetable(page, get_order(PMD_SIZE)); | ||
830 | } | ||
831 | |||
832 | static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd) | ||
833 | { | ||
832 | pte_t *pte; | 834 | pte_t *pte; |
833 | int i; | 835 | int i; |
834 | 836 | ||
@@ -839,14 +841,13 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd, | |||
839 | } | 841 | } |
840 | 842 | ||
841 | /* free a pte talbe */ | 843 | /* free a pte talbe */ |
842 | free_pagetable(pmd_page(*pmd), 0, altmap); | 844 | free_pagetable(pmd_page(*pmd), 0); |
843 | spin_lock(&init_mm.page_table_lock); | 845 | spin_lock(&init_mm.page_table_lock); |
844 | pmd_clear(pmd); | 846 | pmd_clear(pmd); |
845 | spin_unlock(&init_mm.page_table_lock); | 847 | spin_unlock(&init_mm.page_table_lock); |
846 | } | 848 | } |
847 | 849 | ||
848 | static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, | 850 | static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud) |
849 | struct vmem_altmap *altmap) | ||
850 | { | 851 | { |
851 | pmd_t *pmd; | 852 | pmd_t *pmd; |
852 | int i; | 853 | int i; |
@@ -858,14 +859,13 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, | |||
858 | } | 859 | } |
859 | 860 | ||
860 | /* free a pmd talbe */ | 861 | /* free a pmd talbe */ |
861 | free_pagetable(pud_page(*pud), 0, altmap); | 862 | free_pagetable(pud_page(*pud), 0); |
862 | spin_lock(&init_mm.page_table_lock); | 863 | spin_lock(&init_mm.page_table_lock); |
863 | pud_clear(pud); | 864 | pud_clear(pud); |
864 | spin_unlock(&init_mm.page_table_lock); | 865 | spin_unlock(&init_mm.page_table_lock); |
865 | } | 866 | } |
866 | 867 | ||
867 | static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d, | 868 | static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d) |
868 | struct vmem_altmap *altmap) | ||
869 | { | 869 | { |
870 | pud_t *pud; | 870 | pud_t *pud; |
871 | int i; | 871 | int i; |
@@ -877,7 +877,7 @@ static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d, | |||
877 | } | 877 | } |
878 | 878 | ||
879 | /* free a pud talbe */ | 879 | /* free a pud talbe */ |
880 | free_pagetable(p4d_page(*p4d), 0, altmap); | 880 | free_pagetable(p4d_page(*p4d), 0); |
881 | spin_lock(&init_mm.page_table_lock); | 881 | spin_lock(&init_mm.page_table_lock); |
882 | p4d_clear(p4d); | 882 | p4d_clear(p4d); |
883 | spin_unlock(&init_mm.page_table_lock); | 883 | spin_unlock(&init_mm.page_table_lock); |
@@ -885,7 +885,7 @@ static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d, | |||
885 | 885 | ||
886 | static void __meminit | 886 | static void __meminit |
887 | remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end, | 887 | remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end, |
888 | struct vmem_altmap *altmap, bool direct) | 888 | bool direct) |
889 | { | 889 | { |
890 | unsigned long next, pages = 0; | 890 | unsigned long next, pages = 0; |
891 | pte_t *pte; | 891 | pte_t *pte; |
@@ -916,7 +916,7 @@ remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end, | |||
916 | * freed when offlining, or simplely not in use. | 916 | * freed when offlining, or simplely not in use. |
917 | */ | 917 | */ |
918 | if (!direct) | 918 | if (!direct) |
919 | free_pagetable(pte_page(*pte), 0, altmap); | 919 | free_pagetable(pte_page(*pte), 0); |
920 | 920 | ||
921 | spin_lock(&init_mm.page_table_lock); | 921 | spin_lock(&init_mm.page_table_lock); |
922 | pte_clear(&init_mm, addr, pte); | 922 | pte_clear(&init_mm, addr, pte); |
@@ -939,7 +939,7 @@ remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end, | |||
939 | 939 | ||
940 | page_addr = page_address(pte_page(*pte)); | 940 | page_addr = page_address(pte_page(*pte)); |
941 | if (!memchr_inv(page_addr, PAGE_INUSE, PAGE_SIZE)) { | 941 | if (!memchr_inv(page_addr, PAGE_INUSE, PAGE_SIZE)) { |
942 | free_pagetable(pte_page(*pte), 0, altmap); | 942 | free_pagetable(pte_page(*pte), 0); |
943 | 943 | ||
944 | spin_lock(&init_mm.page_table_lock); | 944 | spin_lock(&init_mm.page_table_lock); |
945 | pte_clear(&init_mm, addr, pte); | 945 | pte_clear(&init_mm, addr, pte); |
@@ -974,9 +974,8 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end, | |||
974 | if (IS_ALIGNED(addr, PMD_SIZE) && | 974 | if (IS_ALIGNED(addr, PMD_SIZE) && |
975 | IS_ALIGNED(next, PMD_SIZE)) { | 975 | IS_ALIGNED(next, PMD_SIZE)) { |
976 | if (!direct) | 976 | if (!direct) |
977 | free_pagetable(pmd_page(*pmd), | 977 | free_hugepage_table(pmd_page(*pmd), |
978 | get_order(PMD_SIZE), | 978 | altmap); |
979 | altmap); | ||
980 | 979 | ||
981 | spin_lock(&init_mm.page_table_lock); | 980 | spin_lock(&init_mm.page_table_lock); |
982 | pmd_clear(pmd); | 981 | pmd_clear(pmd); |
@@ -989,9 +988,8 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end, | |||
989 | page_addr = page_address(pmd_page(*pmd)); | 988 | page_addr = page_address(pmd_page(*pmd)); |
990 | if (!memchr_inv(page_addr, PAGE_INUSE, | 989 | if (!memchr_inv(page_addr, PAGE_INUSE, |
991 | PMD_SIZE)) { | 990 | PMD_SIZE)) { |
992 | free_pagetable(pmd_page(*pmd), | 991 | free_hugepage_table(pmd_page(*pmd), |
993 | get_order(PMD_SIZE), | 992 | altmap); |
994 | altmap); | ||
995 | 993 | ||
996 | spin_lock(&init_mm.page_table_lock); | 994 | spin_lock(&init_mm.page_table_lock); |
997 | pmd_clear(pmd); | 995 | pmd_clear(pmd); |
@@ -1003,8 +1001,8 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end, | |||
1003 | } | 1001 | } |
1004 | 1002 | ||
1005 | pte_base = (pte_t *)pmd_page_vaddr(*pmd); | 1003 | pte_base = (pte_t *)pmd_page_vaddr(*pmd); |
1006 | remove_pte_table(pte_base, addr, next, altmap, direct); | 1004 | remove_pte_table(pte_base, addr, next, direct); |
1007 | free_pte_table(pte_base, pmd, altmap); | 1005 | free_pte_table(pte_base, pmd); |
1008 | } | 1006 | } |
1009 | 1007 | ||
1010 | /* Call free_pmd_table() in remove_pud_table(). */ | 1008 | /* Call free_pmd_table() in remove_pud_table(). */ |
@@ -1033,8 +1031,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end, | |||
1033 | IS_ALIGNED(next, PUD_SIZE)) { | 1031 | IS_ALIGNED(next, PUD_SIZE)) { |
1034 | if (!direct) | 1032 | if (!direct) |
1035 | free_pagetable(pud_page(*pud), | 1033 | free_pagetable(pud_page(*pud), |
1036 | get_order(PUD_SIZE), | 1034 | get_order(PUD_SIZE)); |
1037 | altmap); | ||
1038 | 1035 | ||
1039 | spin_lock(&init_mm.page_table_lock); | 1036 | spin_lock(&init_mm.page_table_lock); |
1040 | pud_clear(pud); | 1037 | pud_clear(pud); |
@@ -1048,8 +1045,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end, | |||
1048 | if (!memchr_inv(page_addr, PAGE_INUSE, | 1045 | if (!memchr_inv(page_addr, PAGE_INUSE, |
1049 | PUD_SIZE)) { | 1046 | PUD_SIZE)) { |
1050 | free_pagetable(pud_page(*pud), | 1047 | free_pagetable(pud_page(*pud), |
1051 | get_order(PUD_SIZE), | 1048 | get_order(PUD_SIZE)); |
1052 | altmap); | ||
1053 | 1049 | ||
1054 | spin_lock(&init_mm.page_table_lock); | 1050 | spin_lock(&init_mm.page_table_lock); |
1055 | pud_clear(pud); | 1051 | pud_clear(pud); |
@@ -1062,7 +1058,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end, | |||
1062 | 1058 | ||
1063 | pmd_base = pmd_offset(pud, 0); | 1059 | pmd_base = pmd_offset(pud, 0); |
1064 | remove_pmd_table(pmd_base, addr, next, direct, altmap); | 1060 | remove_pmd_table(pmd_base, addr, next, direct, altmap); |
1065 | free_pmd_table(pmd_base, pud, altmap); | 1061 | free_pmd_table(pmd_base, pud); |
1066 | } | 1062 | } |
1067 | 1063 | ||
1068 | if (direct) | 1064 | if (direct) |
@@ -1094,7 +1090,7 @@ remove_p4d_table(p4d_t *p4d_start, unsigned long addr, unsigned long end, | |||
1094 | * to adapt for boot-time switching between 4 and 5 level page tables. | 1090 | * to adapt for boot-time switching between 4 and 5 level page tables. |
1095 | */ | 1091 | */ |
1096 | if (CONFIG_PGTABLE_LEVELS == 5) | 1092 | if (CONFIG_PGTABLE_LEVELS == 5) |
1097 | free_pud_table(pud_base, p4d, altmap); | 1093 | free_pud_table(pud_base, p4d); |
1098 | } | 1094 | } |
1099 | 1095 | ||
1100 | if (direct) | 1096 | if (direct) |