sparc64: Flush locked TLB entries used to map initmem
PATCH 1/1 sparc64: Flush locked TLB entries used to map initmem
Check if __init_begin <= (some 4Mb aligned address) < __init_end. If true then flush corresponding 4Mb TLB page.
Move BSS at the middle of the image to make initmem be last range of mapped kernel area.
It's not likely case, but sometimes can be useful.
I use flush_tlb_kernel_range which flushes 8K pages sequentially and only the first flush() has a result. It seems it's not necessary to introduce new function for one-time boot use...
--- arch/sparc/kernel/head_64.S | 4 ++-- arch/sparc/kernel/vmlinux.lds.S | 3 ++- arch/sparc/mm/init_64.c | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-)
arch/sparc/kernel/head_64.S +2 -2
@@ -681,8 +681,8 @@ tlb_fixup_done: /* Clear the bss */ sethi %hi(__bss_start), %o0 or %o0, %lo(__bss_start), %o0 - sethi %hi(_end), %o1 - or %o1, %lo(_end), %o1 + sethi %hi(__bss_stop), %o1 + or %o1, %lo(__bss_stop), %o1 call __bzero sub %o1, %o0, %o1
arch/sparc/kernel/vmlinux.lds.S +2 -1
@@ -64,6 +64,8 @@ SECTIONS /* End of data section */ _edata = .; + BSS_SECTION(0, 0, 0) + .fixup : { __start___fixup = .; *(.fixup)
@@ -141,7 +143,6 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_end = .; - BSS_SECTION(0, 0, 0) _end = . ; STABS_DEBUG
arch/sparc/mm/init_64.c +17 -0
@@ -2079,6 +2079,21 @@ void __init mem_init(void)cheetah_ecache_flush_init (); } +/* Flush locked TLB entry (entries) if it is used to map initmem range +* only, i.e. __init_begin <= (some 4Mb aligned address) < __init_end. +*/ +static void flush_initmem_tlb_entries (void ) +{ +unsigned long begin =round_up ((unsigned long )(__init_begin),1 <<22 ); +unsigned long end =round_up ((unsigned long )(__init_end),1 <<22 ); + +if (begin >= end) +return ; + +pr_info ("TLB: Flushing initmem range [%016lx, %016lx]\n" , begin, end-1 ); +flush_tlb_kernel_range (begin, end); +} +void free_initmem (void ) {unsigned long addr, initend;
@@ -2108,6 +2123,8 @@ void free_initmem(void)if (do_free)free_reserved_page (virt_to_page (page)); } + +flush_initmem_tlb_entries (); }#ifdef CONFIG_BLK_DEV_INITRD
We can't move BSS up. I use non-standard bootloader and it eats this. But SILO doesn't want, he says about multiple loadable segments in ELF file. So the patch is not applicable. Sorry.
05.08.2013, 21:06, "Kirill Tkhai" <[email protected]>:
Quoted 94 lines
Check if
__init_begin<= (some 4Mb aligned address) <__init_end. If true then flush corresponding 4Mb TLB page.Move BSS at the middle of the image to make initmem be last range of mapped kernel area.
It's not likely case, but sometimes can be useful.
I use
flush_tlb_kernel_rangewhich flushes 8K pages sequentially and only the firstflush()has a result. It seems it's not necessary to introduce new function for one-time boot use...Signed-off-by Kirill Tkhai <[email protected]>CC David Miller <[email protected]>---
šarch/sparc/kernel/head_64.S šššš| ššš4 ++-- šarch/sparc/kernel/vmlinux.lds.S | ššš3 ++- šarch/sparc/mm/init_64.c šššššššš| šš17 +++++++++++++++++ š3 files changed, 21 insertions(+), 3 deletions(-)arch/sparc/kernel/head_64.S +0
-0@@ -681,8 +681,8 @@ tlb_fixup_done:ššššššššš/* Clear the bss */
šššššššššsethi %hi(__bss_start), %o0
šššššššššor %o0, %lo(__bss_start), %o0
- sethi %hi(_end), %o1
- or %o1, %lo(_end), %o1
+ sethi %hi(__bss_stop), %o1
+ or %o1, %lo(__bss_stop), %o1
šššššššššcall__bzero
ššššššššššsub %o1, %o0, %o1arch/sparc/kernel/vmlinux.lds.S +0
-0@@ -64,6 +64,8 @@ SECTIONSššššššššš/* End of data section */
ššššššššš_edata = .;+
BSS_SECTION(0, 0, 0)
+
ššššššššš.fixup : {
ššššššššššššššššš__start___fixup = .;
ššššššššššššššššš*(.fixup)arch/sparc/kernel/vmlinux.lds.S +0
-1@@ -141,7 +143,6 @@ SECTIONS ššššššššš. = ALIGN(PAGE_SIZE); ššššššššš__init_end = .; - BSS_SECTION(0, 0, 0) ššššššššš_end = . ;šššššššššSTABS_DEBUG
arch/sparc/mm/init_64.c +17
-0@@ -2079,6 +2079,21 @@ void __init mem_init(void)šššššššššššššššššcheetah_ecache_flush_init (); š} +/* Flush locked TLB entry (entries) if it is used to map initmem range +* only, i.e. __init_begin <= (some 4Mb aligned address) < __init_end. +*/ +static void flush_initmem_tlb_entries (void ) +{ +unsigned long begin =round_up ((unsigned long )(__init_begin),1 <<22 ); +unsigned long end =round_up ((unsigned long )(__init_end),1 <<22 ); + +if (begin >= end) +return ; + +pr_info ("TLB: Flushing initmem range [%016lx, %016lx]\n" , begin, end-1 ); +flush_tlb_kernel_range (begin, end); +} +švoid free_initmem (void ) š{šššššššššunsigned long addr, initend;@@ -2108,6 +2123,8 @@ void free_initmem(void)šššššššššššššššššif (do_free)šššššššššššššššššššššššššfree_reserved_page (virt_to_page(page )); ššššššššš} + +flush_initmem_tlb_entries (); š}š#ifdef
CONFIG_BLK_DEV_INITRD
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to [email protected]
More majordomo info at šhttp://vger.kernel.org/majordomo-info.html