The main purpose of this patchset is to dramatically reduce the time
spent in DTLB miss handler. This is achieved by:
1/ Mapping RAM with 8M pages
2/ Mapping IMMR with a fixed 512K page
On a live running system (VoIP gateway for Air Trafic Control), over
a 10 minutes period (with 277s idle), we get 87 millions DTLB misses
and approximatly 35 secondes are spent in DTLB handler.
This represents 5.8% of the overall time and even 10.8% of the
non-idle time.
Among those 87 millions DTLB misses, 15% are on user addresses and
85% are on kernel addresses. And within the kernel addresses, 93%
are on addresses from the linear address space and only 7% are on
addresses from the virtual address space.
Once the full patchset applied, the number of DTLB misses during the
period is reduced to 11.8 millions for a duration of 5.8s, which
represents 2% of the non-idle time.
This patch also includes other miscellaneous improvements:
1/ Handling of CPU6 ERRATA directly in mtspr() C macro to reduce code
specific to PPC8xx
2/ Rewrite of a few non critical ASM functions in C
3/ Removal of some unused items
See related patches for details
Main changes in v3:
* Using fixmap instead of fix address for mapping IMMR
Change in v4:
* Fix of a wrong #if notified by kbuild robot in 07/23
Change in v5:
* Removed use of pmd_val() as L-value
* Adapted to match the new include files layout in Linux 4.5
Change in v6:
* Removed remaining use of pmd_val() as L-value (reported by kbuild test robot)
Change in v7:
* No change (commit error)
Change in v8:
* Don't include x_block_mapped() from compilation in
arch/powerpc/mm/fsl_booke_mmu.c when CONFIG_FSL_BOOKE is not set
(reported by kbuild test robot)
Christophe Leroy (23):
powerpc/8xx: Save r3 all the time in DTLB miss handler
powerpc/8xx: Map linear kernel RAM with 8M pages
powerpc: Update documentation for noltlbs kernel parameter
powerpc/8xx: move setup_initial_memory_limit() into 8xx_mmu.c
powerpc32: Fix pte_offset_kernel() to return NULL for bad pages
powerpc32: refactor x_mapped_by_bats() and x_mapped_by_tlbcam()
together
powerpc/8xx: Fix vaddr for IMMR early remap
powerpc/8xx: Map IMMR area with 512k page at a fixed address
powerpc/8xx: CONFIG_PIN_TLB unneeded for CONFIG_PPC_EARLY_DEBUG_CPM
powerpc/8xx: map more RAM at startup when needed
powerpc32: Remove useless/wrong MMU:setio progress message
powerpc32: remove ioremap_base
powerpc/8xx: Add missing SPRN defines into reg_8xx.h
powerpc/8xx: Handle CPU6 ERRATA directly in mtspr() macro
powerpc/8xx: remove special handling of CPU6 errata in set_dec()
powerpc/8xx: rewrite set_context() in C
powerpc/8xx: rewrite flush_instruction_cache() in C
powerpc: add inline functions for cache related instructions
powerpc32: Remove clear_pages() and define clear_page() inline
powerpc32: move xxxxx_dcache_range() functions inline
powerpc: Simplify test in __dma_sync()
powerpc32: small optimisation in flush_icache_range()
powerpc32: Remove one insn in mulhdu
Documentation/kernel-parameters.txt | 2 +-
arch/powerpc/Kconfig.debug | 1 -
arch/powerpc/include/asm/cache.h | 19 +++
arch/powerpc/include/asm/cacheflush.h | 52 ++++++-
arch/powerpc/include/asm/fixmap.h | 14 ++
arch/powerpc/include/asm/mmu-8xx.h | 4 +-
arch/powerpc/include/asm/nohash/32/pgtable.h | 5 +-
arch/powerpc/include/asm/page_32.h | 17 ++-
arch/powerpc/include/asm/reg.h | 2 +
arch/powerpc/include/asm/reg_8xx.h | 93 ++++++++++++
arch/powerpc/include/asm/time.h | 6 +-
arch/powerpc/kernel/asm-offsets.c | 8 ++
arch/powerpc/kernel/head_8xx.S | 207 +++++++++++++++++----------
arch/powerpc/kernel/misc_32.S | 107 ++------------
arch/powerpc/kernel/ppc_ksyms.c | 2 +
arch/powerpc/kernel/ppc_ksyms_32.c | 1 -
arch/powerpc/mm/8xx_mmu.c | 190 ++++++++++++++++++++++++
arch/powerpc/mm/Makefile | 1 +
arch/powerpc/mm/dma-noncoherent.c | 2 +-
arch/powerpc/mm/fsl_booke_mmu.c | 6 +-
arch/powerpc/mm/init_32.c | 23 ---
arch/powerpc/mm/mmu_decl.h | 34 +++--
arch/powerpc/mm/pgtable_32.c | 47 +-----
arch/powerpc/mm/ppc_mmu_32.c | 4 +-
arch/powerpc/platforms/embedded6xx/mpc10x.h | 10 --
arch/powerpc/sysdev/cpm_common.c | 15 +-
26 files changed, 585 insertions(+), 287 deletions(-)
create mode 100644 arch/powerpc/mm/8xx_mmu.c
--
2.1.0
Now the noltlbs kernel parameter is also applicable to PPC8xx
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
Documentation/kernel-parameters.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -2592,7 +2592,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. nolapic_timer [X86-32,APIC] Do not use the local APIC timer. noltlbs [PPC] Do not use large page/tlb entries for kernel- lowmem mapping on PPC40x.+ lowmem mapping on PPC40x and PPC8xx nomca [IA-64] Disable machine check abort handling
The fixmap related functions try to map kernel pages that are
already mapped through Large TLBs. pte_offset_kernel() has to
return NULL for LTLBs, otherwise the caller will try to access
level 2 table which doesn't exist
Signed-off-by: Christophe Leroy <redacted>
---
v3: new
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/nohash/32/pgtable.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
x_mapped_by_bats() and x_mapped_by_tlbcam() serve the same kind of
purpose, and are never defined at the same time.
So rename them x_block_mapped() and define them in the relevant
places
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: Functions are mutually exclusive so renamed iaw Scott comment instead of grouping into a single function
v4: no change
v5: no change
v6: no change
v8: Don't include x_block_mapped() from compilation in
arch/powerpc/mm/fsl_booke_mmu.c when CONFIG_FSL_BOOKE is not set
(problem reported by kbuild robot with a configuration having
CONFIG_FSL_BOOK3E and not CONFIG_FSL_BOOKE)
arch/powerpc/mm/fsl_booke_mmu.c | 6 ++++--
arch/powerpc/mm/mmu_decl.h | 10 ++++++++++
arch/powerpc/mm/pgtable_32.c | 44 ++++++-----------------------------------
arch/powerpc/mm/ppc_mmu_32.c | 4 ++--
4 files changed, 22 insertions(+), 42 deletions(-)
Once the linear memory space has been mapped with 8Mb pages, as
seen in the related commit, we get 11 millions DTLB missed during
the reference 600s period. 77% of the misses are on user addresses
and 23% are on kernel addresses (1 fourth for linear address space
and 3 fourth for virtual address space)
Traditionaly, each driver manages one computer board which has its
own components with its own memory maps.
But on embedded chips like the MPC8xx, the SOC has all registers
located in the same IO area.
When looking at ioremaps done during startup, we see that
many drivers are re-mapping small parts of the IMMR for their own use
and all those small pieces gets their own 4k page, amplifying the
number of TLB misses: in our system we get 0xff000000 mapped 31 times
and 0xff003000 mapped 9 times.
Even if each part of IMMR was mapped only once with 4k pages, it would
still be several small mappings towards linear area.
With the patch, on the same principle as what was done for the RAM,
the IMMR gets mapped by a 512k page.
In 4k pages mode, we reserve a 4Mb area for mapping IMMR. The TLB
miss handler checks that we are within the first 512k and bail out
with page not marked valid if we are outside
In 16k pages mode, it is not realistic to reserve a 64Mb area, so
we do a standard mapping of the 512k area using 32 pages of 16k.
The CPM will be mapped via the first two pages, and the SEC engine
will be mapped via the 16th and 17th pages. As the pages are marked
guarded, there will be no speculative accesses.
With this patch applied, the number of DTLB misses during the 10 min
period is reduced to 11.8 millions for a duration of 5.8s, which
represents 2% of the non-idle time hence yet another 10% reduction.
Signed-off-by: Christophe Leroy <redacted>
---
v2:
- using bt instead of blt/bgt
- reorganised in order to have only one taken branch for both 512k
and 8M instead of a first branch for both 8M and 512k then a second
branch for 512k
v3:
- using fixmap
- using the new x_block_mapped() functions
v4: no change
v5: no change
v6: removed use of pmd_val() as L-value
v8: no change
arch/powerpc/include/asm/fixmap.h | 9 ++++++-
arch/powerpc/kernel/head_8xx.S | 36 +++++++++++++++++++++++++-
arch/powerpc/mm/8xx_mmu.c | 53 +++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/mmu_decl.h | 3 ++-
4 files changed, 98 insertions(+), 3 deletions(-)
@@ -52,12 +52,19 @@ enum fixed_addresses {FIX_KMAP_END=FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,#endif#ifdef CONFIG_PPC_8xx-/* For IMMR we need an aligned 512K area */FIX_IMMR_START,+#ifdef CONFIG_PPC_4K_PAGES+/* For IMMR we need an aligned 4M area (full PGD entry) */+FIX_IMMR_TOP=(FIX_IMMR_START-1+((4*1024*1024)/PAGE_SIZE))&+~(((4*1024*1024)/PAGE_SIZE)-1),+FIX_IMMR_BASE=FIX_IMMR_TOP-1+((4*1024*1024)/PAGE_SIZE),+#else+/* For IMMR we need an aligned 512K area */FIX_IMMR_TOP=(FIX_IMMR_START-1+((512*1024)/PAGE_SIZE))&~(((512*1024)/PAGE_SIZE)-1),FIX_IMMR_BASE=FIX_IMMR_TOP-1+((512*1024)/PAGE_SIZE),#endif+#endif/* FIX_PCIE_MCFG, */__end_of_fixed_addresses};
@@ -254,6 +254,37 @@ DataAccess:.=0x400InstructionAccess:+/*+*BottompartofDTLBMisshandlerfor512kpages+*notenoughspaceintheprimarylocation+*/+#ifdef CONFIG_PPC_4K_PAGES+/*+*512kpagesareonlyusedformappingIMMRareain4Kpagesmode.+*Onlymapthefirst512kpageofthe4MareacoveredbythePGDentry.+*Thisshouldnothappen,butifwearecalledforanotherpageofthat+*area,don't mark it valid+*+*In16kpagesmode,IMMRisdirectlymappedwith16kpages+*/+DTLBMiss512k:+rlwinm.r10,r10,0,0x00380000+bne-1f+orir11,r11,MD_SVALID+1:mtcrr3+MTSPR_CPU6(SPRN_MD_TWC,r11,r3)+rlwinmr10,r11,0,0xffc00000+orir10,r10,0xf0|MD_SPS16K|_PAGE_SHARED|_PAGE_DIRTY|\+_PAGE_PRESENT|_PAGE_NO_CACHE+MTSPR_CPU6(SPRN_MD_RPN,r10,r3)/*UpdateTLBentry*/++lir11,RPN_PATTERN+mfsprr3,SPRN_SPRG_SCRATCH2+mtsprSPRN_DAR,r11/*TagDAR*/+EXCEPTION_EPILOG_0+rfi+#endif+/*Externalinterrupt*/EXCEPTION(0x500,HardwareInterrupt,do_IRQ,EXC_XFER_LITE)
From: Scott Wood <oss@buserror.net> Date: 2016-03-11 23:15:52
On Tue, Feb 09, 2016 at 05:08:02PM +0100, Christophe Leroy wrote:
Once the linear memory space has been mapped with 8Mb pages, as
seen in the related commit, we get 11 millions DTLB missed during
the reference 600s period. 77% of the misses are on user addresses
and 23% are on kernel addresses (1 fourth for linear address space
and 3 fourth for virtual address space)
Traditionaly, each driver manages one computer board which has its
own components with its own memory maps.
But on embedded chips like the MPC8xx, the SOC has all registers
located in the same IO area.
When looking at ioremaps done during startup, we see that
many drivers are re-mapping small parts of the IMMR for their own use
and all those small pieces gets their own 4k page, amplifying the
number of TLB misses: in our system we get 0xff000000 mapped 31 times
and 0xff003000 mapped 9 times.
Even if each part of IMMR was mapped only once with 4k pages, it would
still be several small mappings towards linear area.
With the patch, on the same principle as what was done for the RAM,
the IMMR gets mapped by a 512k page.
"the patch" -- this one, that below says it maps IMMR with other sizes?
In 4k pages mode, we reserve a 4Mb area for mapping IMMR. The TLB
miss handler checks that we are within the first 512k and bail out
with page not marked valid if we are outside
In 16k pages mode, it is not realistic to reserve a 64Mb area, so
we do a standard mapping of the 512k area using 32 pages of 16k.
The CPM will be mapped via the first two pages, and the SEC engine
will be mapped via the 16th and 17th pages. As the pages are marked
guarded, there will be no speculative accesses.
If IMMR is 512k, why do you need to reserve 4M/64M for it?
-Scott
On Tue, Feb 09, 2016 at 05:08:02PM +0100, Christophe Leroy wrote:
quoted
Once the linear memory space has been mapped with 8Mb pages, as
seen in the related commit, we get 11 millions DTLB missed during
the reference 600s period. 77% of the misses are on user addresses
and 23% are on kernel addresses (1 fourth for linear address space
and 3 fourth for virtual address space)
Traditionaly, each driver manages one computer board which has its
own components with its own memory maps.
But on embedded chips like the MPC8xx, the SOC has all registers
located in the same IO area.
When looking at ioremaps done during startup, we see that
many drivers are re-mapping small parts of the IMMR for their own use
and all those small pieces gets their own 4k page, amplifying the
number of TLB misses: in our system we get 0xff000000 mapped 31 times
and 0xff003000 mapped 9 times.
Even if each part of IMMR was mapped only once with 4k pages, it would
still be several small mappings towards linear area.
With the patch, on the same principle as what was done for the RAM,
the IMMR gets mapped by a 512k page.
"the patch" -- this one, that below says it maps IMMR with other sizes?
No, the physical mapping is done using one 512k page. And this is done
in 4k pages mode only, for the reason explained below.
quoted
In 4k pages mode, we reserve a 4Mb area for mapping IMMR. The TLB
miss handler checks that we are within the first 512k and bail out
with page not marked valid if we are outside
In 16k pages mode, it is not realistic to reserve a 64Mb area, so
we do a standard mapping of the 512k area using 32 pages of 16k.
The CPM will be mapped via the first two pages, and the SEC engine
will be mapped via the 16th and 17th pages. As the pages are marked
guarded, there will be no speculative accesses.
If IMMR is 512k, why do you need to reserve 4M/64M for it?
The principle here, as for the 8M pages used for the mapping of RAM, is
to have the PTE in the PGD (level 1 table) and no level 2 table
associated with that PGD entry.
Each PGD entry maps a 4M area in 4k pages mode and a 64M area in 16k
pages mode. That's the reason.
We can afford "loosing" 4M virtual memory but I felt like "loosing" 64M
of virtual memory is not worth it taking into account that 2 16k pages
are enough to map the CPM internal memory and 2 other 16k pages are
enough to map the SEC engine internal memory.
Christophe
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus
On recent kernels, with some debug options like for instance
CONFIG_LOCKDEP, the BSS requires more than 8M memory, allthough
the kernel code fits in the first 8M.
Today, it is necessary to activate CONFIG_PIN_TLB to get more than 8M
at startup, allthough pinning TLB is not necessary for that.
This patch adds more pages (up to 24Mb) to the initial mapping if
possible/needed in order to have the necessary mappings regardless of
CONFIG_PIN_TLB.
We could have mapped 16M or 24M inconditionnally but since some
platforms only have 8M memory, we need something a bit more elaborated
Therefore, if the bootloader is compliant with ePAPR standard, we use
r7 to know how much memory was mapped by the bootloader.
Otherwise, we try to determine the required memory size by looking at
the _end symbol and the address of the device tree.
This patch does not modify the behaviour when CONFIG_PIN_TLB is
selected.
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: Automatic detection of available/needed memory instead of allocating 16M for all.
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/kernel/head_8xx.S | 56 +++++++++++++++++++++++++++++++++++++++---
arch/powerpc/mm/8xx_mmu.c | 10 +++-----
2 files changed, 56 insertions(+), 10 deletions(-)
@@ -20,6 +20,7 @@#define IMMR_SIZE (__fix_to_virt(FIX_IMMR_TOP) + PAGE_SIZE - VIRT_IMMR_BASE)externint__map_without_ltlbs;+intinitial_memory_size;/* size of initial memory mapped by head_8xx.S *//**ReturnPAforthisVAifitisinIMMRarea,or0
@@ -143,11 +144,6 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,*/BUG_ON(first_memblock_base!=0);-#ifdef CONFIG_PIN_TLB-/* 8xx can only access 24MB at the moment */-memblock_set_current_limit(min_t(u64,first_memblock_size,0x01800000));-#else-/* 8xx can only access 8MB at the moment */-memblock_set_current_limit(min_t(u64,first_memblock_size,0x00800000));-#endif+memblock_set_current_limit(min_t(u64,first_memblock_size,+initial_memory_size));}
Commit 771168494719 ("[POWERPC] Remove unused machine call outs")
removed the call to setup_io_mappings(), so remove the associated
progress line message
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/mm/init_32.c | 4 ----
1 file changed, 4 deletions(-)
Add missing SPRN defines into reg_8xx.h
Some of them are defined in mmu-8xx.h, so we include mmu-8xx.h in
reg_8xx.h, for that we remove references to PAGE_SHIFT in mmu-8xx.h
to have it self sufficient, as includers of reg_8xx.h don't all
include asm/page.h
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: We just add missing ones, don't move anymore the ones from mmu-8xx.h
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/mmu-8xx.h | 4 ++--
arch/powerpc/include/asm/reg_8xx.h | 11 +++++++++++
2 files changed, 13 insertions(+), 2 deletions(-)
@@ -4,6 +4,8 @@#ifndef _ASM_POWERPC_REG_8xx_H#define _ASM_POWERPC_REG_8xx_H+#include<asm/mmu-8xx.h>+/* Cache control on the MPC8xx is provided through some additional*specialpurposeregisters.*/
@@ -14,6 +16,15 @@#define SPRN_DC_ADR 569 /* Address needed for some commands */#define SPRN_DC_DAT 570 /* Read-only data register */+/* Misc Debug */+#define SPRN_DPDR 630+#define SPRN_MI_CAM 816+#define SPRN_MI_RAM0 817+#define SPRN_MI_RAM1 818+#define SPRN_MD_CAM 824+#define SPRN_MD_RAM0 825+#define SPRN_MD_RAM1 826+/* Commands. Only the first few are available to the instruction cache.*/#define IDC_ENABLE 0x02000000 /* Cache enable */
flush/clean/invalidate _dcache_range() functions are all very
similar and are quite short. They are mainly used in __dma_sync()
perf_event locate them in the top 3 consumming functions during
heavy ethernet activity
They are good candidate for inlining, as __dma_sync() does
almost nothing but calling them
Signed-off-by: Christophe Leroy <redacted>
---
v2: new
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/cacheflush.h | 52 ++++++++++++++++++++++++++--
arch/powerpc/kernel/misc_32.S | 65 -----------------------------------
arch/powerpc/kernel/ppc_ksyms.c | 2 ++
3 files changed, 51 insertions(+), 68 deletions(-)
@@ -375,71 +375,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)isyncblr/*-*Writeanymodifieddatacacheblocksouttomemory.-*Doesnotinvalidatethecorrespondingcachelines (especiallyfor-*anycorrespondinginstructioncache).-*-*clean_dcache_range(unsignedlongstart,unsignedlongstop)-*/-_GLOBAL(clean_dcache_range)-lir5,L1_CACHE_BYTES-1-andcr3,r3,r5-subfr4,r3,r4-addr4,r4,r5-srwi.r4,r4,L1_CACHE_SHIFT-beqlr-mtctrr4--1:dcbst0,r3-addir3,r3,L1_CACHE_BYTES-bdnz1b-sync/*waitfordcbst's to get to ram */-blr--/*-*Writeanymodifieddatacacheblocksouttomemoryandinvalidatethem.-*Doesnotinvalidatethecorrespondinginstructioncacheblocks.-*-*flush_dcache_range(unsignedlongstart,unsignedlongstop)-*/-_GLOBAL(flush_dcache_range)-lir5,L1_CACHE_BYTES-1-andcr3,r3,r5-subfr4,r3,r4-addr4,r4,r5-srwi.r4,r4,L1_CACHE_SHIFT-beqlr-mtctrr4--1:dcbf0,r3-addir3,r3,L1_CACHE_BYTES-bdnz1b-sync/*waitfordcbst's to get to ram */-blr--/*-*Likeabove,butinvalidatetheD-cache.Thisisusedbythe8xx-*toinvalidatethecachesothePPCcoredoesn't get stale data-*fromtheCPM (nocachesnoopinghere:-).-*-*invalidate_dcache_range(unsignedlongstart,unsignedlongstop)-*/-_GLOBAL(invalidate_dcache_range)-lir5,L1_CACHE_BYTES-1-andcr3,r3,r5-subfr4,r3,r4-addr4,r4,r5-srwi.r4,r4,L1_CACHE_SHIFT-beqlr-mtctrr4--1:dcbi0,r3-addir3,r3,L1_CACHE_BYTES-bdnz1b-sync/*waitfordcbi's to get to ram */-blr--/**FlushaparticularpagefromthedatacachetoRAM.*Note:thisisnecessarybecausetheinstructioncachedoes*not**snoopfromthedatacache.
clear_pages() is never used expect by clear_page, and PPC32 is the
only architecture (still) having this function. Neither PPC64 nor
any other architecture has it.
This patch removes clear_pages() and moves clear_page() function
inline (same as PPC64) as it only is a few isns
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/page_32.h | 17 ++++++++++++++---
arch/powerpc/kernel/misc_32.S | 16 ----------------
arch/powerpc/kernel/ppc_ksyms_32.c | 1 -
3 files changed, 14 insertions(+), 20 deletions(-)
@@ -1,6 +1,8 @@#ifndef _ASM_POWERPC_PAGE_32_H#define _ASM_POWERPC_PAGE_32_H+#include<asm/cache.h>+#if defined(CONFIG_PHYSICAL_ALIGN) && (CONFIG_PHYSICAL_START != 0)#if (CONFIG_PHYSICAL_START % CONFIG_PHYSICAL_ALIGN) != 0#error "CONFIG_PHYSICAL_START must be a multiple of CONFIG_PHYSICAL_ALIGN"
@@ -36,9 +38,18 @@ typedef unsigned long long pte_basic_t;typedefunsignedlongpte_basic_t;#endif-structpage;-externvoidclear_pages(void*page,intorder);-staticinlinevoidclear_page(void*page){clear_pages(page,0);}+/*+*Clearpageusingthedcbzinstruction,whichdoesn'tcauseany+*memorytraffic(excepttowriteoutanycachelineswhichget+*displaced).Thisonlyworksoncacheablememory.+*/+staticinlinevoidclear_page(void*addr)+{+unsignedinti;++for(i=0;i<PAGE_SIZE/L1_CACHE_BYTES;i++,addr+=L1_CACHE_BYTES)+dcbz(addr);+}externvoidcopy_page(void*to,void*from);#include<asm-generic/getorder.h>
Inlining of _dcache_range() functions has shown that the compiler
does the same thing a bit better with one insn less
Signed-off-by: Christophe Leroy <redacted>
---
v2: new
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/kernel/misc_32.S | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
Remove one instruction in mulhdu
Signed-off-by: Christophe Leroy <redacted>
---
v2: new
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/kernel/misc_32.S | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
This simplification helps the compiler. We now have only one test
instead of two, so it reduces the number of branches.
Signed-off-by: Christophe Leroy <redacted>
---
v2: new
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/mm/dma-noncoherent.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
This patch adds inline functions to use dcbz, dcbi, dcbf, dcbst
from C functions
Signed-off-by: Christophe Leroy <redacted>
---
v2: new
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/cache.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
On PPC8xx, flushing instruction cache is performed by writing
in register SPRN_IC_CST. This registers suffers CPU6 ERRATA.
The patch rewrites the fonction in C so that CPU6 ERRATA will
be handled transparently
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/kernel/misc_32.S | 10 ++++------
arch/powerpc/mm/8xx_mmu.c | 7 +++++++
2 files changed, 11 insertions(+), 6 deletions(-)
There is no real need to have set_context() in assembly.
Now that we have mtspr() handling CPU6 ERRATA directly, we
can rewrite set_context() in C language for easier maintenance.
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/kernel/head_8xx.S | 44 ------------------------------------------
arch/powerpc/mm/8xx_mmu.c | 34 ++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 44 deletions(-)
@@ -147,3 +147,37 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,memblock_set_current_limit(min_t(u64,first_memblock_size,initial_memory_size));}++/*+*SetuptouseagivenMMUcontext.+*idiscontextnumber,pgdisPGDpointer.+*+*Weplacethephysicaladdressofthenewtaskpagedirectoryloaded+*intotheMMUbaseregister,andsettheASIDcompareregisterwith+*thenew"context."+*/+voidset_context(unsignedlongid,pgd_t*pgd)+{+s16offset=(s16)(__pa(swapper_pg_dir));++#ifdef CONFIG_BDI_SWITCH+pgd_t**ptr=*(pgd_t***)(KERNELBASE+0xf0);++/* Context switch the PTE pointer for the Abatron BDI2000.+*ThePGDIRispassedassecondargument.+*/+*(ptr+1)=pgd;+#endif++/* Register M_TW will contain base address of level 1 table minus the+*lowerpartofthekernelPGDIRbaseaddress,sothatallaccessesto+*level1tablearedonerelativetolowerpartofkernelPGDIRbase+*address.+*/+mtspr(SPRN_M_TW,__pa(pgd)-offset);++/* Update context */+mtspr(SPRN_M_CASID,id);+/* sync */+mb();+}
CPU6 ERRATA is now handled directly in mtspr(), so we can use the
standard set_dec() fonction in all cases.
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/time.h | 6 +-----
arch/powerpc/kernel/head_8xx.S | 18 ------------------
2 files changed, 1 insertion(+), 23 deletions(-)
@@ -1011,24 +1011,6 @@ _GLOBAL(set_context)SYNCblr-#ifdef CONFIG_8xx_CPU6-/*It's here because it is unique to the 8xx.-*Itisimportantwegetcalledwithinterruptsdisabled.Iusedto-*dothat,butitappearsthatallcodethatcallsthisalreadyhad-*interruptdisabled.-*/-.globlset_dec_cpu6-set_dec_cpu6:-lisr7,cpu6_errata_word@h-orir7,r7,cpu6_errata_word@l-lir4,0x2c00-stwr4,8(r7)-lwzr4,8(r7)-mtspr22,r3/*UpdateDecrementer*/-SYNC-blr-#endif-/**Weputafewthingsherethathavetobepage-aligned.*Thisstuffgoesatthebeginningofthedatasegment,
MPC8xx has an ERRATA on the use of mtspr() for some registers
This patch includes the ERRATA handling directly into mtspr() macro
so that mtspr() users don't need to bother about that errata
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/reg.h | 2 +
arch/powerpc/include/asm/reg_8xx.h | 82 ++++++++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+)
ioremap_base is not initialised and is nowhere used so remove it
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: fix comment as well
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/nohash/32/pgtable.h | 2 +-
arch/powerpc/mm/mmu_decl.h | 1 -
arch/powerpc/mm/pgtable_32.c | 3 +--
arch/powerpc/platforms/embedded6xx/mpc10x.h | 10 ----------
4 files changed, 2 insertions(+), 14 deletions(-)
IMMR is now mapped by page tables so it is not
anymore necessary to PIN TLBs
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/Kconfig.debug | 1 -
1 file changed, 1 deletion(-)
@@ -220,7 +220,6 @@ config PPC_EARLY_DEBUG_40xconfigPPC_EARLY_DEBUG_CPMbool"Early serial debugging for Freescale CPM-based serial ports"depends onSERIAL_CPM-selectPIN_TLBifPPC_8xxhelpSelectthistoenableearlydebuggingforFreescalechipsusingaCPM-basedserialport.Thisassumesthatthebootwrapper
Memory: 124428K/131072K available (3748K kernel code, 188K rwdata,
648K rodata, 508K init, 290K bss, 6644K reserved)
Kernel virtual memory layout:
* 0xfffdf000..0xfffff000 : fixmap
* 0xfde00000..0xfe000000 : consistent mem
* 0xfddf6000..0xfde00000 : early ioremap
* 0xc9000000..0xfddf6000 : vmalloc & ioremap
SLUB: HWalign=16, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Today, IMMR is mapped 1:1 at startup
Mapping IMMR 1:1 is just wrong because it may overlap with another
area. On most mpc8xx boards it is OK as IMMR is set to 0xff000000
but for instance on EP88xC board, IMMR is at 0xfa200000 which
overlaps with VM ioremap area
This patch fixes the virtual address for remapping IMMR with the fixmap
regardless of the value of IMMR.
The size of IMMR area is 256kbytes (CPM at offset 0, security engine
at offset 128k) so a 512k page is enough
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: Using fixmap instead of fixed address
v4: Fix a wrong #if notified by kbuild robot
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/fixmap.h | 7 +++++++
arch/powerpc/kernel/asm-offsets.c | 8 ++++++++
arch/powerpc/kernel/head_8xx.S | 11 ++++++-----
arch/powerpc/mm/mmu_decl.h | 7 +++++++
arch/powerpc/sysdev/cpm_common.c | 15 ++++++++++++---
5 files changed, 40 insertions(+), 8 deletions(-)
@@ -51,6 +51,13 @@ enum fixed_addresses {FIX_KMAP_BEGIN,/* reserved pte's for temporary kernel mappings */FIX_KMAP_END=FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,#endif+#ifdef CONFIG_PPC_8xx+/* For IMMR we need an aligned 512K area */+FIX_IMMR_START,+FIX_IMMR_TOP=(FIX_IMMR_START-1+((512*1024)/PAGE_SIZE))&+~(((512*1024)/PAGE_SIZE)-1),+FIX_IMMR_BASE=FIX_IMMR_TOP-1+((512*1024)/PAGE_SIZE),+#endif/* FIX_PCIE_MCFG, */__end_of_fixed_addresses};
From: Scott Wood <oss@buserror.net> Date: 2016-03-11 22:52:14
On Tue, Feb 09, 2016 at 05:08:00PM +0100, Christophe Leroy wrote:
quoted hunk
Memory: 124428K/131072K available (3748K kernel code, 188K rwdata,
648K rodata, 508K init, 290K bss, 6644K reserved)
Kernel virtual memory layout:
* 0xfffdf000..0xfffff000 : fixmap
* 0xfde00000..0xfe000000 : consistent mem
* 0xfddf6000..0xfde00000 : early ioremap
* 0xc9000000..0xfddf6000 : vmalloc & ioremap
SLUB: HWalign=16, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Today, IMMR is mapped 1:1 at startup
Mapping IMMR 1:1 is just wrong because it may overlap with another
area. On most mpc8xx boards it is OK as IMMR is set to 0xff000000
but for instance on EP88xC board, IMMR is at 0xfa200000 which
overlaps with VM ioremap area
This patch fixes the virtual address for remapping IMMR with the fixmap
regardless of the value of IMMR.
The size of IMMR area is 256kbytes (CPM at offset 0, security engine
at offset 128k) so a 512k page is enough
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: Using fixmap instead of fixed address
v4: Fix a wrong #if notified by kbuild robot
v5: no change
v6: no change
v8: no change
arch/powerpc/include/asm/fixmap.h | 7 +++++++
arch/powerpc/kernel/asm-offsets.c | 8 ++++++++
arch/powerpc/kernel/head_8xx.S | 11 ++++++-----
arch/powerpc/mm/mmu_decl.h | 7 +++++++
arch/powerpc/sysdev/cpm_common.c | 15 ++++++++++++---
5 files changed, 40 insertions(+), 8 deletions(-)
@@ -51,6 +51,13 @@ enum fixed_addresses {FIX_KMAP_BEGIN,/* reserved pte's for temporary kernel mappings */FIX_KMAP_END=FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,#endif+#ifdef CONFIG_PPC_8xx+/* For IMMR we need an aligned 512K area */+FIX_IMMR_START,+FIX_IMMR_TOP=(FIX_IMMR_START-1+((512*1024)/PAGE_SIZE))&+~(((512*1024)/PAGE_SIZE)-1),+FIX_IMMR_BASE=FIX_IMMR_TOP-1+((512*1024)/PAGE_SIZE),+#endif/* FIX_PCIE_MCFG, */__end_of_fixed_addresses};
This doesn't look correct -- shouldn't the last thing in the 8xx ifdef be the
last byte of the IMMR, so that any subsequent fixmap entry would start at
the correct location?
Also, can standard alignment macros be used?
-Scott
Now we have a 8xx specific .c file for that so put it in there
as other powerpc variants do
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/mm/8xx_mmu.c | 17 +++++++++++++++++
arch/powerpc/mm/init_32.c | 19 -------------------
2 files changed, 17 insertions(+), 19 deletions(-)
@@ -81,3 +81,20 @@ unsigned long __init mmu_mapin_ram(unsigned long top)returnmapped;}++voidsetup_initial_memory_limit(phys_addr_tfirst_memblock_base,+phys_addr_tfirst_memblock_size)+{+/* We don't currently support the first MEMBLOCK not mapping 0+*physicalonthoseprocessors+*/+BUG_ON(first_memblock_base!=0);++#ifdef CONFIG_PIN_TLB+/* 8xx can only access 24MB at the moment */+memblock_set_current_limit(min_t(u64,first_memblock_size,0x01800000));+#else+/* 8xx can only access 8MB at the moment */+memblock_set_current_limit(min_t(u64,first_memblock_size,0x00800000));+#endif+}
@@ -193,22 +193,3 @@ void __init MMU_init(void)/* Shortly after that, the entire linear mapping will be available */memblock_set_current_limit(lowmem_end_addr);}--#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */-voidsetup_initial_memory_limit(phys_addr_tfirst_memblock_base,-phys_addr_tfirst_memblock_size)-{-/* We don't currently support the first MEMBLOCK not mapping 0-*physicalonthoseprocessors-*/-BUG_ON(first_memblock_base!=0);--#ifdef CONFIG_PIN_TLB-/* 8xx can only access 24MB at the moment */-memblock_set_current_limit(min_t(u64,first_memblock_size,0x01800000));-#else-/* 8xx can only access 8MB at the moment */-memblock_set_current_limit(min_t(u64,first_memblock_size,0x00800000));-#endif-}-#endif /* CONFIG_8xx */
On a live running system (VoIP gateway for Air Trafic Control), over
a 10 minutes period (with 277s idle), we get 87 millions DTLB misses
and approximatly 35 secondes are spent in DTLB handler.
This represents 5.8% of the overall time and even 10.8% of the
non-idle time.
Among those 87 millions DTLB misses, 15% are on user addresses and
85% are on kernel addresses. And within the kernel addresses, 93%
are on addresses from the linear address space and only 7% are on
addresses from the virtual address space.
MPC8xx has no BATs but it has 8Mb page size. This patch implements
mapping of kernel RAM using 8Mb pages, on the same model as what is
done on the 40x.
In 4k pages mode, each PGD entry maps a 4Mb area: we map every two
entries to the same 8Mb physical page. In each second entry, we add
4Mb to the page physical address to ease life of the FixupDAR
routine. This is just ignored by HW.
In 16k pages mode, each PGD entry maps a 64Mb area: each PGD entry
will point to the first page of the area. The DTLB handler adds
the 3 bits from EPN to map the correct page.
With this patch applied, we now get only 13 millions TLB misses
during the 10 minutes period. The idle time has increased to 313s
and the overall time spent in DTLB miss handler is 6.3s, which
represents 1% of the overall time and 2.2% of non-idle time.
Signed-off-by: Christophe Leroy <redacted>
---
v2: using bt instead of bgt and named the label explicitly
v3: no change
v4: no change
v5: removed use of pmd_val() as L-value
v6: no change
v8: no change
arch/powerpc/kernel/head_8xx.S | 35 +++++++++++++++++-
arch/powerpc/mm/8xx_mmu.c | 83 ++++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/Makefile | 1 +
arch/powerpc/mm/mmu_decl.h | 15 ++------
4 files changed, 120 insertions(+), 14 deletions(-)
create mode 100644 arch/powerpc/mm/8xx_mmu.c
@@ -0,0 +1,83 @@+/*+*ThisfilecontainstheroutinesforinitializingtheMMU+*onthe8xxseriesofchips.+*--christophe+*+*Derivedfromarch/powerpc/mm/40x_mmu.c:+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicense+*aspublishedbytheFreeSoftwareFoundation;eitherversion+*2oftheLicense,or(atyouroption)anylaterversion.+*+*/++#include<linux/memblock.h>++#include"mmu_decl.h"++externint__map_without_ltlbs;+/*+*MMU_init_hwdoesthechip-specificinitializationoftheMMUhardware.+*/+void__initMMU_init_hw(void)+{+/* Nothing to do for the time being but keep it similar to other PPC */+}++#define LARGE_PAGE_SIZE_4M (1<<22)+#define LARGE_PAGE_SIZE_8M (1<<23)+#define LARGE_PAGE_SIZE_64M (1<<26)++unsignedlong__initmmu_mapin_ram(unsignedlongtop)+{+unsignedlongv,s,mapped;+phys_addr_tp;++v=KERNELBASE;+p=0;+s=top;++if(__map_without_ltlbs)+return0;++#ifdef CONFIG_PPC_4K_PAGES+while(s>=LARGE_PAGE_SIZE_8M){+pmd_t*pmdp;+unsignedlongval=p|MD_PS8MEG;++pmdp=pmd_offset(pud_offset(pgd_offset_k(v),v),v);+*pmdp++=__pmd(val);+*pmdp++=__pmd(val+LARGE_PAGE_SIZE_4M);++v+=LARGE_PAGE_SIZE_8M;+p+=LARGE_PAGE_SIZE_8M;+s-=LARGE_PAGE_SIZE_8M;+}+#else /* CONFIG_PPC_16K_PAGES */+while(s>=LARGE_PAGE_SIZE_64M){+pmd_t*pmdp;+unsignedlongval=p|MD_PS8MEG;++pmdp=pmd_offset(pud_offset(pgd_offset_k(v),v),v);+*pmdp++=__pmd(val);++v+=LARGE_PAGE_SIZE_64M;+p+=LARGE_PAGE_SIZE_64M;+s-=LARGE_PAGE_SIZE_64M;+}+#endif++mapped=top-s;++/* If the size of RAM is not an exact power of two, we may not+*havecoveredRAMinitsentiretywith8MiB+*pages.Consequently,restrictthetopendofRAMcurrently+*allocablesothatcallstotheMEMBLOCKtoallocatePTEsfor"tail"+*coveragewithnormal-sizedpages(orotherreasons)donot+*attempttoallocateoutsidetheallowedrange.+*/+memblock_set_current_limit(mapped);++returnmapped;+}
@@ -132,22 +132,17 @@ extern void wii_memory_fixups(void);/* ...and now those things that may be slightly different between processor*architectures.--Dan*/-#if defined(CONFIG_8xx)-#define MMU_init_hw() do { } while(0)-#define mmu_mapin_ram(top) (0UL)--#elif defined(CONFIG_4xx)+#ifdef CONFIG_PPC32externvoidMMU_init_hw(void);externunsignedlongmmu_mapin_ram(unsignedlongtop);+#endif-#elif defined(CONFIG_PPC_FSL_BOOK3E)+#ifdef CONFIG_PPC_FSL_BOOK3Eexternunsignedlongmap_mem_in_cams(unsignedlongram,intmax_cam_idx,booldryrun);externunsignedlongcalc_cam_sz(unsignedlongram,unsignedlongvirt,phys_addr_tphys);#ifdef CONFIG_PPC32-externvoidMMU_init_hw(void);-externunsignedlongmmu_mapin_ram(unsignedlongtop);externvoidadjust_total_lowmem(void);externintswitch_to_as1(void);externvoidrestore_to_as0(intesel,intoffset,void*dt_ptr,intbootcpu);
We are spending between 40 and 160 cycles with a mean of 65 cycles in
the DTLB handling routine (measured with mftbl) so make it more
simple althought it adds one instruction.
With this modification, we get three registers available at all time,
which will help with following patch.
Signed-off-by: Christophe Leroy <redacted>
---
v2: no change
v3: no change
v4: no change
v5: no change
v6: no change
v8: no change
arch/powerpc/kernel/head_8xx.S | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)