aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/mm
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2007-02-20 14:13:30 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-02-20 14:13:30 -0500
commit5a84d159061d914c8dd4aa372ac6e9529c2be453 (patch)
tree9b08af78085334af44414adafe0096276f8fe0ff /arch/i386/mm
parente80a0e6e7ccdf64575d4384cb4172860422f5b81 (diff)
parent7d477a04a619e90ee08724e8f2d8803c6bdfcef8 (diff)
Merge ARM fixes
Diffstat (limited to 'arch/i386/mm')
-rw-r--r--arch/i386/mm/discontig.c1
-rw-r--r--arch/i386/mm/fault.c44
-rw-r--r--arch/i386/mm/highmem.c7
-rw-r--r--arch/i386/mm/init.c4
-rw-r--r--arch/i386/mm/pageattr.c4
-rw-r--r--arch/i386/mm/pgtable.c26
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);
101extern void add_one_highpage_init(struct page *, int, int); 101extern void add_one_highpage_init(struct page *, int, int);
102 102
103extern struct e820map e820; 103extern struct e820map e820;
104extern unsigned long init_pg_tables_end;
105extern unsigned long highend_pfn, highstart_pfn; 104extern unsigned long highend_pfn, highstart_pfn;
106extern unsigned long max_low_pfn; 105extern unsigned long max_low_pfn;
107extern unsigned long totalram_pages; 106extern 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}
47EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); 47EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
48 48
49static inline int notify_page_fault(enum die_val val, const char *str, 49static 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(&notify_page_fault_chain, val, &args); 58 return atomic_notifier_call_chain(&notify_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 */
66void 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)
171void reserve_top_address(unsigned long reserve) 171void 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
284out_oom: 294out_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}