diff options
-rw-r--r-- | arch/x86/mm/pageattr_32.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/arch/x86/mm/pageattr_32.c b/arch/x86/mm/pageattr_32.c index 570a37bf1401..1011b21f8db0 100644 --- a/arch/x86/mm/pageattr_32.c +++ b/arch/x86/mm/pageattr_32.c | |||
@@ -38,7 +38,7 @@ pte_t *lookup_address(unsigned long address, int *level) | |||
38 | } | 38 | } |
39 | 39 | ||
40 | static struct page * | 40 | static struct page * |
41 | split_large_page(unsigned long address, pgprot_t prot, pgprot_t ref_prot) | 41 | split_large_page(unsigned long address, pgprot_t ref_prot) |
42 | { | 42 | { |
43 | unsigned long addr; | 43 | unsigned long addr; |
44 | struct page *base; | 44 | struct page *base; |
@@ -58,10 +58,9 @@ split_large_page(unsigned long address, pgprot_t prot, pgprot_t ref_prot) | |||
58 | pbase = (pte_t *)page_address(base); | 58 | pbase = (pte_t *)page_address(base); |
59 | paravirt_alloc_pt(&init_mm, page_to_pfn(base)); | 59 | paravirt_alloc_pt(&init_mm, page_to_pfn(base)); |
60 | 60 | ||
61 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { | 61 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) |
62 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, | 62 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, ref_prot)); |
63 | addr == address ? prot : ref_prot)); | 63 | |
64 | } | ||
65 | return base; | 64 | return base; |
66 | } | 65 | } |
67 | 66 | ||
@@ -101,6 +100,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot) | |||
101 | BUG_ON(PageHighMem(page)); | 100 | BUG_ON(PageHighMem(page)); |
102 | address = (unsigned long)page_address(page); | 101 | address = (unsigned long)page_address(page); |
103 | 102 | ||
103 | repeat: | ||
104 | kpte = lookup_address(address, &level); | 104 | kpte = lookup_address(address, &level); |
105 | if (!kpte) | 105 | if (!kpte) |
106 | return -EINVAL; | 106 | return -EINVAL; |
@@ -128,7 +128,8 @@ static int __change_page_attr(struct page *page, pgprot_t prot) | |||
128 | set_pte_atomic(kpte, mk_pte(page, prot)); | 128 | set_pte_atomic(kpte, mk_pte(page, prot)); |
129 | } else { | 129 | } else { |
130 | struct page *split; | 130 | struct page *split; |
131 | split = split_large_page(address, prot, ref_prot); | 131 | |
132 | split = split_large_page(address, ref_prot); | ||
132 | if (!split) | 133 | if (!split) |
133 | return -ENOMEM; | 134 | return -ENOMEM; |
134 | 135 | ||
@@ -136,6 +137,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot) | |||
136 | * There's a small window here to waste a bit of RAM: | 137 | * There's a small window here to waste a bit of RAM: |
137 | */ | 138 | */ |
138 | set_pmd_pte(kpte, address, mk_pte(split, ref_prot)); | 139 | set_pmd_pte(kpte, address, mk_pte(split, ref_prot)); |
140 | goto repeat; | ||
139 | } | 141 | } |
140 | return 0; | 142 | return 0; |
141 | } | 143 | } |