aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-01-30 07:34:07 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:34:07 -0500
commitf62d0f008e889915c93631c04d4c7d871f05bea7 (patch)
tree36eb08ed99de278c77ef58df06b282736ff19b08
parentd806e5ee20f62a892b09aa59559f143d465285db (diff)
x86: cpa: set_memory_notpresent()
Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/mm/init_64.c17
-rw-r--r--arch/x86/mm/pageattr.c34
-rw-r--r--include/asm-x86/cacheflush.h1
3 files changed, 42 insertions, 10 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 05bb12db0b09..4757be7b5e55 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -559,8 +559,21 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
559 free_page(addr); 559 free_page(addr);
560 totalram_pages++; 560 totalram_pages++;
561 } 561 }
562 if (addr > __START_KERNEL_map) 562#ifdef CONFIG_DEBUG_RODATA
563 global_flush_tlb(); 563 /*
564 * This will make the __init pages not present and
565 * not executable, so that any attempt to use a
566 * __init function from now on will fault immediately
567 * rather than supriously later when memory gets reused.
568 *
569 * We only do this for DEBUG_RODATA to not break up the
570 * 2Mb kernel mapping just for this debug feature.
571 */
572 if (begin >= __START_KERNEL_map) {
573 set_memory_np(begin, (end - begin)/PAGE_SIZE);
574 set_memory_nx(begin, (end - begin)/PAGE_SIZE);
575 }
576#endif
564} 577}
565 578
566void free_initmem(void) 579void free_initmem(void)
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index fcd96125c5ae..e5910ac37e59 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -357,8 +357,6 @@ int change_page_attr_clear(unsigned long addr, int numpages, pgprot_t prot)
357 return change_page_attr_addr(addr, numpages, prot); 357 return change_page_attr_addr(addr, numpages, prot);
358} 358}
359 359
360
361
362int set_memory_uc(unsigned long addr, int numpages) 360int set_memory_uc(unsigned long addr, int numpages)
363{ 361{
364 pgprot_t uncached; 362 pgprot_t uncached;
@@ -402,7 +400,6 @@ int set_memory_ro(unsigned long addr, int numpages)
402 pgprot_val(rw) = _PAGE_RW; 400 pgprot_val(rw) = _PAGE_RW;
403 return change_page_attr_clear(addr, numpages, rw); 401 return change_page_attr_clear(addr, numpages, rw);
404} 402}
405EXPORT_SYMBOL(set_memory_ro);
406 403
407int set_memory_rw(unsigned long addr, int numpages) 404int set_memory_rw(unsigned long addr, int numpages)
408{ 405{
@@ -411,7 +408,14 @@ int set_memory_rw(unsigned long addr, int numpages)
411 pgprot_val(rw) = _PAGE_RW; 408 pgprot_val(rw) = _PAGE_RW;
412 return change_page_attr_set(addr, numpages, rw); 409 return change_page_attr_set(addr, numpages, rw);
413} 410}
414EXPORT_SYMBOL(set_memory_rw); 411
412int set_memory_np(unsigned long addr, int numpages)
413{
414 pgprot_t present;
415
416 pgprot_val(present) = _PAGE_PRESENT;
417 return change_page_attr_clear(addr, numpages, present);
418}
415 419
416int set_pages_uc(struct page *page, int numpages) 420int set_pages_uc(struct page *page, int numpages)
417{ 421{
@@ -461,7 +465,6 @@ int set_pages_ro(struct page *page, int numpages)
461 pgprot_val(rw) = _PAGE_RW; 465 pgprot_val(rw) = _PAGE_RW;
462 return change_page_attr_clear(addr, numpages, rw); 466 return change_page_attr_clear(addr, numpages, rw);
463} 467}
464EXPORT_SYMBOL(set_pages_ro);
465 468
466int set_pages_rw(struct page *page, int numpages) 469int set_pages_rw(struct page *page, int numpages)
467{ 470{
@@ -471,8 +474,6 @@ int set_pages_rw(struct page *page, int numpages)
471 pgprot_val(rw) = _PAGE_RW; 474 pgprot_val(rw) = _PAGE_RW;
472 return change_page_attr_set(addr, numpages, rw); 475 return change_page_attr_set(addr, numpages, rw);
473} 476}
474EXPORT_SYMBOL(set_pages_rw);
475
476 477
477void clflush_cache_range(void *addr, int size) 478void clflush_cache_range(void *addr, int size)
478{ 479{
@@ -503,6 +504,20 @@ void global_flush_tlb(void)
503EXPORT_SYMBOL(global_flush_tlb); 504EXPORT_SYMBOL(global_flush_tlb);
504 505
505#ifdef CONFIG_DEBUG_PAGEALLOC 506#ifdef CONFIG_DEBUG_PAGEALLOC
507
508static int __set_pages_p(struct page *page, int numpages)
509{
510 unsigned long addr = (unsigned long)page_address(page);
511 return change_page_attr_set(addr, numpages,
512 __pgprot(_PAGE_PRESENT | _PAGE_RW));
513}
514
515static int __set_pages_np(struct page *page, int numpages)
516{
517 unsigned long addr = (unsigned long)page_address(page);
518 return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
519}
520
506void kernel_map_pages(struct page *page, int numpages, int enable) 521void kernel_map_pages(struct page *page, int numpages, int enable)
507{ 522{
508 if (PageHighMem(page)) 523 if (PageHighMem(page))
@@ -522,7 +537,10 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
522 * The return value is ignored - the calls cannot fail, 537 * The return value is ignored - the calls cannot fail,
523 * large pages are disabled at boot time: 538 * large pages are disabled at boot time:
524 */ 539 */
525 change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); 540 if (enable)
541 __set_pages_p(page, numpages);
542 else
543 __set_pages_np(page, numpages);
526 544
527 /* 545 /*
528 * We should perform an IPI and flush all tlbs, 546 * We should perform an IPI and flush all tlbs,
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
index e79159bc0987..a95afaf1240d 100644
--- a/include/asm-x86/cacheflush.h
+++ b/include/asm-x86/cacheflush.h
@@ -42,6 +42,7 @@ int set_memory_x(unsigned long addr, int numpages);
42int set_memory_nx(unsigned long addr, int numpages); 42int set_memory_nx(unsigned long addr, int numpages);
43int set_memory_ro(unsigned long addr, int numpages); 43int set_memory_ro(unsigned long addr, int numpages);
44int set_memory_rw(unsigned long addr, int numpages); 44int set_memory_rw(unsigned long addr, int numpages);
45int set_memory_np(unsigned long addr, int numpages);
45 46
46void clflush_cache_range(void *addr, int size); 47void clflush_cache_range(void *addr, int size);
47 48