diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:33:55 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:33:55 -0500 |
commit | 97f99fedf27f337e2d3d95ca01e321beb26edc3d (patch) | |
tree | b190c89a26e34aeca3f02dd2ca27638cc4dd9e70 /arch/x86/mm/pageattr_32.c | |
parent | 78c94abaea55df7003f3ad0e5b6c78ee1cc860bb (diff) |
x86: simplify 32-bit cpa largepage splitting
simplify 32-bit cpa largepage splitting: do a pure split and repeat
the pte lookup to get the new pte modified.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm/pageattr_32.c')
-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 | } |