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 | |
parent | e80a0e6e7ccdf64575d4384cb4172860422f5b81 (diff) | |
parent | 7d477a04a619e90ee08724e8f2d8803c6bdfcef8 (diff) |
Merge ARM fixes
Diffstat (limited to 'arch/i386/mm')
-rw-r--r-- | arch/i386/mm/discontig.c | 1 | ||||
-rw-r--r-- | arch/i386/mm/fault.c | 44 | ||||
-rw-r--r-- | arch/i386/mm/highmem.c | 7 | ||||
-rw-r--r-- | arch/i386/mm/init.c | 4 | ||||
-rw-r--r-- | arch/i386/mm/pageattr.c | 4 | ||||
-rw-r--r-- | arch/i386/mm/pgtable.c | 26 |
6 files changed, 41 insertions, 45 deletions
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index e0c390d6ceb5..aa58720f6871 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c | |||
@@ -101,7 +101,6 @@ extern void find_max_pfn(void); | |||
101 | extern void add_one_highpage_init(struct page *, int, int); | 101 | extern void add_one_highpage_init(struct page *, int, int); |
102 | 102 | ||
103 | extern struct e820map e820; | 103 | extern struct e820map e820; |
104 | extern unsigned long init_pg_tables_end; | ||
105 | extern unsigned long highend_pfn, highstart_pfn; | 104 | extern unsigned long highend_pfn, highstart_pfn; |
106 | extern unsigned long max_low_pfn; | 105 | extern unsigned long max_low_pfn; |
107 | extern unsigned long totalram_pages; | 106 | extern unsigned long totalram_pages; |
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index aaaa4d225f7e..b8c4e259fc8b 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c | |||
@@ -46,43 +46,17 @@ int unregister_page_fault_notifier(struct notifier_block *nb) | |||
46 | } | 46 | } |
47 | EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); | 47 | EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); |
48 | 48 | ||
49 | static inline int notify_page_fault(enum die_val val, const char *str, | 49 | static inline int notify_page_fault(struct pt_regs *regs, long err) |
50 | struct pt_regs *regs, long err, int trap, int sig) | ||
51 | { | 50 | { |
52 | struct die_args args = { | 51 | struct die_args args = { |
53 | .regs = regs, | 52 | .regs = regs, |
54 | .str = str, | 53 | .str = "page fault", |
55 | .err = err, | 54 | .err = err, |
56 | .trapnr = trap, | 55 | .trapnr = 14, |
57 | .signr = sig | 56 | .signr = SIGSEGV |
58 | }; | 57 | }; |
59 | return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); | 58 | return atomic_notifier_call_chain(¬ify_page_fault_chain, |
60 | } | 59 | DIE_PAGE_FAULT, &args); |
61 | |||
62 | /* | ||
63 | * Unlock any spinlocks which will prevent us from getting the | ||
64 | * message out | ||
65 | */ | ||
66 | void bust_spinlocks(int yes) | ||
67 | { | ||
68 | int loglevel_save = console_loglevel; | ||
69 | |||
70 | if (yes) { | ||
71 | oops_in_progress = 1; | ||
72 | return; | ||
73 | } | ||
74 | #ifdef CONFIG_VT | ||
75 | unblank_screen(); | ||
76 | #endif | ||
77 | oops_in_progress = 0; | ||
78 | /* | ||
79 | * OK, the message is on the console. Now we call printk() | ||
80 | * without oops_in_progress set so that printk will give klogd | ||
81 | * a poke. Hold onto your hats... | ||
82 | */ | ||
83 | console_loglevel = 15; /* NMI oopser may have shut the console up */ | ||
84 | printk(" "); | ||
85 | console_loglevel = loglevel_save; | ||
86 | } | 60 | } |
87 | 61 | ||
88 | /* | 62 | /* |
@@ -353,8 +327,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
353 | if (unlikely(address >= TASK_SIZE)) { | 327 | if (unlikely(address >= TASK_SIZE)) { |
354 | if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) | 328 | if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) |
355 | return; | 329 | return; |
356 | if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 330 | if (notify_page_fault(regs, error_code) == NOTIFY_STOP) |
357 | SIGSEGV) == NOTIFY_STOP) | ||
358 | return; | 331 | return; |
359 | /* | 332 | /* |
360 | * Don't take the mm semaphore here. If we fixup a prefetch | 333 | * Don't take the mm semaphore here. If we fixup a prefetch |
@@ -363,8 +336,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
363 | goto bad_area_nosemaphore; | 336 | goto bad_area_nosemaphore; |
364 | } | 337 | } |
365 | 338 | ||
366 | if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 339 | if (notify_page_fault(regs, error_code) == NOTIFY_STOP) |
367 | SIGSEGV) == NOTIFY_STOP) | ||
368 | return; | 340 | return; |
369 | 341 | ||
370 | /* It's safe to allow irq's after cr2 has been saved and the vmalloc | 342 | /* It's safe to allow irq's after cr2 has been saved and the vmalloc |
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c index e0fa6cb655a8..bb2de1089add 100644 --- a/arch/i386/mm/highmem.c +++ b/arch/i386/mm/highmem.c | |||
@@ -33,13 +33,14 @@ void *kmap_atomic(struct page *page, enum km_type type) | |||
33 | 33 | ||
34 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 34 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
35 | pagefault_disable(); | 35 | pagefault_disable(); |
36 | |||
37 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
38 | BUG_ON(!pte_none(*(kmap_pte-idx))); | ||
39 | |||
36 | if (!PageHighMem(page)) | 40 | if (!PageHighMem(page)) |
37 | return page_address(page); | 41 | return page_address(page); |
38 | 42 | ||
39 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
40 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 43 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
41 | if (!pte_none(*(kmap_pte-idx))) | ||
42 | BUG(); | ||
43 | set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); | 44 | set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); |
44 | 45 | ||
45 | return (void*) vaddr; | 46 | return (void*) vaddr; |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index c5c5ea700cc7..ae436882af7a 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -62,6 +62,7 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd) | |||
62 | 62 | ||
63 | #ifdef CONFIG_X86_PAE | 63 | #ifdef CONFIG_X86_PAE |
64 | pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); | 64 | pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); |
65 | paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT); | ||
65 | set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); | 66 | set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); |
66 | pud = pud_offset(pgd, 0); | 67 | pud = pud_offset(pgd, 0); |
67 | if (pmd_table != pmd_offset(pud, 0)) | 68 | if (pmd_table != pmd_offset(pud, 0)) |
@@ -82,6 +83,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) | |||
82 | { | 83 | { |
83 | if (pmd_none(*pmd)) { | 84 | if (pmd_none(*pmd)) { |
84 | pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); | 85 | pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); |
86 | paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT); | ||
85 | set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); | 87 | set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); |
86 | if (page_table != pte_offset_kernel(pmd, 0)) | 88 | if (page_table != pte_offset_kernel(pmd, 0)) |
87 | BUG(); | 89 | BUG(); |
@@ -345,6 +347,8 @@ static void __init pagetable_init (void) | |||
345 | /* Init entries of the first-level page table to the zero page */ | 347 | /* Init entries of the first-level page table to the zero page */ |
346 | for (i = 0; i < PTRS_PER_PGD; i++) | 348 | for (i = 0; i < PTRS_PER_PGD; i++) |
347 | set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT)); | 349 | set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT)); |
350 | #else | ||
351 | paravirt_alloc_pd(__pa(swapper_pg_dir) >> PAGE_SHIFT); | ||
348 | #endif | 352 | #endif |
349 | 353 | ||
350 | /* Enable PSE if available */ | 354 | /* Enable PSE if available */ |
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index ad91528bdc14..412ebbd8adb0 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c | |||
@@ -60,6 +60,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, | |||
60 | address = __pa(address); | 60 | address = __pa(address); |
61 | addr = address & LARGE_PAGE_MASK; | 61 | addr = address & LARGE_PAGE_MASK; |
62 | pbase = (pte_t *)page_address(base); | 62 | pbase = (pte_t *)page_address(base); |
63 | paravirt_alloc_pt(page_to_pfn(base)); | ||
63 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { | 64 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { |
64 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, | 65 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, |
65 | addr == address ? prot : ref_prot)); | 66 | addr == address ? prot : ref_prot)); |
@@ -172,6 +173,7 @@ __change_page_attr(struct page *page, pgprot_t prot) | |||
172 | if (!PageReserved(kpte_page)) { | 173 | if (!PageReserved(kpte_page)) { |
173 | if (cpu_has_pse && (page_private(kpte_page) == 0)) { | 174 | if (cpu_has_pse && (page_private(kpte_page) == 0)) { |
174 | ClearPagePrivate(kpte_page); | 175 | ClearPagePrivate(kpte_page); |
176 | paravirt_release_pt(page_to_pfn(kpte_page)); | ||
175 | list_add(&kpte_page->lru, &df_list); | 177 | list_add(&kpte_page->lru, &df_list); |
176 | revert_page(kpte_page, address); | 178 | revert_page(kpte_page, address); |
177 | } | 179 | } |
@@ -224,7 +226,7 @@ void global_flush_tlb(void) | |||
224 | list_replace_init(&df_list, &l); | 226 | list_replace_init(&df_list, &l); |
225 | spin_unlock_irq(&cpa_lock); | 227 | spin_unlock_irq(&cpa_lock); |
226 | if (!cpu_has_clflush) | 228 | if (!cpu_has_clflush) |
227 | flush_map(0); | 229 | flush_map(NULL); |
228 | list_for_each_entry_safe(pg, next, &l, lru) { | 230 | list_for_each_entry_safe(pg, next, &l, lru) { |
229 | if (cpu_has_clflush) | 231 | if (cpu_has_clflush) |
230 | flush_map(page_address(pg)); | 232 | flush_map(page_address(pg)); |
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 | } |