diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:34:07 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:34:07 -0500 |
commit | f62d0f008e889915c93631c04d4c7d871f05bea7 (patch) | |
tree | 36eb08ed99de278c77ef58df06b282736ff19b08 | |
parent | d806e5ee20f62a892b09aa59559f143d465285db (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.c | 17 | ||||
-rw-r--r-- | arch/x86/mm/pageattr.c | 34 | ||||
-rw-r--r-- | include/asm-x86/cacheflush.h | 1 |
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 | ||
566 | void free_initmem(void) | 579 | void 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 | |||
362 | int set_memory_uc(unsigned long addr, int numpages) | 360 | int 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 | } |
405 | EXPORT_SYMBOL(set_memory_ro); | ||
406 | 403 | ||
407 | int set_memory_rw(unsigned long addr, int numpages) | 404 | int 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 | } |
414 | EXPORT_SYMBOL(set_memory_rw); | 411 | |
412 | int 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 | ||
416 | int set_pages_uc(struct page *page, int numpages) | 420 | int 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 | } |
464 | EXPORT_SYMBOL(set_pages_ro); | ||
465 | 468 | ||
466 | int set_pages_rw(struct page *page, int numpages) | 469 | int 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 | } |
474 | EXPORT_SYMBOL(set_pages_rw); | ||
475 | |||
476 | 477 | ||
477 | void clflush_cache_range(void *addr, int size) | 478 | void clflush_cache_range(void *addr, int size) |
478 | { | 479 | { |
@@ -503,6 +504,20 @@ void global_flush_tlb(void) | |||
503 | EXPORT_SYMBOL(global_flush_tlb); | 504 | EXPORT_SYMBOL(global_flush_tlb); |
504 | 505 | ||
505 | #ifdef CONFIG_DEBUG_PAGEALLOC | 506 | #ifdef CONFIG_DEBUG_PAGEALLOC |
507 | |||
508 | static 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 | |||
515 | static 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 | |||
506 | void kernel_map_pages(struct page *page, int numpages, int enable) | 521 | void 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); | |||
42 | int set_memory_nx(unsigned long addr, int numpages); | 42 | int set_memory_nx(unsigned long addr, int numpages); |
43 | int set_memory_ro(unsigned long addr, int numpages); | 43 | int set_memory_ro(unsigned long addr, int numpages); |
44 | int set_memory_rw(unsigned long addr, int numpages); | 44 | int set_memory_rw(unsigned long addr, int numpages); |
45 | int set_memory_np(unsigned long addr, int numpages); | ||
45 | 46 | ||
46 | void clflush_cache_range(void *addr, int size); | 47 | void clflush_cache_range(void *addr, int size); |
47 | 48 | ||