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
Christophe Leroy (20):
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
powerpc/8xx: Fix vaddr for IMMR early remap
powerpc32: iounmap() cannot vunmap() area mapped by TLBCAMs either
powerpc32: refactor x_mapped_by_bats() and x_mapped_by_tlbcam()
together
powerpc/8xx: Map IMMR area with 512k page at a fixed address
powerpc/8xx: show IMMR area in startup memory layout
powerpc/8xx: CONFIG_PIN_TLB unneeded for CONFIG_PPC_EARLY_DEBUG_CPM
powerpc/8xx: map 16M RAM at startup
powerpc/8xx: move 8xx SPRN defines into reg_8xx.h and add some missing
ones
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
powerpc32: Remove clear_pages()
powerpc32: Remove useless/wrong MMU:setio progress message
powerpc/8xx: also use r3 in the ITLB miss in all situations
powerpc32: remove ioremap_base
Documentation/kernel-parameters.txt | 2 +-
arch/powerpc/Kconfig.debug | 2 -
arch/powerpc/include/asm/mmu-8xx.h | 26 ++--
arch/powerpc/include/asm/page_32.h | 3 +-
arch/powerpc/include/asm/pgtable-ppc32.h | 5 +
arch/powerpc/include/asm/reg.h | 2 +
arch/powerpc/include/asm/reg_8xx.h | 106 ++++++++++++++++
arch/powerpc/include/asm/time.h | 6 +-
arch/powerpc/kernel/head_8xx.S | 151 +++++++++-------------
arch/powerpc/kernel/misc_32.S | 17 +--
arch/powerpc/kernel/ppc_ksyms_32.c | 1 -
arch/powerpc/mm/8xx_mmu.c | 190 ++++++++++++++++++++++++++++
arch/powerpc/mm/Makefile | 1 +
arch/powerpc/mm/init_32.c | 23 ----
arch/powerpc/mm/mem.c | 4 +
arch/powerpc/mm/mmu_decl.h | 16 +--
arch/powerpc/mm/pgtable_32.c | 54 +++++++-
arch/powerpc/platforms/embedded6xx/mpc10x.h | 8 --
18 files changed, 444 insertions(+), 173 deletions(-)
create mode 100644 arch/powerpc/mm/8xx_mmu.c
--
2.1.0
We are spending between 40 and 160 cycles with a mean of 65 cycles in
the TLB handling routines (measured with mftbl) so make it more
simple althought it adds one instruction.
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/kernel/head_8xx.S | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
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>
---
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 */
x_mapped_by_bats() and x_mapped_by_tlbcam() serve the same kind of
purpose, so lets group them into a single function.
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/mm/pgtable_32.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
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 a second 8M page to the initial mapping in order to
have 16M mapped regardless of CONFIG_PIN_TLB, like several other
32 bits PPC (40x, 601, ...)
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/kernel/head_8xx.S | 2 ++
arch/powerpc/mm/8xx_mmu.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
@@ -144,7 +144,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,/* 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));+/* 8xx can only access 16MB at the moment */+memblock_set_current_limit(min_t(u64,first_memblock_size,0x01000000));#endif}
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>
---
arch/powerpc/include/asm/reg.h | 2 +
arch/powerpc/include/asm/reg_8xx.h | 82 ++++++++++++++++++++++++++++++++++++++
2 files changed, 84 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>
---
arch/powerpc/kernel/misc_32.S | 10 ++++------
arch/powerpc/mm/8xx_mmu.c | 7 +++++++
2 files changed, 11 insertions(+), 6 deletions(-)
ioremap_base is not initialised and is nowhere used so remove it
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/mm/mmu_decl.h | 1 -
arch/powerpc/mm/pgtable_32.c | 1 -
arch/powerpc/platforms/embedded6xx/mpc10x.h | 8 --------
3 files changed, 10 deletions(-)
We are spending between 40 and 160 cycles with a mean of 65 cycles
in the TLB handling routines (measured with mftbl) so make it more
simple althought it adds one instruction
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/kernel/head_8xx.S | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
clear_pages() is never used, and PPC32 is the only architecture
(still) having this function. Neither PPC64 nor any other
architecture has it.
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/include/asm/page_32.h | 3 +--
arch/powerpc/kernel/misc_32.S | 7 +++----
arch/powerpc/kernel/ppc_ksyms_32.c | 1 -
3 files changed, 4 insertions(+), 7 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>
---
arch/powerpc/kernel/head_8xx.S | 44 ------------------------------------------
arch/powerpc/mm/8xx_mmu.c | 33 +++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 44 deletions(-)
@@ -148,3 +148,36 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,memblock_set_current_limit(min_t(u64,first_memblock_size,0x01000000));#endif}++/*+*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);+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>
---
arch/powerpc/include/asm/time.h | 6 +-----
arch/powerpc/kernel/head_8xx.S | 18 ------------------
2 files changed, 1 insertion(+), 23 deletions(-)
@@ -944,24 +944,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,
@@ -11,7 +11,7 @@*iswritten,andthecontentsofseveralregistersareusedto*createtheentry.*/-#define SPRN_MI_CTR 784 /* Instruction TLB control register */+/* SPRN_MI_CTR *//* Instruction TLB control register */#define MI_GPM 0x80000000 /* Set domain manager mode */#define MI_PPM 0x40000000 /* Set subpage protection */#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
@@ -23,7 +23,7 @@/* These are the Ks and Kp from the PowerPC books. For proper operation,*Ks=0,Kp=1.*/-#define SPRN_MI_AP 786+/* SPRN_MI_AP */#define MI_Ks 0x80000000 /* Should not be set */#define MI_Kp 0x40000000 /* Should always be set */
@@ -44,7 +44,7 @@*aboutthelastinstructionTLBmiss.WhenMI_RPNiswritten,bitsin*thisregisterareusedtocreatetheTLBentry.*/-#define SPRN_MI_EPN 787+/* SPRN_MI_EPN */#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */#define MI_EVALID 0x00000200 /* Entry is valid */#define MI_ASIDMASK 0x0000000f /* ASID match value */
@@ -68,7 +68,7 @@*causesaTLBentrytobecreatedfortheinstructionTLB,using*additionalinformationfromtheMI_EPN,andMI_TWCregisters.*/-#define SPRN_MI_RPN 790+/* SPRN_MI_RPN */#define MI_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) *//* Define an RPN value for mapping kernel memory to large virtual
@@ -78,7 +78,7 @@*/#define MI_BOOTINIT 0x000001fd-#define SPRN_MD_CTR 792 /* Data TLB control register */+/* SPRN_MD_CTR *//* Data TLB control register */#define MD_GPM 0x80000000 /* Set domain manager mode */#define MD_PPM 0x40000000 /* Set subpage protection */#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
@@ -89,14 +89,14 @@#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */#define MD_RESETVAL 0x04000000 /* Value of register at reset */-#define SPRN_M_CASID 793 /* Address space ID (context) to match */+/* SPRN_M_CASID *//* Address space ID (context) to match */#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value *//* These are the Ks and Kp from the PowerPC books. For proper operation,*Ks=0,Kp=1.*/-#define SPRN_MD_AP 794+/* SPRN_MD_AP */#define MD_Ks 0x80000000 /* Should not be set */#define MD_Kp 0x40000000 /* Should always be set */
@@ -117,7 +117,7 @@*aboutthelastinstructionTLBmiss.WhenMD_RPNiswritten,bitsin*thisregisterareusedtocreatetheTLBentry.*/-#define SPRN_MD_EPN 795+/* SPRN_MD_EPN */#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */#define MD_EVALID 0x00000200 /* Entry is valid */#define MD_ASIDMASK 0x0000000f /* ASID match value */
@@ -127,7 +127,7 @@*Duringasoftwaretablewalk,readingthisregisterprovidestheaddress*oftheentryassociatedwithMD_EPN.*/-#define SPRN_M_TWB 796+/* SPRN_M_TWB */#define M_L1TB 0xfffff000 /* Level 1 table base address */#define M_L1INDX 0x00000ffc /* Level 1 index, when read *//* Reset value is undefined */
@@ -137,7 +137,7 @@*whentheMD_RPNiswritten.Itisalsoprovidesthehardwareassist*forfindingthePTEaddressduringsoftwaretablewalk.*/-#define SPRN_MD_TWC 797+/* SPRN_MD_TWC */#define MD_L2TB 0xfffff000 /* Level 2 table base address */#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */#define MD_APG 0x000001e0 /* Access protection group (0) */
@@ -155,13 +155,13 @@*causesaTLBentrytobecreatedforthedataTLB,using*additionalinformationfromtheMD_EPN,andMD_TWCregisters.*/-#define SPRN_MD_RPN 798+/* SPRN_MD_RPN */#define MD_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) *//* This is a temporary storage register that could be used to save*aprocessorworkingregisterduringatablewalk.*/-#define SPRN_M_TW 799+/* SPRN_M_TW */#ifndef __ASSEMBLY__typedefstruct{
@@ -4,6 +4,21 @@#ifndef _ASM_POWERPC_REG_8xx_H#define _ASM_POWERPC_REG_8xx_H+/* MMU registers */+#define SPRN_MI_CTR 784 /* Instruction TLB control register */+#define SPRN_MI_AP 786+#define SPRN_MI_EPN 787+#define SPRN_MI_TWC 789+#define SPRN_MI_RPN 790+#define SPRN_MD_CTR 792 /* Data TLB control register */+#define SPRN_M_CASID 793 /* Address space ID (context) to match */+#define SPRN_MD_AP 794+#define SPRN_MD_EPN 795+#define SPRN_M_TWB 796+#define SPRN_MD_TWC 797+#define SPRN_MD_RPN 798+#define SPRN_M_TW 799+/* Cache control on the MPC8xx is provided through some additional*specialpurposeregisters.*/
@@ -14,6 +29,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 */
IMMR is now mapped at 0xff000000 by page tables so it is not
anymore necessary to PIN TLBs
Signed-off-by: Christophe Leroy <redacted>
---
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
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 missed 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.
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 16:
the CPM will be mapped via the first two pages, and the SEC engine
will be mapped via the 16th and 17th pages
With this patch applies, 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>
---
arch/powerpc/include/asm/pgtable-ppc32.h | 5 +++
arch/powerpc/kernel/head_8xx.S | 57 ++++++++++++++++++++++----------
arch/powerpc/mm/8xx_mmu.c | 50 ++++++++++++++++++++++++++++
arch/powerpc/mm/pgtable_32.c | 20 +++++++++++
4 files changed, 114 insertions(+), 18 deletions(-)
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
Mapping IMMR 1:1 is just wrong because it may overlap with another
area. On most mpc8xx boards it is OK because 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 to 0xff000000,
regardless of the value of IMMR.
The size of IMMR area is 256kbytes (CPM at offset 0, security engine
at offset 128) so 512kbytes is enough and allows to handle the EP88xC
case (which is not 8Mbytes but only 2Mbytes aligned) the same way.
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig.debug | 1 -
arch/powerpc/kernel/head_8xx.S | 10 +++++-----
2 files changed, 5 insertions(+), 6 deletions(-)
@@ -2474,7 +2474,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
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
gets 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>
---
arch/powerpc/kernel/head_8xx.S | 30 ++++++++++++++-
arch/powerpc/mm/8xx_mmu.c | 83 ++++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/Makefile | 1 +
arch/powerpc/mm/mmu_decl.h | 15 ++------
4 files changed, 115 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);+pmd_val(*pmdp++)=val;+pmd_val(*pmdp++)=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);+pmd_val(*pmdp++)=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,21 +132,16 @@ 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);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);