diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-02-20 14:13:30 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-20 14:13:30 -0500 |
commit | 5a84d159061d914c8dd4aa372ac6e9529c2be453 (patch) | |
tree | 9b08af78085334af44414adafe0096276f8fe0ff /arch/i386/mm/pgtable.c | |
parent | e80a0e6e7ccdf64575d4384cb4172860422f5b81 (diff) | |
parent | 7d477a04a619e90ee08724e8f2d8803c6bdfcef8 (diff) |
Merge ARM fixes
Diffstat (limited to 'arch/i386/mm/pgtable.c')
-rw-r--r-- | arch/i386/mm/pgtable.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index f349eaf450b0..fa0cfbd551e1 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c | |||
@@ -171,6 +171,8 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags) | |||
171 | void reserve_top_address(unsigned long reserve) | 171 | void reserve_top_address(unsigned long reserve) |
172 | { | 172 | { |
173 | BUG_ON(fixmaps > 0); | 173 | BUG_ON(fixmaps > 0); |
174 | printk(KERN_INFO "Reserving virtual address space above 0x%08x\n", | ||
175 | (int)-reserve); | ||
174 | #ifdef CONFIG_COMPAT_VDSO | 176 | #ifdef CONFIG_COMPAT_VDSO |
175 | BUG_ON(reserve != 0); | 177 | BUG_ON(reserve != 0); |
176 | #else | 178 | #else |
@@ -248,9 +250,15 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) | |||
248 | clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD, | 250 | clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD, |
249 | swapper_pg_dir + USER_PTRS_PER_PGD, | 251 | swapper_pg_dir + USER_PTRS_PER_PGD, |
250 | KERNEL_PGD_PTRS); | 252 | KERNEL_PGD_PTRS); |
253 | |||
251 | if (PTRS_PER_PMD > 1) | 254 | if (PTRS_PER_PMD > 1) |
252 | return; | 255 | return; |
253 | 256 | ||
257 | /* must happen under lock */ | ||
258 | paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT, | ||
259 | __pa(swapper_pg_dir) >> PAGE_SHIFT, | ||
260 | USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD); | ||
261 | |||
254 | pgd_list_add(pgd); | 262 | pgd_list_add(pgd); |
255 | spin_unlock_irqrestore(&pgd_lock, flags); | 263 | spin_unlock_irqrestore(&pgd_lock, flags); |
256 | } | 264 | } |
@@ -260,6 +268,7 @@ void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) | |||
260 | { | 268 | { |
261 | unsigned long flags; /* can be called from interrupt context */ | 269 | unsigned long flags; /* can be called from interrupt context */ |
262 | 270 | ||
271 | paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT); | ||
263 | spin_lock_irqsave(&pgd_lock, flags); | 272 | spin_lock_irqsave(&pgd_lock, flags); |
264 | pgd_list_del(pgd); | 273 | pgd_list_del(pgd); |
265 | spin_unlock_irqrestore(&pgd_lock, flags); | 274 | spin_unlock_irqrestore(&pgd_lock, flags); |
@@ -277,13 +286,18 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
277 | pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); | 286 | pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); |
278 | if (!pmd) | 287 | if (!pmd) |
279 | goto out_oom; | 288 | goto out_oom; |
289 | paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT); | ||
280 | set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); | 290 | set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); |
281 | } | 291 | } |
282 | return pgd; | 292 | return pgd; |
283 | 293 | ||
284 | out_oom: | 294 | out_oom: |
285 | for (i--; i >= 0; i--) | 295 | for (i--; i >= 0; i--) { |
286 | kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1)); | 296 | pgd_t pgdent = pgd[i]; |
297 | void* pmd = (void *)__va(pgd_val(pgdent)-1); | ||
298 | paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); | ||
299 | kmem_cache_free(pmd_cache, pmd); | ||
300 | } | ||
287 | kmem_cache_free(pgd_cache, pgd); | 301 | kmem_cache_free(pgd_cache, pgd); |
288 | return NULL; | 302 | return NULL; |
289 | } | 303 | } |
@@ -294,8 +308,12 @@ void pgd_free(pgd_t *pgd) | |||
294 | 308 | ||
295 | /* in the PAE case user pgd entries are overwritten before usage */ | 309 | /* in the PAE case user pgd entries are overwritten before usage */ |
296 | if (PTRS_PER_PMD > 1) | 310 | if (PTRS_PER_PMD > 1) |
297 | for (i = 0; i < USER_PTRS_PER_PGD; ++i) | 311 | for (i = 0; i < USER_PTRS_PER_PGD; ++i) { |
298 | kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1)); | 312 | pgd_t pgdent = pgd[i]; |
313 | void* pmd = (void *)__va(pgd_val(pgdent)-1); | ||
314 | paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); | ||
315 | kmem_cache_free(pmd_cache, pmd); | ||
316 | } | ||
299 | /* in the non-PAE case, free_pgtables() clears user pgd entries */ | 317 | /* in the non-PAE case, free_pgtables() clears user pgd entries */ |
300 | kmem_cache_free(pgd_cache, pgd); | 318 | kmem_cache_free(pgd_cache, pgd); |
301 | } | 319 | } |