* [patch 0/2] x86_64: preserve large page text mappings with CONFIG_DEBUG_RODATA @ 2009-10-14 21:46 Suresh Siddha 2009-10-14 21:46 ` [patch 1/2] x86_64: preserve large page mapping for 1st 2MB kernel txt " Suresh Siddha 2009-10-14 21:46 ` [patch 2/2] x86_64: align RODATA kernel section to 2MB " Suresh Siddha 0 siblings, 2 replies; 7+ messages in thread From: Suresh Siddha @ 2009-10-14 21:46 UTC (permalink / raw) To: hpa, mingo, tglx, arjan; +Cc: linux-kernel, chinang.ma Most of the distributions enable CONFIG_DEBUG_RODATA by default, with the assumption that the debug protection checks come with no cost. Our OLTP tests showed 1% improvement (with 2% reduction in system time and 1% increase in iowait idle time) by disabling CONFIG_DEBUG_RODATA on a two socket NHM-EP system. CONFIG_DEBUG_RODATA breaks some of the kernel text/data large page mappings to small pages, thus causing this regression. These two patches address this issue. Experiments with EL5 kernel and mainline show that the first patch in the series (preserve large page mapping for 1st 2MB kernel txt with CONFIG_DEBUG_RODATA) should recover most of the above mentioned regression. We are doing couple of more OLTP tests for the confirmation. thanks, suresh ^ permalink raw reply [flat|nested] 7+ messages in thread
* [patch 1/2] x86_64: preserve large page mapping for 1st 2MB kernel txt with CONFIG_DEBUG_RODATA 2009-10-14 21:46 [patch 0/2] x86_64: preserve large page text mappings with CONFIG_DEBUG_RODATA Suresh Siddha @ 2009-10-14 21:46 ` Suresh Siddha 2009-10-24 1:03 ` [tip:branch?] x86-64: " tip-bot for Suresh Siddha 2009-10-14 21:46 ` [patch 2/2] x86_64: align RODATA kernel section to 2MB " Suresh Siddha 1 sibling, 1 reply; 7+ messages in thread From: Suresh Siddha @ 2009-10-14 21:46 UTC (permalink / raw) To: hpa, mingo, tglx, arjan; +Cc: linux-kernel, chinang.ma, Suresh Siddha [-- Attachment #1: prevent_kernel_text_lp.patch --] [-- Type: text/plain, Size: 2438 bytes --] In the first 2MB, kernel text is co-located with kernel static page tables setup by head_64.S. CONFIG_DEBUG_RODATA chops this 2MB large page mapping to small 4KB pages as we mark the kernel text as RO, leaving the static page tables as RW. With CONFIG_DEBUG_RODATA disabled, OLTP run on NHM-EP shows 1% improvement with 2% reduction in system time and 1% improvement in iowait idle time. To recover this, move the kernel static page tables to .data section, so that we don't have to break the first 2MB of kernel text to small pages with CONFIG_DEBUG_RODATA. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> --- arch/x86/kernel/head_64.S | 3 ++- arch/x86/mm/init_64.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) Index: tree/arch/x86/kernel/head_64.S =================================================================== --- tree.orig/arch/x86/kernel/head_64.S +++ tree/arch/x86/kernel/head_64.S @@ -262,11 +262,11 @@ ENTRY(secondary_startup_64) .quad x86_64_start_kernel ENTRY(initial_gs) .quad INIT_PER_CPU_VAR(irq_stack_union) - __FINITDATA ENTRY(stack_start) .quad init_thread_union+THREAD_SIZE-8 .word 0 + __FINITDATA bad_address: jmp bad_address @@ -340,6 +340,7 @@ ENTRY(name) i = i + 1 ; \ .endr + .data /* * This default setting generates an ident mapping at address 0x100000 * and a mapping for the kernel that precisely maps virtual address Index: tree/arch/x86/mm/init_64.c =================================================================== --- tree.orig/arch/x86/mm/init_64.c +++ tree/arch/x86/mm/init_64.c @@ -698,7 +698,7 @@ static int kernel_set_to_readonly; void set_kernel_text_rw(void) { - unsigned long start = PFN_ALIGN(_stext); + unsigned long start = PFN_ALIGN(_text); unsigned long end = PFN_ALIGN(__start_rodata); if (!kernel_set_to_readonly) @@ -712,7 +712,7 @@ void set_kernel_text_rw(void) void set_kernel_text_ro(void) { - unsigned long start = PFN_ALIGN(_stext); + unsigned long start = PFN_ALIGN(_text); unsigned long end = PFN_ALIGN(__start_rodata); if (!kernel_set_to_readonly) @@ -726,7 +726,7 @@ void set_kernel_text_ro(void) void mark_rodata_ro(void) { - unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); + unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata); unsigned long rodata_start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; ^ permalink raw reply [flat|nested] 7+ messages in thread
* [tip:branch?] x86-64: preserve large page mapping for 1st 2MB kernel txt with CONFIG_DEBUG_RODATA 2009-10-14 21:46 ` [patch 1/2] x86_64: preserve large page mapping for 1st 2MB kernel txt " Suresh Siddha @ 2009-10-24 1:03 ` tip-bot for Suresh Siddha 0 siblings, 0 replies; 7+ messages in thread From: tip-bot for Suresh Siddha @ 2009-10-24 1:03 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, suresh.b.siddha, tglx Commit-ID: b9af7c0d44b8bb71e3af5e94688d076414aa8c87 Gitweb: http://git.kernel.org/tip/b9af7c0d44b8bb71e3af5e94688d076414aa8c87 Author: Suresh Siddha <suresh.b.siddha@intel.com> AuthorDate: Wed, 14 Oct 2009 14:46:55 -0700 Committer: H. Peter Anvin <hpa@zytor.com> CommitDate: Tue, 20 Oct 2009 14:46:00 +0900 x86-64: preserve large page mapping for 1st 2MB kernel txt with CONFIG_DEBUG_RODATA In the first 2MB, kernel text is co-located with kernel static page tables setup by head_64.S. CONFIG_DEBUG_RODATA chops this 2MB large page mapping to small 4KB pages as we mark the kernel text as RO, leaving the static page tables as RW. With CONFIG_DEBUG_RODATA disabled, OLTP run on NHM-EP shows 1% improvement with 2% reduction in system time and 1% improvement in iowait idle time. To recover this, move the kernel static page tables to .data section, so that we don't have to break the first 2MB of kernel text to small pages with CONFIG_DEBUG_RODATA. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <20091014220254.063193621@sbs-t61.sc.intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/kernel/head_64.S | 3 ++- arch/x86/mm/init_64.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 780cd92..b55ee4f 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -262,11 +262,11 @@ ENTRY(secondary_startup_64) .quad x86_64_start_kernel ENTRY(initial_gs) .quad INIT_PER_CPU_VAR(irq_stack_union) - __FINITDATA ENTRY(stack_start) .quad init_thread_union+THREAD_SIZE-8 .word 0 + __FINITDATA bad_address: jmp bad_address @@ -340,6 +340,7 @@ ENTRY(name) i = i + 1 ; \ .endr + .data /* * This default setting generates an ident mapping at address 0x100000 * and a mapping for the kernel that precisely maps virtual address diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index c20d30b..7dafd41 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -699,7 +699,7 @@ static int kernel_set_to_readonly; void set_kernel_text_rw(void) { - unsigned long start = PFN_ALIGN(_stext); + unsigned long start = PFN_ALIGN(_text); unsigned long end = PFN_ALIGN(__start_rodata); if (!kernel_set_to_readonly) @@ -713,7 +713,7 @@ void set_kernel_text_rw(void) void set_kernel_text_ro(void) { - unsigned long start = PFN_ALIGN(_stext); + unsigned long start = PFN_ALIGN(_text); unsigned long end = PFN_ALIGN(__start_rodata); if (!kernel_set_to_readonly) @@ -727,7 +727,7 @@ void set_kernel_text_ro(void) void mark_rodata_ro(void) { - unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); + unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata); unsigned long rodata_start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; ^ permalink raw reply [flat|nested] 7+ messages in thread
* [patch 2/2] x86_64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA 2009-10-14 21:46 [patch 0/2] x86_64: preserve large page text mappings with CONFIG_DEBUG_RODATA Suresh Siddha 2009-10-14 21:46 ` [patch 1/2] x86_64: preserve large page mapping for 1st 2MB kernel txt " Suresh Siddha @ 2009-10-14 21:46 ` Suresh Siddha 2009-10-15 3:24 ` Sam Ravnborg 2009-10-24 1:03 ` [tip:branch?] x86-64: " tip-bot for Suresh Siddha 1 sibling, 2 replies; 7+ messages in thread From: Suresh Siddha @ 2009-10-14 21:46 UTC (permalink / raw) To: hpa, mingo, tglx, arjan; +Cc: linux-kernel, chinang.ma, Suresh Siddha [-- Attachment #1: align_rodata_hpage.patch --] [-- Type: text/plain, Size: 4819 bytes --] CONFIG_DEBUG_RODATA chops the large pages spanning boundaries of kernel text/rodata/data to small 4KB pages as they are mapped with different attributes (text as RO, RODATA as RO and NX etc). On x86_64, preserve the large page mappings for kernel text/rodata/data boundaries when CONFIG_DEBUG_RODATA is enabled. This is done by allowing the RODATA section to be hugepage aligned and having same RWX attributes for the 2MB page boundaries Extra Memory pages padding the sections will be freed during the end of the boot and the kernel identity mappings will have different RWX permissions compared to the kernel text mappings. Kernel identity mappings to these physical pages will be mapped with smaller pages but large page mappings are still retained for kernel text,rodata,data mappings. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> --- arch/x86/include/asm/sections.h | 6 ++++++ arch/x86/kernel/vmlinux.lds.S | 17 +++++++++++++++++ arch/x86/mm/init_64.c | 14 +++++++++++++- arch/x86/mm/pageattr.c | 14 ++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) Index: tree/arch/x86/include/asm/sections.h =================================================================== --- tree.orig/arch/x86/include/asm/sections.h +++ tree/arch/x86/include/asm/sections.h @@ -2,7 +2,13 @@ #define _ASM_X86_SECTIONS_H #include <asm-generic/sections.h> +#include <asm/uaccess.h> extern char __brk_base[], __brk_limit[]; +extern struct exception_table_entry __stop___ex_table[]; + +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) +extern char __end_rodata_hpage_align[]; +#endif #endif /* _ASM_X86_SECTIONS_H */ Index: tree/arch/x86/kernel/vmlinux.lds.S =================================================================== --- tree.orig/arch/x86/kernel/vmlinux.lds.S +++ tree/arch/x86/kernel/vmlinux.lds.S @@ -41,6 +41,21 @@ ENTRY(phys_startup_64) jiffies_64 = jiffies; #endif +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) + +#define X64_ALIGN_DEBUG_RODATA_BEGIN . = ALIGN(HPAGE_SIZE); + +#define X64_ALIGN_DEBUG_RODATA_END \ + . = ALIGN(HPAGE_SIZE); \ + __end_rodata_hpage_align = .; + +#else + +#define X64_ALIGN_DEBUG_RODATA_BEGIN +#define X64_ALIGN_DEBUG_RODATA_END + +#endif + PHDRS { text PT_LOAD FLAGS(5); /* R_E */ data PT_LOAD FLAGS(7); /* RWE */ @@ -90,7 +105,9 @@ SECTIONS EXCEPTION_TABLE(16) :text = 0x9090 + X64_ALIGN_DEBUG_RODATA_BEGIN RO_DATA(PAGE_SIZE) + X64_ALIGN_DEBUG_RODATA_END /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { Index: tree/arch/x86/mm/init_64.c =================================================================== --- tree.orig/arch/x86/mm/init_64.c +++ tree/arch/x86/mm/init_64.c @@ -726,9 +726,13 @@ void set_kernel_text_ro(void) void mark_rodata_ro(void) { - unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata); + unsigned long start = PFN_ALIGN(_text); unsigned long rodata_start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; + unsigned long end = (unsigned long) &__end_rodata_hpage_align; + unsigned long text_end = PAGE_ALIGN((unsigned long) &__stop___ex_table); + unsigned long rodata_end = PAGE_ALIGN((unsigned long) &__end_rodata); + unsigned long data_start = (unsigned long) &_sdata; printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", (end - start) >> 10); @@ -751,6 +755,14 @@ void mark_rodata_ro(void) printk(KERN_INFO "Testing CPA: again\n"); set_memory_ro(start, (end-start) >> PAGE_SHIFT); #endif + + free_init_pages("unused kernel memory", + (unsigned long) page_address(virt_to_page(text_end)), + (unsigned long) + page_address(virt_to_page(rodata_start))); + free_init_pages("unused kernel memory", + (unsigned long) page_address(virt_to_page(rodata_end)), + (unsigned long) page_address(virt_to_page(data_start))); } #endif Index: tree/arch/x86/mm/pageattr.c =================================================================== --- tree.orig/arch/x86/mm/pageattr.c +++ tree/arch/x86/mm/pageattr.c @@ -279,6 +279,20 @@ static inline pgprot_t static_protection __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_RW; +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) + /* + * Kernel text mappings for the large page aligned .rodata section + * will be read-only. For the kernel identity mappings covering + * the holes caused by this alignment can be anything. + * + * This will preserve the large page mappings for kernel text/data + * at no extra cost. + */ + if (within(address, (unsigned long)_text, + (unsigned long)__end_rodata_hpage_align)) + pgprot_val(forbidden) |= _PAGE_RW; +#endif + prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); return prot; ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 2/2] x86_64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA 2009-10-14 21:46 ` [patch 2/2] x86_64: align RODATA kernel section to 2MB " Suresh Siddha @ 2009-10-15 3:24 ` Sam Ravnborg 2009-10-15 20:23 ` Suresh Siddha 2009-10-24 1:03 ` [tip:branch?] x86-64: " tip-bot for Suresh Siddha 1 sibling, 1 reply; 7+ messages in thread From: Sam Ravnborg @ 2009-10-15 3:24 UTC (permalink / raw) To: Suresh Siddha; +Cc: hpa, mingo, tglx, arjan, linux-kernel, chinang.ma > Index: tree/arch/x86/include/asm/sections.h > =================================================================== > --- tree.orig/arch/x86/include/asm/sections.h > +++ tree/arch/x86/include/asm/sections.h > @@ -2,7 +2,13 @@ > #define _ASM_X86_SECTIONS_H > > #include <asm-generic/sections.h> > +#include <asm/uaccess.h> > > extern char __brk_base[], __brk_limit[]; > +extern struct exception_table_entry __stop___ex_table[]; > + > +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) > +extern char __end_rodata_hpage_align[]; > +#endif > > #endif /* _ASM_X86_SECTIONS_H */ > Index: tree/arch/x86/kernel/vmlinux.lds.S > =================================================================== > --- tree.orig/arch/x86/kernel/vmlinux.lds.S > +++ tree/arch/x86/kernel/vmlinux.lds.S > @@ -41,6 +41,21 @@ ENTRY(phys_startup_64) > jiffies_64 = jiffies; > #endif > > +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) > + > +#define X64_ALIGN_DEBUG_RODATA_BEGIN . = ALIGN(HPAGE_SIZE); > + > +#define X64_ALIGN_DEBUG_RODATA_END \ > + . = ALIGN(HPAGE_SIZE); \ > + __end_rodata_hpage_align = .; This symbol is only defined if CONFIG_DEBUG_RODATA is defined, but (see below). > + > +#else > + > +#define X64_ALIGN_DEBUG_RODATA_BEGIN > +#define X64_ALIGN_DEBUG_RODATA_END > + > +#endif A coment describing the purpose of this would be nice. > + > PHDRS { > text PT_LOAD FLAGS(5); /* R_E */ > data PT_LOAD FLAGS(7); /* RWE */ > @@ -90,7 +105,9 @@ SECTIONS > > EXCEPTION_TABLE(16) :text = 0x9090 > > + X64_ALIGN_DEBUG_RODATA_BEGIN > RO_DATA(PAGE_SIZE) > + X64_ALIGN_DEBUG_RODATA_END > > /* Data */ > .data : AT(ADDR(.data) - LOAD_OFFSET) { > Index: tree/arch/x86/mm/init_64.c > =================================================================== > --- tree.orig/arch/x86/mm/init_64.c > +++ tree/arch/x86/mm/init_64.c > @@ -726,9 +726,13 @@ void set_kernel_text_ro(void) > > void mark_rodata_ro(void) > { > - unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata); > + unsigned long start = PFN_ALIGN(_text); > unsigned long rodata_start = > ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; > + unsigned long end = (unsigned long) &__end_rodata_hpage_align; Here the symbol seems to be referenced unconditionally. Sam ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 2/2] x86_64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA 2009-10-15 3:24 ` Sam Ravnborg @ 2009-10-15 20:23 ` Suresh Siddha 0 siblings, 0 replies; 7+ messages in thread From: Suresh Siddha @ 2009-10-15 20:23 UTC (permalink / raw) To: Sam Ravnborg; +Cc: hpa, mingo, tglx, arjan, linux-kernel, Ma, Chinang On Wed, 2009-10-14 at 20:24 -0700, Sam Ravnborg wrote: > > +#else > > + > > +#define X64_ALIGN_DEBUG_RODATA_BEGIN > > +#define X64_ALIGN_DEBUG_RODATA_END > > + > > +#endif > > A coment describing the purpose of > this would be nice. I will update this in the next version of the patch. > > @@ -726,9 +726,13 @@ void set_kernel_text_ro(void) > > > > void mark_rodata_ro(void) > > { > > - unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata); > > + unsigned long start = PFN_ALIGN(_text); > > unsigned long rodata_start = > > ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; > > + unsigned long end = (unsigned long) &__end_rodata_hpage_align; > Here the symbol seems to be referenced unconditionally. This function is defined only for CONFIG_DEBUG_RODATA. thanks, suresh ^ permalink raw reply [flat|nested] 7+ messages in thread
* [tip:branch?] x86-64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA 2009-10-14 21:46 ` [patch 2/2] x86_64: align RODATA kernel section to 2MB " Suresh Siddha 2009-10-15 3:24 ` Sam Ravnborg @ 2009-10-24 1:03 ` tip-bot for Suresh Siddha 1 sibling, 0 replies; 7+ messages in thread From: tip-bot for Suresh Siddha @ 2009-10-24 1:03 UTC (permalink / raw) To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, suresh.b.siddha, tglx Commit-ID: 74e081797bd9d2a7d8005fe519e719df343a2ba8 Gitweb: http://git.kernel.org/tip/74e081797bd9d2a7d8005fe519e719df343a2ba8 Author: Suresh Siddha <suresh.b.siddha@intel.com> AuthorDate: Wed, 14 Oct 2009 14:46:56 -0700 Committer: H. Peter Anvin <hpa@zytor.com> CommitDate: Tue, 20 Oct 2009 14:46:00 +0900 x86-64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA CONFIG_DEBUG_RODATA chops the large pages spanning boundaries of kernel text/rodata/data to small 4KB pages as they are mapped with different attributes (text as RO, RODATA as RO and NX etc). On x86_64, preserve the large page mappings for kernel text/rodata/data boundaries when CONFIG_DEBUG_RODATA is enabled. This is done by allowing the RODATA section to be hugepage aligned and having same RWX attributes for the 2MB page boundaries Extra Memory pages padding the sections will be freed during the end of the boot and the kernel identity mappings will have different RWX permissions compared to the kernel text mappings. Kernel identity mappings to these physical pages will be mapped with smaller pages but large page mappings are still retained for kernel text,rodata,data mappings. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <20091014220254.190119924@sbs-t61.sc.intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/include/asm/sections.h | 6 ++++++ arch/x86/kernel/vmlinux.lds.S | 17 +++++++++++++++++ arch/x86/mm/init_64.c | 14 +++++++++++++- arch/x86/mm/pageattr.c | 14 ++++++++++++++ 4 files changed, 50 insertions(+), 1 deletions(-) diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h index 1b7ee5d..0a52424 100644 --- a/arch/x86/include/asm/sections.h +++ b/arch/x86/include/asm/sections.h @@ -2,7 +2,13 @@ #define _ASM_X86_SECTIONS_H #include <asm-generic/sections.h> +#include <asm/uaccess.h> extern char __brk_base[], __brk_limit[]; +extern struct exception_table_entry __stop___ex_table[]; + +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) +extern char __end_rodata_hpage_align[]; +#endif #endif /* _ASM_X86_SECTIONS_H */ diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 92929fb..1476379 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -41,6 +41,21 @@ ENTRY(phys_startup_64) jiffies_64 = jiffies; #endif +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) + +#define X64_ALIGN_DEBUG_RODATA_BEGIN . = ALIGN(HPAGE_SIZE); + +#define X64_ALIGN_DEBUG_RODATA_END \ + . = ALIGN(HPAGE_SIZE); \ + __end_rodata_hpage_align = .; + +#else + +#define X64_ALIGN_DEBUG_RODATA_BEGIN +#define X64_ALIGN_DEBUG_RODATA_END + +#endif + PHDRS { text PT_LOAD FLAGS(5); /* R_E */ data PT_LOAD FLAGS(7); /* RWE */ @@ -90,7 +105,9 @@ SECTIONS EXCEPTION_TABLE(16) :text = 0x9090 + X64_ALIGN_DEBUG_RODATA_BEGIN RO_DATA(PAGE_SIZE) + X64_ALIGN_DEBUG_RODATA_END /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 7dafd41..0ed09fa 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -727,9 +727,13 @@ void set_kernel_text_ro(void) void mark_rodata_ro(void) { - unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata); + unsigned long start = PFN_ALIGN(_text); unsigned long rodata_start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; + unsigned long end = (unsigned long) &__end_rodata_hpage_align; + unsigned long text_end = PAGE_ALIGN((unsigned long) &__stop___ex_table); + unsigned long rodata_end = PAGE_ALIGN((unsigned long) &__end_rodata); + unsigned long data_start = (unsigned long) &_sdata; printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", (end - start) >> 10); @@ -752,6 +756,14 @@ void mark_rodata_ro(void) printk(KERN_INFO "Testing CPA: again\n"); set_memory_ro(start, (end-start) >> PAGE_SHIFT); #endif + + free_init_pages("unused kernel memory", + (unsigned long) page_address(virt_to_page(text_end)), + (unsigned long) + page_address(virt_to_page(rodata_start))); + free_init_pages("unused kernel memory", + (unsigned long) page_address(virt_to_page(rodata_end)), + (unsigned long) page_address(virt_to_page(data_start))); } #endif diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index dd38bfb..b494fc4 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -279,6 +279,20 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_RW; +#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) + /* + * Kernel text mappings for the large page aligned .rodata section + * will be read-only. For the kernel identity mappings covering + * the holes caused by this alignment can be anything. + * + * This will preserve the large page mappings for kernel text/data + * at no extra cost. + */ + if (within(address, (unsigned long)_text, + (unsigned long)__end_rodata_hpage_align)) + pgprot_val(forbidden) |= _PAGE_RW; +#endif + prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); return prot; ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-10-24 1:04 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-10-14 21:46 [patch 0/2] x86_64: preserve large page text mappings with CONFIG_DEBUG_RODATA Suresh Siddha 2009-10-14 21:46 ` [patch 1/2] x86_64: preserve large page mapping for 1st 2MB kernel txt " Suresh Siddha 2009-10-24 1:03 ` [tip:branch?] x86-64: " tip-bot for Suresh Siddha 2009-10-14 21:46 ` [patch 2/2] x86_64: align RODATA kernel section to 2MB " Suresh Siddha 2009-10-15 3:24 ` Sam Ravnborg 2009-10-15 20:23 ` Suresh Siddha 2009-10-24 1:03 ` [tip:branch?] x86-64: " tip-bot for Suresh Siddha
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
Powered by JetHome