Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1402146 > unrolled thread
| Started by | Christophe Leroy <christophe.leroy@c-s.fr> |
|---|---|
| First post | 2016-05-17 09:10 +0200 |
| Last post | 2016-05-17 09:10 +0200 |
| Articles | 4 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH v3 0/7] powerpc/8xx: Optimisation of TLB handling for IMMR and RAM Christophe Leroy <christophe.leroy@c-s.fr> - 2016-05-17 09:10 +0200
[PATCH v3 7/7] powerpc/8xx: add CONFIG_PIN_TLB_IMMR Christophe Leroy <christophe.leroy@c-s.fr> - 2016-05-17 09:10 +0200
[PATCH v3 2/7] powerpc/8xx: Map IMMR area with 512k page at a fixed address Christophe Leroy <christophe.leroy@c-s.fr> - 2016-05-17 09:10 +0200
[PATCH v3 5/7] powerpc/8xx: Don't use page table for linear memory space Christophe Leroy <christophe.leroy@c-s.fr> - 2016-05-17 09:10 +0200
| From | Christophe Leroy <christophe.leroy@c-s.fr> |
|---|---|
| Date | 2016-05-17 09:10 +0200 |
| Subject | [PATCH v3 0/7] powerpc/8xx: Optimisation of TLB handling for IMMR and RAM |
| Message-ID | <rzHiG-1ph-15@gated-at.bofh.it> |
The purpose of this set of patches is to continue on TLB handling optimisation on the 8xx with the handling of IMMR area as a single 512k area instead of multiple 4k pages. This set includes a rework of linear RAM mapping in order to not use page table but direct linear mapping. The result is equivalent to the use of BATs on other PPCs and it avoids reading the page table. This set also includes a rework of the handling of PIN_TLB config option. This option used to be linked to the quantity of RAM available. It is now independant, users having only 8M memory can also use PIN_TLB. Christophe Leroy (7): 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: unpin all TLBs before flushing powerpc/8xx: Don't use page table for linear memory space powerpc/8xx: Rework CONFIG_PIN_TLB handling powerpc/8xx: add CONFIG_PIN_TLB_IMMR arch/powerpc/Kconfig | 5 ++ arch/powerpc/Kconfig.debug | 1 - arch/powerpc/include/asm/fixmap.h | 7 ++ arch/powerpc/include/asm/mmu-8xx.h | 3 + arch/powerpc/kernel/asm-offsets.c | 8 ++ arch/powerpc/kernel/head_8xx.S | 159 +++++++++++++++++++------------------ arch/powerpc/mm/8xx_mmu.c | 131 ++++++++++++++++++++---------- arch/powerpc/mm/mmu_decl.h | 3 +- arch/powerpc/sysdev/cpm_common.c | 22 +++-- 9 files changed, 212 insertions(+), 127 deletions(-) -- v2: Fixed a test in the 6/7 v3: Fixed issue with 82xx 2.1.0
[toc] | [next] | [standalone]
| From | Christophe Leroy <christophe.leroy@c-s.fr> |
|---|---|
| Date | 2016-05-17 09:10 +0200 |
| Subject | [PATCH v3 7/7] powerpc/8xx: add CONFIG_PIN_TLB_IMMR |
| Message-ID | <rzHiG-1ph-29@gated-at.bofh.it> |
| In reply to | #1402146 |
CONFIG_PIN_TLB maps IMMR area and the first 24 Mbytes of memory.
In some circunstances it might be more interesting to not map
IMMR but map 32 Mbytes of memory instead.
Therefore we add config option CONFIG_PIN_TLB_IMMR to select if
IMMR shall be pinned or not, hence whether we pin 24 or 32 Mbytes of RAM
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
v2: No change
v3: No change
arch/powerpc/Kconfig | 5 +++++
arch/powerpc/kernel/head_8xx.S | 10 ++++++----
arch/powerpc/mm/8xx_mmu.c | 12 ++++++++----
3 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ffca388..5b3a1ee 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -1055,6 +1055,11 @@ config CONSISTENT_SIZE
config PIN_TLB
bool "Pinned Kernel TLBs (860 ONLY)"
depends on ADVANCED_OPTIONS && 8xx
+
+config PIN_TLB_IMMR
+ bool "Pinned TLB for IMMR"
+ depends on PIN_TLB
+ default y
endmenu
if PPC64
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 00cc9df..43ddaae 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -414,11 +414,11 @@ DataStoreTLBMiss:
*/
mfspr r11, SPRN_MD_EPN
rlwinm r11, r11, 16, 0xfff8
-#ifndef CONFIG_PIN_TLB
+#ifndef CONFIG_PIN_TLB_IMMR
cmpli cr0, r11, VIRT_IMMR_BASE@h
#endif
cmpli cr7, r11, PAGE_OFFSET@h
-#ifndef CONFIG_PIN_TLB
+#ifndef CONFIG_PIN_TLB_IMMR
_ENTRY(DTLBMiss_jmp)
beq- DTLBMissIMMR
#endif
@@ -819,7 +819,6 @@ initial_mmu:
#ifdef CONFIG_PIN_TLB
oris r10, r10, MD_RSV4I@h
- ori r10, r10, 0x1c00
mtspr SPRN_MD_CTR, r10 /* Set data TLB control */
#endif
@@ -843,7 +842,10 @@ initial_mmu:
/* Map a 512k page for the IMMR to get the processor
* internal registers (among other things).
*/
-#ifdef CONFIG_PIN_TLB
+#ifdef CONFIG_PIN_TLB_IMMR
+ ori r10, r10, 0x1c00
+ mtspr SPRN_MD_CTR, r10
+
mfspr r9, 638 /* Get current IMMR */
andis. r9, r9, 0xfff8 /* Get 512 kbytes boundary */
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index 0f0a83e..6c5025e 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -61,11 +61,15 @@ void __init MMU_init_hw(void)
#ifdef CONFIG_PIN_TLB
unsigned long ctr = mfspr(SPRN_MD_CTR) & 0xfe000000;
unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY;
- int i;
+#ifdef CONFIG_PIN_TLB_IMMR
+ int i = 29;
+#else
+ int i = 28;
+#endif
unsigned long addr = 0;
unsigned long mem = total_lowmem;
- for (i = 29; i < 32 && mem >= LARGE_PAGE_SIZE_8M; i++) {
+ for (; i < 32 && mem >= LARGE_PAGE_SIZE_8M; i++) {
mtspr(SPRN_MD_CTR, ctr | (i << 8));
mtspr(SPRN_MD_EPN, (unsigned long)__va(addr) | MD_EVALID);
mtspr(SPRN_MD_TWC, MD_PS8MEG | MD_SVALID);
@@ -88,7 +92,7 @@ static void mmu_mapin_immr(void)
}
/* Address of instructions to patch */
-#ifndef CONFIG_PIN_TLB
+#ifndef CONFIG_PIN_TLB_IMMR
extern unsigned int DTLBMiss_jmp;
#endif
extern unsigned int DTLBMiss_cmp, FixupDAR_cmp;
@@ -109,7 +113,7 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
if (__map_without_ltlbs) {
mapped = 0;
mmu_mapin_immr();
-#ifndef CONFIG_PIN_TLB
+#ifndef CONFIG_PIN_TLB_IMMR
patch_instruction(&DTLBMiss_jmp, PPC_INST_NOP);
#endif
} else {
--
2.1.0
[toc] | [prev] | [next] | [standalone]
| From | Christophe Leroy <christophe.leroy@c-s.fr> |
|---|---|
| Date | 2016-05-17 09:10 +0200 |
| Subject | [PATCH v3 2/7] powerpc/8xx: Map IMMR area with 512k page at a fixed address |
| Message-ID | <rzHiG-1ph-21@gated-at.bofh.it> |
| In reply to | #1402146 |
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.
This patch maps the IMMR with a single 512k page.
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 <christophe.leroy@c-s.fr>
---
v2: No change
v3: No change
arch/powerpc/kernel/head_8xx.S | 29 ++++++++++++++++++++++
arch/powerpc/mm/8xx_mmu.c | 56 +++++++++++++++++++++++++++++++++++++++++-
arch/powerpc/mm/mmu_decl.h | 3 ++-
3 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 378a185..44f4edb 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -384,6 +384,27 @@ InstructionTLBMiss:
EXCEPTION_EPILOG_0
rfi
+/*
+ * Bottom part of DataStoreTLBMiss handler for IMMR area
+ * not enough space in the DataStoreTLBMiss area
+ */
+DTLBMissIMMR:
+ mtcr r3
+ /* Set 512k byte guarded page and mark it valid */
+ li r10, MD_PS512K | MD_GUARDED | MD_SVALID
+ MTSPR_CPU6(SPRN_MD_TWC, r10, r3)
+ mfspr r10, SPRN_IMMR /* Get current IMMR */
+ rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */
+ ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY | \
+ _PAGE_PRESENT | _PAGE_NO_CACHE
+ MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
+
+ li r11, RPN_PATTERN
+ mfspr r3, SPRN_SPRG_SCRATCH2
+ mtspr SPRN_DAR, r11 /* Tag DAR */
+ EXCEPTION_EPILOG_0
+ rfi
+
. = 0x1200
DataStoreTLBMiss:
mtspr SPRN_SPRG_SCRATCH2, r3
@@ -397,6 +418,14 @@ DataStoreTLBMiss:
IS_KERNEL(r11, r10)
mfspr r11, SPRN_M_TW /* Get level 1 table */
BRANCH_UNLESS_KERNEL(3f)
+
+ rlwinm r11, r10, 16, 0xfff8
+#ifndef CONFIG_PIN_TLB
+ cmpli cr0, r11, VIRT_IMMR_BASE@h
+_ENTRY(DTLBMiss_jmp)
+ beq- DTLBMissIMMR
+#endif
+
lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
3:
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index 9491005..2207725 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -13,10 +13,43 @@
*/
#include <linux/memblock.h>
+#include <asm/fixmap.h>
+#include <asm/code-patching.h>
#include "mmu_decl.h"
+#define IMMR_SIZE (FIX_IMMR_SIZE << PAGE_SHIFT)
+
extern int __map_without_ltlbs;
+
+/*
+ * Return PA for this VA if it is in IMMR area, or 0
+ */
+phys_addr_t v_block_mapped(unsigned long va)
+{
+ unsigned long p = PHYS_IMMR_BASE;
+
+ if (__map_without_ltlbs)
+ return 0;
+ if (va >= VIRT_IMMR_BASE && va < VIRT_IMMR_BASE + IMMR_SIZE)
+ return p + va - VIRT_IMMR_BASE;
+ return 0;
+}
+
+/*
+ * Return VA for a given PA or 0 if not mapped
+ */
+unsigned long p_block_mapped(phys_addr_t pa)
+{
+ unsigned long p = PHYS_IMMR_BASE;
+
+ if (__map_without_ltlbs)
+ return 0;
+ if (pa >= p && pa < p + IMMR_SIZE)
+ return VIRT_IMMR_BASE + pa - p;
+ return 0;
+}
+
/*
* MMU_init_hw does the chip-specific initialization of the MMU hardware.
*/
@@ -29,6 +62,22 @@ void __init MMU_init_hw(void)
#define LARGE_PAGE_SIZE_8M (1<<23)
#define LARGE_PAGE_SIZE_64M (1<<26)
+static void mmu_mapin_immr(void)
+{
+ unsigned long p = PHYS_IMMR_BASE;
+ unsigned long v = VIRT_IMMR_BASE;
+ unsigned long f = pgprot_val(PAGE_KERNEL_NCG);
+ int offset;
+
+ for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE)
+ map_page(v + offset, p + offset, f);
+}
+
+/* Address of instructions to patch */
+#ifndef CONFIG_PIN_TLB
+extern unsigned int DTLBMiss_jmp;
+#endif
+
unsigned long __init mmu_mapin_ram(unsigned long top)
{
unsigned long v, s, mapped;
@@ -38,8 +87,13 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
p = 0;
s = top;
- if (__map_without_ltlbs)
+ if (__map_without_ltlbs) {
+ mmu_mapin_immr();
+#ifndef CONFIG_PIN_TLB
+ patch_instruction(&DTLBMiss_jmp, PPC_INST_NOP);
+#endif
return 0;
+ }
#ifdef CONFIG_PPC_4K_PAGES
while (s >= LARGE_PAGE_SIZE_8M) {
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 6af6532..f988db6 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -154,9 +154,10 @@ struct tlbcam {
};
#endif
-#if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE) || defined(CONFIG_PPC_8xx)
/* 6xx have BATS */
/* FSL_BOOKE have TLBCAM */
+/* 8xx have LTLB */
phys_addr_t v_block_mapped(unsigned long va);
unsigned long p_block_mapped(phys_addr_t pa);
#else
--
2.1.0
[toc] | [prev] | [next] | [standalone]
| From | Christophe Leroy <christophe.leroy@c-s.fr> |
|---|---|
| Date | 2016-05-17 09:10 +0200 |
| Subject | [PATCH v3 5/7] powerpc/8xx: Don't use page table for linear memory space |
| Message-ID | <rzHiH-1ph-33@gated-at.bofh.it> |
| In reply to | #1402146 |
Instead of using the first level page table to define mappings for
the linear memory space, we can use direct mapping from the TLB
handling routines. This has several advantages:
* No need to read the tables at each TLB miss
* No issue in 16k pages mode where the 1st level table maps 64 Mbytes
The size of the available linear space is known at system startup.
In order to avoid data access at each TLB miss to know the memory
size, the TLB routine is patched at startup with the proper size
This patch provides a 10%-15% improvment of TLB miss handling for
kernel addresses
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
v2: No change
v3: No change
arch/powerpc/kernel/head_8xx.S | 71 ++++++++++++++++++++++--------------------
arch/powerpc/mm/8xx_mmu.c | 56 +++++++++++----------------------
2 files changed, 55 insertions(+), 72 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index d9a1656..3de7d02 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -389,52 +389,52 @@ InstructionTLBMiss:
* not enough space in the DataStoreTLBMiss area
*/
DTLBMissIMMR:
- mtcr r3
+ mtcr r10
/* Set 512k byte guarded page and mark it valid */
li r10, MD_PS512K | MD_GUARDED | MD_SVALID
- MTSPR_CPU6(SPRN_MD_TWC, r10, r3)
+ MTSPR_CPU6(SPRN_MD_TWC, r10, r11)
mfspr r10, SPRN_IMMR /* Get current IMMR */
rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */
ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY | \
_PAGE_PRESENT | _PAGE_NO_CACHE
- MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
+ MTSPR_CPU6(SPRN_MD_RPN, r10, r11) /* Update TLB entry */
li r11, RPN_PATTERN
- mfspr r3, SPRN_SPRG_SCRATCH2
mtspr SPRN_DAR, r11 /* Tag DAR */
EXCEPTION_EPILOG_0
rfi
. = 0x1200
DataStoreTLBMiss:
- mtspr SPRN_SPRG_SCRATCH2, r3
EXCEPTION_PROLOG_0
- mfcr r3
+ mfcr r10
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- mfspr r10, SPRN_MD_EPN
- IS_KERNEL(r11, r10)
- mfspr r11, SPRN_M_TW /* Get level 1 table */
- BRANCH_UNLESS_KERNEL(3f)
-
- rlwinm r11, r10, 16, 0xfff8
+ mfspr r11, SPRN_MD_EPN
+ rlwinm r11, r11, 16, 0xfff8
#ifndef CONFIG_PIN_TLB
cmpli cr0, r11, VIRT_IMMR_BASE@h
+#endif
+ cmpli cr7, r11, PAGE_OFFSET@h
+#ifndef CONFIG_PIN_TLB
_ENTRY(DTLBMiss_jmp)
beq- DTLBMissIMMR
#endif
+ bge- cr7, 4f
- lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
+ mfspr r11, SPRN_M_TW /* Get level 1 table */
3:
+ mtcr r10
+#ifdef CONFIG_8xx_CPU6
+ mtspr SPRN_SPRG_SCRATCH2, r3
+#endif
+ mfspr r10, SPRN_MD_EPN
/* Insert level 1 index */
rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */
- mtcr r11
- bt- 28,DTLBMiss8M /* bit 28 = Large page (8M) */
- mtcr r3
/* We have a pte table, so load fetch the pte from the table.
*/
@@ -482,29 +482,30 @@ _ENTRY(DTLBMiss_jmp)
MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
/* Restore registers */
+#ifdef CONFIG_8xx_CPU6
mfspr r3, SPRN_SPRG_SCRATCH2
+#endif
mtspr SPRN_DAR, r11 /* Tag DAR */
EXCEPTION_EPILOG_0
rfi
-DTLBMiss8M:
- mtcr r3
- ori r11, r11, MD_SVALID
- MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
-#ifdef CONFIG_PPC_16K_PAGES
- /*
- * In 16k pages mode, each PGD entry defines a 64M block.
- * Here we select the 8M page within the block.
- */
- rlwimi r11, r10, 0, 0x03800000
-#endif
- rlwinm r10, r11, 0, 0xff800000
+4:
+_ENTRY(DTLBMiss_cmp)
+ cmpli cr0, r11, PAGE_OFFSET@h
+ lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
+ bge- 3b
+
+ mtcr r10
+ /* Set 8M byte page and mark it valid */
+ li r10, MD_PS8MEG | MD_SVALID
+ MTSPR_CPU6(SPRN_MD_TWC, r10, r11)
+ mfspr r10, SPRN_MD_EPN
+ rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */
ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY | \
_PAGE_PRESENT
- MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
+ MTSPR_CPU6(SPRN_MD_RPN, r10, r11) /* Update TLB entry */
li r11, RPN_PATTERN
- mfspr r3, SPRN_SPRG_SCRATCH2
mtspr SPRN_DAR, r11 /* Tag DAR */
EXCEPTION_EPILOG_0
rfi
@@ -583,12 +584,14 @@ FixupDAR:/* Entry point for dcbx workaround. */
IS_KERNEL(r11, r10)
mfspr r11, SPRN_M_TW /* Get level 1 table */
BRANCH_UNLESS_KERNEL(3f)
+ rlwinm r11, r10, 16, 0xfff8
+_ENTRY(FixupDAR_cmp)
+ cmpli cr7, r11, PAGE_OFFSET@h
+ blt- cr7, 200f
lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
/* Insert level 1 index */
3: rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */
- mtcr r11
- bt 28,200f /* bit 28 = Large page (8M) */
rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */
/* Insert level 2 index */
rlwimi r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
@@ -614,8 +617,8 @@ FixupDAR:/* Entry point for dcbx workaround. */
141: mfspr r10,SPRN_SPRG_SCRATCH2
b DARFixed /* Nope, go back to normal TLB processing */
- /* concat physical page address(r11) and page offset(r10) */
-200: rlwimi r11, r10, 0, 32 - (PAGE_SHIFT << 1), 31
+ /* create physical page address from effective address */
+200: tophys(r11, r10)
b 201b
144: mfspr r10, SPRN_DSISR
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index 2207725..996dfaa 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -58,9 +58,7 @@ void __init MMU_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)
static void mmu_mapin_immr(void)
{
@@ -77,52 +75,33 @@ static void mmu_mapin_immr(void)
#ifndef CONFIG_PIN_TLB
extern unsigned int DTLBMiss_jmp;
#endif
+extern unsigned int DTLBMiss_cmp, FixupDAR_cmp;
-unsigned long __init mmu_mapin_ram(unsigned long top)
+void mmu_patch_cmp_limit(unsigned int *addr, unsigned long mapped)
{
- unsigned long v, s, mapped;
- phys_addr_t p;
+ unsigned int instr = *addr;
- v = KERNELBASE;
- p = 0;
- s = top;
+ instr &= 0xffff0000;
+ instr |= (unsigned long)__va(mapped) >> 16;
+ patch_instruction(addr, instr);
+}
+
+unsigned long __init mmu_mapin_ram(unsigned long top)
+{
+ unsigned long mapped;
if (__map_without_ltlbs) {
+ mapped = 0;
mmu_mapin_immr();
#ifndef CONFIG_PIN_TLB
patch_instruction(&DTLBMiss_jmp, PPC_INST_NOP);
#endif
- return 0;
- }
-
-#ifdef CONFIG_PPC_4K_PAGES
- while (s >= LARGE_PAGE_SIZE_8M) {
- pmd_t *pmdp;
- unsigned long val = 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 {
+ mapped = top & ~(LARGE_PAGE_SIZE_8M - 1);
}
-#else /* CONFIG_PPC_16K_PAGES */
- while (s >= LARGE_PAGE_SIZE_64M) {
- pmd_t *pmdp;
- unsigned long val = 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;
+ mmu_patch_cmp_limit(&DTLBMiss_cmp, mapped);
+ mmu_patch_cmp_limit(&FixupDAR_cmp, mapped);
/* If the size of RAM is not an exact power of two, we may not
* have covered RAM in its entirety with 8 MiB
@@ -131,7 +110,8 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
* coverage with normal-sized pages (or other reasons) do not
* attempt to allocate outside the allowed range.
*/
- memblock_set_current_limit(mapped);
+ if (mapped)
+ memblock_set_current_limit(mapped);
return mapped;
}
--
2.1.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web