* [PATCH v2 03/19] powerpc/8xx: exception InstructionAccess does not exist on MPC8xx
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
Exception InstructionAccess does not exist on MPC8xx. No need to branch there from somewhere else.
Handling can be done directly in InstructionTLBError Exception.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 17 +++++++----------
1 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 3af6db1..fbe5d10 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -234,15 +234,9 @@ DataAccess:
EXC_XFER_LITE(0x300, handle_page_fault)
/* Instruction access exception.
- * This is "never generated" by the MPC8xx. We jump to it for other
- * translation errors.
+ * This is "never generated" by the MPC8xx.
*/
- . = 0x400
-InstructionAccess:
- EXCEPTION_PROLOG
- mr r4,r12
- mr r5,r9
- EXC_XFER_LITE(0x400, handle_page_fault)
+ EXCEPTION(0x400, InstructionAccess, unknown_exception, EXC_XFER_STD)
/* External interrupt */
EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
@@ -382,7 +376,7 @@ InstructionTLBMiss:
#endif
mfspr r10, SPRN_SPRG_SCRATCH2
EXCEPTION_EPILOG_0
- b InstructionAccess
+ b InstructionTLBError
. = 0x1200
DataStoreTLBMiss:
@@ -477,7 +471,10 @@ DataStoreTLBMiss:
*/
. = 0x1300
InstructionTLBError:
- b InstructionAccess
+ EXCEPTION_PROLOG
+ mr r4,r12
+ mr r5,r9
+ EXC_XFER_LITE(0x1300, handle_page_fault)
/* This is the data TLB error on the MPC8xx. This could be due to
* many reasons, including a dirty update to a pte. We can catch that
--
1.7.1
^ permalink raw reply related
* [PATCH v2 05/19] powerpc/8xx: Fix comment about DIRTY update
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
Since commit 2321f33790a6c5b80322d907a92d5739e7521a13, dirty handling is not
handled here anymore. So we fix the comment.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index e59e39e..171c6ef 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -477,12 +477,8 @@ InstructionTLBError:
EXC_XFER_LITE(0x1300, handle_page_fault)
/* This is the data TLB error on the MPC8xx. This could be due to
- * many reasons, including a dirty update to a pte. We can catch that
- * one here, but anything else is an error. First, we track down the
- * Linux pte. If it is valid, write access is allowed, but the
- * page dirty bit is not set, we will set it and reload the TLB. For
- * any other case, we bail out to a higher level function that can
- * handle it.
+ * many reasons, including a dirty update to a pte. We bail out to
+ * a higher level function that can handle it.
*/
. = 0x1400
DataTLBError:
--
1.7.1
^ permalink raw reply related
* [PATCH v2 04/19] powerpc/8xx: Remove loading of r10 at end of FixupDAR
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
Since commit 2321f33790a6c5b80322d907a92d5739e7521a13, r10 is not used anymore
after FixupDAR. There is therefore no need to set it up with the value of DAR.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index fbe5d10..e59e39e 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -495,7 +495,7 @@ DataTLBError:
mfspr r10, SPRN_DAR
cmpwi cr0, r10, 0x00f0
beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
-DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */
+DARFixed:/* Return from dcbx instruction bug workaround */
#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0)
#endif
@@ -524,7 +524,7 @@ DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR
/* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions
* by decoding the registers used by the dcbx instruction and adding them.
- * DAR is set to the calculated address and r10 also holds the EA on exit.
+ * DAR is set to the calculated address.
*/
/* define if you don't want to use self modifying code */
#define NO_SELF_MODIFYING_CODE
@@ -564,8 +564,7 @@ FixupDAR:/* Entry point for dcbx workaround. */
beq+ 142f
cmpwi cr0, r10, 1964 /* Is icbi? */
beq+ 142f
-141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */
- b DARFixed /* Nope, go back to normal TLB processing */
+141: b DARFixed /* Nope, go back to normal TLB processing */
144: mfspr r10, SPRN_DSISR
rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */
--
1.7.1
^ permalink raw reply related
* [PATCH v2 10/19] powerpc/8xx: Duplicate two insns instead of branching
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
Branching takes two cycles on MPC8xx. Lets duplicate the two instructions
and avoid the branching.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 5037420..4a49ff3 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -638,9 +638,11 @@ modified_instr:
/* special handling for r10,r11 since these are modified already */
153: mfspr r11, SPRN_SPRG_SCRATCH1 /* load r11 from SPRN_SPRG_SCRATCH1 */
- b 155f
+ add r10, r10, r11 /* add it */
+ mfctr r11 /* restore r11 */
+ b 151b
154: mfspr r11, SPRN_SPRG_SCRATCH0 /* load r10 from SPRN_SPRG_SCRATCH0 */
-155: add r10, r10, r11 /* add it */
+ add r10, r10, r11 /* add it */
mfctr r11 /* restore r11 */
b 151b
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH v2 06/19] powerpc/8xx: No need to save r10 and r3 when not calling FixupDAR
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
r10 and r3 are only used inside FixupDAR function. So lets save them inside
that function only.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 27 +++++++++++++--------------
1 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 171c6ef..845abf8 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -482,20 +482,12 @@ InstructionTLBError:
*/
. = 0x1400
DataTLBError:
-#ifdef CONFIG_8xx_CPU6
- stw r3, 8(r0)
-#endif
EXCEPTION_PROLOG_0
- mtspr SPRN_SPRG_SCRATCH2, r10
- mfspr r10, SPRN_DAR
- cmpwi cr0, r10, 0x00f0
+ mfspr r11, SPRN_DAR
+ cmpwi cr0, r11, 0x00f0
beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
DARFixed:/* Return from dcbx instruction bug workaround */
-#ifdef CONFIG_8xx_CPU6
- lwz r3, 8(r0)
-#endif
- mfspr r10,SPRN_SPRG_SCRATCH2
EXCEPTION_EPILOG_0
b DataAccess
@@ -525,6 +517,10 @@ DARFixed:/* Return from dcbx instruction bug workaround */
/* define if you don't want to use self modifying code */
#define NO_SELF_MODIFYING_CODE
FixupDAR:/* Entry point for dcbx workaround. */
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+#endif
+ mtspr SPRN_SPRG_SCRATCH2, r10
/* fetch instruction from memory. */
mfspr r10, SPRN_SRR0
andis. r11, r10, 0x8000 /* Address >= 0x80000000 */
@@ -540,6 +536,9 @@ FixupDAR:/* Entry point for dcbx workaround. */
mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
lwz r11, 0(r11) /* Get the pte */
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0) /* restore r3 from memory */
+#endif
/* concat physical page address(r11) and page offset(r10) */
rlwimi r11, r10, 0, 20, 31
lwz r11,0(r11)
@@ -560,15 +559,13 @@ FixupDAR:/* Entry point for dcbx workaround. */
beq+ 142f
cmpwi cr0, r10, 1964 /* Is icbi? */
beq+ 142f
-141: b DARFixed /* Nope, go back to normal TLB processing */
+141: mfspr r10,SPRN_SPRG_SCRATCH2
+ b DARFixed /* Nope, go back to normal TLB processing */
144: mfspr r10, SPRN_DSISR
rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */
mtspr SPRN_DSISR, r10
142: /* continue, it was a dcbx, dcbi instruction. */
-#ifdef CONFIG_8xx_CPU6
- lwz r3, 8(r0) /* restore r3 from memory */
-#endif
#ifndef NO_SELF_MODIFYING_CODE
andis. r10,r11,0x1f /* test if reg RA is r0 */
li r10,modified_instr@l
@@ -587,6 +584,7 @@ modified_instr:
bne+ 143f
subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */
143: mtdar r10 /* store faulting EA in DAR */
+ mfspr r10,SPRN_SPRG_SCRATCH2
b DARFixed /* Go back to normal TLB handling */
#else
mfctr r10
@@ -640,6 +638,7 @@ modified_instr:
mfdar r11
mtctr r11 /* restore ctr reg from DAR */
mtdar r10 /* save fault EA to DAR */
+ mfspr r10,SPRN_SPRG_SCRATCH2
b DARFixed /* Go back to normal TLB handling */
/* special handling for r10,r11 since these are modified already */
--
1.7.1
^ permalink raw reply related
* [PATCH v2 15/19] powerpc/8xx: Implement 16k pages
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
This patch activates the handling of 16k pages on the MPC8xx.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/mmu-8xx.h | 2 ++
arch/powerpc/kernel/head_8xx.S | 4 ++++
3 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 5f44d3b..dc5f64e 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -518,7 +518,7 @@ config PPC_4K_PAGES
bool "4k page size"
config PPC_16K_PAGES
- bool "16k page size" if 44x
+ bool "16k page size" if 44x || PPC_8xx
config PPC_64K_PAGES
bool "64k page size" if 44x || PPC_STD_MMU_64 || PPC_BOOK3E_64
diff --git a/arch/powerpc/include/asm/mmu-8xx.h b/arch/powerpc/include/asm/mmu-8xx.h
index 3d11d3c..986b9e1 100644
--- a/arch/powerpc/include/asm/mmu-8xx.h
+++ b/arch/powerpc/include/asm/mmu-8xx.h
@@ -56,6 +56,7 @@
* additional information from the MI_EPN, and MI_TWC registers.
*/
#define SPRN_MI_RPN 790
+#define MI_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */
/* Define an RPN value for mapping kernel memory to large virtual
* pages for boot initialization. This has real page number of 0,
@@ -129,6 +130,7 @@
* additional information from the MD_EPN, and MD_TWC registers.
*/
#define SPRN_MD_RPN 798
+#define MD_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */
/* This is a temporary storage register that could be used to save
* a processor working register during a tablewalk.
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 8966262..4dd6be0 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -45,7 +45,11 @@
* Value for the bits that have fixed value in RPN entries.
* Also used for tagging DAR for DTLBerror.
*/
+#ifdef CONFIG_PPC_16K_PAGES
+#define RPN_PATTERN (0x00f0 | MD_SPS16K)
+#else
#define RPN_PATTERN 0x00f0
+#endif
__HEAD
_ENTRY(_stext);
--
1.7.1
^ permalink raw reply related
* [PATCH v2 18/19] powerpc/8xx: _PMD_PRESENT already set in level 1 entries
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
When a PMD entry is valid, _PMD_PRESENT is set. Therefore, forcing that bit
during TLB loading is useless.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 48d3de8..bb7c816 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -340,7 +340,6 @@ InstructionTLBMiss:
/* We have a pte table, so load the MI_TWC with the attributes
* for this "segment."
*/
- ori r11,r11,1 /* Set valid bit */
MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */
mfspr r11, SPRN_SRR0 /* Get effective address of fault */
/* Extract level 2 index */
@@ -417,7 +416,6 @@ DataStoreTLBMiss:
rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */
lwz r10, 0(r10) /* Get the pte */
- ori r11, r11, 1 /* Set valid bit in physical L2 page */
/* Insert the Guarded flag into the TWC from the Linux PTE.
* It is bit 27 of both the Linux PTE and the TWC (at least
* I got that right :-). It will be better when we can put
--
1.7.1
^ permalink raw reply related
* [PATCH v2 09/19] powerpc/8xx: Optimize verification in FixupDAR
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
By XORing the upper part of the instruction code, we get a value that can
directly be verified with the second test and we can remove the first test.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index e5a250c..5037420 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -542,10 +542,8 @@ FixupDAR:/* Entry point for dcbx workaround. */
/* Check if it really is a dcbx instruction. */
/* dcbt and dcbtst does not generate DTLB Misses/Errors,
* no need to include them here */
- srwi r10, r11, 26 /* check if major OP code is 31 */
- cmpwi cr0, r10, 31
- bne- 141f
- rlwinm r10, r11, 0, 21, 30
+ xoris r10, r11, 0x7c00 /* check if major OP code is 31 */
+ rlwinm r10, r10, 0, 21, 5
cmpwi cr0, r10, 2028 /* Is dcbz? */
beq+ 142f
cmpwi cr0, r10, 940 /* Is dcbi? */
--
1.7.1
^ permalink raw reply related
* [PATCH v2 19/19] powerpc/8xx: Don't restore regs to save them again.
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
There is not need to restore r10, r11 and cr registers at this end of ITLBmiss
handler as they are saved again to the same place in ITLBError handler we are
jumping to.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index bb7c816..e21f0b2 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -381,8 +381,7 @@ InstructionTLBMiss:
lwz r3, 8(r0)
#endif
mfspr r10, SPRN_SPRG_SCRATCH2
- EXCEPTION_EPILOG_0
- b InstructionTLBError
+ b InstructionTLBError1
. = 0x1200
DataStoreTLBMiss:
@@ -471,7 +470,10 @@ DataStoreTLBMiss:
*/
. = 0x1300
InstructionTLBError:
- EXCEPTION_PROLOG
+ EXCEPTION_PROLOG_0
+InstructionTLBError1:
+ EXCEPTION_PROLOG_1
+ EXCEPTION_PROLOG_2
mr r4,r12
mr r5,r9
EXC_XFER_LITE(0x1300, handle_page_fault)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 17/19] powerpc/8xx: set PTE bit 22 off TLBmiss
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
No need to re-set this bit at each TLB miss. Let's set it in the PTE.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/pgtable-ppc32.h | 21 +++++++++++++++++++++
arch/powerpc/include/asm/pte-8xx.h | 7 +++++--
arch/powerpc/kernel/head_8xx.S | 10 ++--------
3 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
index 47edde8..c261792 100644
--- a/arch/powerpc/include/asm/pgtable-ppc32.h
+++ b/arch/powerpc/include/asm/pgtable-ppc32.h
@@ -172,6 +172,26 @@ static inline unsigned long pte_update(pte_t *p,
#ifdef PTE_ATOMIC_UPDATES
unsigned long old, tmp;
+#ifdef CONFIG_PPC_8xx
+ unsigned long tmp2;
+
+ __asm__ __volatile__("\
+1: lwarx %0,0,%4\n\
+ andc %1,%0,%5\n\
+ or %1,%1,%6\n\
+ /* 0x200 == Extended encoding, bit 22 */ \
+ /* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \
+ rlwimi %1,%1,32-2,0x200\n /* get _PAGE_USER */ \
+ rlwinm %3,%1,32-1,0x200\n /* get _PAGE_RW */ \
+ or %1,%3,%1\n\
+ xori %1,%1,0x200\n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4\n\
+ bne- 1b"
+ : "=&r" (old), "=&r" (tmp), "=m" (*p), "=&r" (tmp2)
+ : "r" (p), "r" (clr), "r" (set), "m" (*p)
+ : "cc" );
+#else /* CONFIG_PPC_8xx */
__asm__ __volatile__("\
1: lwarx %0,0,%3\n\
andc %1,%0,%4\n\
@@ -182,6 +202,7 @@ static inline unsigned long pte_update(pte_t *p,
: "=&r" (old), "=&r" (tmp), "=m" (*p)
: "r" (p), "r" (clr), "r" (set), "m" (*p)
: "cc" );
+#endif /* CONFIG_PPC_8xx */
#else /* PTE_ATOMIC_UPDATES */
unsigned long old = pte_val(*p);
*p = __pte((old & ~clr) | set);
diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
index d44826e..dede1e7 100644
--- a/arch/powerpc/include/asm/pte-8xx.h
+++ b/arch/powerpc/include/asm/pte-8xx.h
@@ -48,19 +48,22 @@
*/
#define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */
#define _PAGE_USER 0x0800 /* msb PP bits */
+/* set when neither _PAGE_USER nor _PAGE_RW are set */
+#define _PAGE_KNLRO 0x0200
#define _PMD_PRESENT 0x0001
#define _PMD_BAD 0x0ff0
#define _PMD_PAGE_MASK 0x000c
#define _PMD_PAGE_8M 0x000c
-#define _PTE_NONE_MASK _PAGE_ACCESSED
+#define _PTE_NONE_MASK (_PAGE_ACCESSED | _PAGE_KNLRO)
/* Until my rework is finished, 8xx still needs atomic PTE updates */
#define PTE_ATOMIC_UPDATES 1
/* We need to add _PAGE_SHARED to kernel pages */
-#define _PAGE_KERNEL_RO (_PAGE_SHARED)
+#define _PAGE_KERNEL_RO (_PAGE_SHARED | _PAGE_KNLRO)
+#define _PAGE_KERNEL_ROX (_PAGE_EXEC | _PAGE_KNLRO)
#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index a7af26e..48d3de8 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -445,14 +445,8 @@ DataStoreTLBMiss:
and r11, r11, r10
rlwimi r10, r11, 0, _PAGE_PRESENT
#endif
- /* Honour kernel RO, User NA */
- /* 0x200 == Extended encoding, bit 22 */
- rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
- /* r11 = (r10 & _PAGE_RW) >> 1 */
- rlwinm r11, r10, 32-1, 0x200
- or r10, r11, r10
- /* invert RW and 0x200 bits */
- xori r10, r10, _PAGE_RW | 0x200
+ /* invert RW */
+ xori r10, r10, _PAGE_RW
/* The Linux PTE won't go exactly into the MMU TLB.
* Software indicator bits 22 and 28 must be clear.
--
1.7.1
^ permalink raw reply related
* [PATCH v2 12/19] powerpc/8xx: Don't use MD_TWC for walk
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
MD_TWC can only be used properly with 4k pages.
So lets calculate level 2 table index by ourselves.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 28 ++++++++++++----------------
1 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index ad15070..0f571f5 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -297,8 +297,6 @@ InstructionTLBMiss:
addi r11, r10, -0x1000
tlbie r11
#endif
- DO_8xx_CPU6(0x3780, r3)
- mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -326,10 +324,9 @@ InstructionTLBMiss:
ori r11,r11,1 /* Set valid bit */
DO_8xx_CPU6(0x2b80, r3)
mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
- lwz r10, 0(r11) /* Get the pte */
+ mfspr r11, SPRN_SRR0 /* Get effective address of fault */
+ rlwinm r11, r11, 22, 20, 29 /* Extract level 2 index */
+ lwzx r10, r10, r11 /* Get the pte */
#ifdef CONFIG_SWAP
andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT
@@ -395,12 +392,13 @@ DataStoreTLBMiss:
/* We have a pte table, so load fetch the pte from the table.
*/
- ori r11, r11, 1 /* Set valid bit in physical L2 page */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
+ mfspr r10, SPRN_MD_EPN /* Get address of fault */
+ /* Extract level 2 index */
+ rlwinm r10, r10, 22, 20, 29
+ rlwimi r10, r11, 0, 0, 19 /* Add level 2 base */
lwz r10, 0(r10) /* Get the pte */
+ ori r11, r11, 1 /* Set valid bit in physical L2 page */
/* Insert the Guarded flag into the TWC from the Linux PTE.
* It is bit 27 of both the Linux PTE and the TWC (at least
* I got that right :-). It will be better when we can put
@@ -524,18 +522,16 @@ FixupDAR:/* Entry point for dcbx workaround. */
/* fetch instruction from memory. */
mfspr r10, SPRN_SRR0
andis. r11, r10, 0x8000 /* Address >= 0x80000000 */
- DO_8xx_CPU6(0x3780, r3)
- mtspr SPRN_MD_EPN, r10
mfspr r11, SPRN_M_TW /* Get level 1 table base address */
beq- 3f /* Branch if user space */
lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
3: rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
lwzx r11, r10, r11 /* Get the level 1 entry */
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
- mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
- lwz r11, 0(r11) /* Get the pte */
+ rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */
+ mfspr r11, SPRN_SRR0 /* Get effective address of fault */
+ rlwinm r11, r11, 22, 20, 29 /* Extract level 2 index */
+ lwzx r11, r10, r11 /* Get the pte */
#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0) /* restore r3 from memory */
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH v2 08/19] powerpc/8xx: No need to restore registers and save them again.
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
In DTLBError handler there is not need to restore r10, r11 and cr registers
after fixing DAR as they are saved again to the same place just after.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 5f04d5f..e5a250c 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -478,8 +478,8 @@ DataTLBError:
cmpwi cr0, r11, 0x00f0
beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
DARFixed:/* Return from dcbx instruction bug workaround */
- EXCEPTION_EPILOG_0
- EXCEPTION_PROLOG
+ EXCEPTION_PROLOG_1
+ EXCEPTION_PROLOG_2
mfspr r10,SPRN_DSISR
stw r10,_DSISR(r11)
mr r5,r10
--
1.7.1
^ permalink raw reply related
* [PATCH v2 07/19] powerpc/8xx: DataAccess exception not generated by MPC8xx
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
DataAccess exception is never generated by MPC8xx so do the job directly where
it is used to avoid an unnecessary branching.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 23 ++++++++++-------------
1 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 845abf8..5f04d5f 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -219,19 +219,9 @@ MachineCheck:
EXC_XFER_STD(0x200, machine_check_exception)
/* Data access exception.
- * This is "never generated" by the MPC8xx. We jump to it for other
- * translation errors.
+ * This is "never generated" by the MPC8xx.
*/
- . = 0x300
-DataAccess:
- EXCEPTION_PROLOG
- mfspr r10,SPRN_DSISR
- stw r10,_DSISR(r11)
- mr r5,r10
- mfspr r4,SPRN_DAR
- li r10,0x00f0
- mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
- EXC_XFER_LITE(0x300, handle_page_fault)
+ EXCEPTION(0x300, DataAccess, unknown_exception, EXC_XFER_STD)
/* Instruction access exception.
* This is "never generated" by the MPC8xx.
@@ -489,7 +479,14 @@ DataTLBError:
beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
DARFixed:/* Return from dcbx instruction bug workaround */
EXCEPTION_EPILOG_0
- b DataAccess
+ EXCEPTION_PROLOG
+ mfspr r10,SPRN_DSISR
+ stw r10,_DSISR(r11)
+ mr r5,r10
+ mfspr r4,SPRN_DAR
+ li r10,0x00f0
+ mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
+ EXC_XFER_LITE(0x1400, handle_page_fault)
EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 13/19] powerpc/8xx: Use PAGE size related consts
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
For PAGE size related operations, use PAGE size consts in order to be able to
use different page size in the futur.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 30 ++++++++++++++++++------------
1 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 0f571f5..dcaee9f 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -292,9 +292,9 @@ InstructionTLBMiss:
mtspr SPRN_SPRG_SCRATCH2, r10
mfspr r10, SPRN_SRR0 /* Get effective address of fault */
#ifdef CONFIG_8xx_CPU15
- addi r11, r10, 0x1000
+ addi r11, r10, PAGE_SIZE
tlbie r11
- addi r11, r10, -0x1000
+ addi r11, r10, -PAGE_SIZE
tlbie r11
#endif
@@ -313,7 +313,8 @@ InstructionTLBMiss:
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
3:
#endif
- rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
+ /* Extract level 1 index */
+ rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
lwzx r11, r10, r11 /* Get the level 1 entry */
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
@@ -325,7 +326,8 @@ InstructionTLBMiss:
DO_8xx_CPU6(0x2b80, r3)
mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
mfspr r11, SPRN_SRR0 /* Get effective address of fault */
- rlwinm r11, r11, 22, 20, 29 /* Extract level 2 index */
+ /* Extract level 2 index */
+ rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
lwzx r10, r10, r11 /* Get the pte */
#ifdef CONFIG_SWAP
@@ -385,7 +387,8 @@ DataStoreTLBMiss:
lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
3:
- rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
+ /* Extract level 1 index */
+ rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
lwzx r11, r10, r11 /* Get the level 1 entry */
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
@@ -394,8 +397,8 @@ DataStoreTLBMiss:
*/
mfspr r10, SPRN_MD_EPN /* Get address of fault */
/* Extract level 2 index */
- rlwinm r10, r10, 22, 20, 29
- rlwimi r10, r11, 0, 0, 19 /* Add level 2 base */
+ rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
+ rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */
lwz r10, 0(r10) /* Get the pte */
ori r11, r11, 1 /* Set valid bit in physical L2 page */
@@ -526,18 +529,20 @@ FixupDAR:/* Entry point for dcbx workaround. */
beq- 3f /* Branch if user space */
lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
-3: rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
+ /* Extract level 1 index */
+3: rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
lwzx r11, r10, r11 /* Get the level 1 entry */
rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */
mfspr r11, SPRN_SRR0 /* Get effective address of fault */
- rlwinm r11, r11, 22, 20, 29 /* Extract level 2 index */
+ /* Extract level 2 index */
+ rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
lwzx r11, r10, r11 /* Get the pte */
#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0) /* restore r3 from memory */
#endif
/* concat physical page address(r11) and page offset(r10) */
mfspr r10, SPRN_SRR0
- rlwimi r11, r10, 0, 20, 31
+ rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31
lwz r11,0(r11)
/* Check if it really is a dcbx instruction. */
/* dcbt and dcbtst does not generate DTLB Misses/Errors,
@@ -913,12 +918,13 @@ set_dec_cpu6:
.globl sdata
sdata:
.globl empty_zero_page
+ .align PAGE_SHIFT
empty_zero_page:
- .space 4096
+ .space PAGE_SIZE
.globl swapper_pg_dir
swapper_pg_dir:
- .space 4096
+ .space PGD_TABLE_SIZE
/* Room for two PTE table poiners, usually the kernel and current user
* pointer to their respective root page table (pgdir).
--
1.7.1
^ permalink raw reply related
* [PATCHv2] clk: ppc-corenet: rename to ppc-qoriq and add CLK_OF_DECLARE support
From: Jingchang Lu @ 2014-08-29 8:35 UTC (permalink / raw)
To: mturquette
Cc: scottwood, linuxppc-dev, linux-kernel, linux-arm-kernel,
Jingchang Lu
The IP is shared on PPC and ARM, this rename it to qoriq for better
represention, and this also add the CLK_OF_DECLARE support for being
initialized by of_clk_init() on ARM.
Signed-off-by: Jingchang Lu <jingchang.lu@freescale.com>
---
changes in v2:
rename the driver name to ppc-qoriq.c for shared on PPC and ARM.
drivers/clk/Kconfig | 9 +-
drivers/clk/Makefile | 2 +-
drivers/clk/clk-ppc-corenet.c | 307 -----------------------------------------
drivers/clk/clk-qoriq.c | 312 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 318 insertions(+), 312 deletions(-)
delete mode 100644 drivers/clk/clk-ppc-corenet.c
create mode 100644 drivers/clk/clk-qoriq.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index cfd3af7..d7892b9 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -81,12 +81,13 @@ config COMMON_CLK_AXI_CLKGEN
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
FPGAs. It is commonly used in Analog Devices' reference designs.
-config CLK_PPC_CORENET
- bool "Clock driver for PowerPC corenet platforms"
- depends on PPC_E500MC && OF
+config CLK_QORIQ
+ bool "Clock driver for PowerPC corenet and compatible ARM-based platforms"
+ depends on (PPC_E500MC || ARM) && OF
---help---
This adds the clock driver support for Freescale PowerPC corenet
- platforms using common clock framework.
+ platforms and compatible Freescale ARM based platforms using common
+ clock framework.
config COMMON_CLK_XGENE
bool "Clock driver for APM XGene SoC"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 312742c..c8f1f52 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
-obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
+obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-ppc-corenet.c
deleted file mode 100644
index 8e58edf..0000000
--- a/drivers/clk/clk-ppc-corenet.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * clock driver for Freescale PowerPC corenet SoCs.
- */
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-
-struct cmux_clk {
- struct clk_hw hw;
- void __iomem *reg;
- u32 flags;
-};
-
-#define PLL_KILL BIT(31)
-#define CLKSEL_SHIFT 27
-#define CLKSEL_ADJUST BIT(0)
-#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw)
-
-static unsigned int clocks_per_pll;
-
-static int cmux_set_parent(struct clk_hw *hw, u8 idx)
-{
- struct cmux_clk *clk = to_cmux_clk(hw);
- u32 clksel;
-
- clksel = ((idx / clocks_per_pll) << 2) + idx % clocks_per_pll;
- if (clk->flags & CLKSEL_ADJUST)
- clksel += 8;
- clksel = (clksel & 0xf) << CLKSEL_SHIFT;
- iowrite32be(clksel, clk->reg);
-
- return 0;
-}
-
-static u8 cmux_get_parent(struct clk_hw *hw)
-{
- struct cmux_clk *clk = to_cmux_clk(hw);
- u32 clksel;
-
- clksel = ioread32be(clk->reg);
- clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
- if (clk->flags & CLKSEL_ADJUST)
- clksel -= 8;
- clksel = (clksel >> 2) * clocks_per_pll + clksel % 4;
-
- return clksel;
-}
-
-const struct clk_ops cmux_ops = {
- .get_parent = cmux_get_parent,
- .set_parent = cmux_set_parent,
-};
-
-static void __init core_mux_init(struct device_node *np)
-{
- struct clk *clk;
- struct clk_init_data init;
- struct cmux_clk *cmux_clk;
- struct device_node *node;
- int rc, count, i;
- u32 offset;
- const char *clk_name;
- const char **parent_names;
-
- rc = of_property_read_u32(np, "reg", &offset);
- if (rc) {
- pr_err("%s: could not get reg property\n", np->name);
- return;
- }
-
- /* get the input clock source count */
- count = of_property_count_strings(np, "clock-names");
- if (count < 0) {
- pr_err("%s: get clock count error\n", np->name);
- return;
- }
- parent_names = kzalloc((sizeof(char *) * count), GFP_KERNEL);
- if (!parent_names) {
- pr_err("%s: could not allocate parent_names\n", __func__);
- return;
- }
-
- for (i = 0; i < count; i++)
- parent_names[i] = of_clk_get_parent_name(np, i);
-
- cmux_clk = kzalloc(sizeof(struct cmux_clk), GFP_KERNEL);
- if (!cmux_clk) {
- pr_err("%s: could not allocate cmux_clk\n", __func__);
- goto err_name;
- }
- cmux_clk->reg = of_iomap(np, 0);
- if (!cmux_clk->reg) {
- pr_err("%s: could not map register\n", __func__);
- goto err_clk;
- }
-
- node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
- if (node && (offset >= 0x80))
- cmux_clk->flags = CLKSEL_ADJUST;
-
- rc = of_property_read_string_index(np, "clock-output-names",
- 0, &clk_name);
- if (rc) {
- pr_err("%s: read clock names error\n", np->name);
- goto err_clk;
- }
-
- init.name = clk_name;
- init.ops = &cmux_ops;
- init.parent_names = parent_names;
- init.num_parents = count;
- init.flags = 0;
- cmux_clk->hw.init = &init;
-
- clk = clk_register(NULL, &cmux_clk->hw);
- if (IS_ERR(clk)) {
- pr_err("%s: could not register clock\n", clk_name);
- goto err_clk;
- }
-
- rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
- if (rc) {
- pr_err("Could not register clock provider for node:%s\n",
- np->name);
- goto err_clk;
- }
- goto err_name;
-
-err_clk:
- kfree(cmux_clk);
-err_name:
- /* free *_names because they are reallocated when registered */
- kfree(parent_names);
-}
-
-static void __init core_pll_init(struct device_node *np)
-{
- u32 mult;
- int i, rc, count;
- const char *clk_name, *parent_name;
- struct clk_onecell_data *onecell_data;
- struct clk **subclks;
- void __iomem *base;
-
- base = of_iomap(np, 0);
- if (!base) {
- pr_err("clk-ppc: iomap error\n");
- return;
- }
-
- /* get the multiple of PLL */
- mult = ioread32be(base);
-
- /* check if this PLL is disabled */
- if (mult & PLL_KILL) {
- pr_debug("PLL:%s is disabled\n", np->name);
- goto err_map;
- }
- mult = (mult >> 1) & 0x3f;
-
- parent_name = of_clk_get_parent_name(np, 0);
- if (!parent_name) {
- pr_err("PLL: %s must have a parent\n", np->name);
- goto err_map;
- }
-
- count = of_property_count_strings(np, "clock-output-names");
- if (count < 0 || count > 4) {
- pr_err("%s: clock is not supported\n", np->name);
- goto err_map;
- }
-
- /* output clock number per PLL */
- clocks_per_pll = count;
-
- subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL);
- if (!subclks) {
- pr_err("%s: could not allocate subclks\n", __func__);
- goto err_map;
- }
-
- onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
- if (!onecell_data) {
- pr_err("%s: could not allocate onecell_data\n", __func__);
- goto err_clks;
- }
-
- for (i = 0; i < count; i++) {
- rc = of_property_read_string_index(np, "clock-output-names",
- i, &clk_name);
- if (rc) {
- pr_err("%s: could not get clock names\n", np->name);
- goto err_cell;
- }
-
- /*
- * when count == 4, there are 4 output clocks:
- * /1, /2, /3, /4 respectively
- * when count < 4, there are at least 2 output clocks:
- * /1, /2, (/4, if count == 3) respectively.
- */
- if (count == 4)
- subclks[i] = clk_register_fixed_factor(NULL, clk_name,
- parent_name, 0, mult, 1 + i);
- else
-
- subclks[i] = clk_register_fixed_factor(NULL, clk_name,
- parent_name, 0, mult, 1 << i);
-
- if (IS_ERR(subclks[i])) {
- pr_err("%s: could not register clock\n", clk_name);
- goto err_cell;
- }
- }
-
- onecell_data->clks = subclks;
- onecell_data->clk_num = count;
-
- rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
- if (rc) {
- pr_err("Could not register clk provider for node:%s\n",
- np->name);
- goto err_cell;
- }
-
- iounmap(base);
- return;
-err_cell:
- kfree(onecell_data);
-err_clks:
- kfree(subclks);
-err_map:
- iounmap(base);
-}
-
-static void __init sysclk_init(struct device_node *node)
-{
- struct clk *clk;
- const char *clk_name = node->name;
- struct device_node *np = of_get_parent(node);
- u32 rate;
-
- if (!np) {
- pr_err("ppc-clk: could not get parent node\n");
- return;
- }
-
- if (of_property_read_u32(np, "clock-frequency", &rate)) {
- of_node_put(node);
- return;
- }
-
- of_property_read_string(np, "clock-output-names", &clk_name);
-
- clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
- if (!IS_ERR(clk))
- of_clk_add_provider(np, of_clk_src_simple_get, clk);
-}
-
-static const struct of_device_id clk_match[] __initconst = {
- { .compatible = "fsl,qoriq-sysclk-1.0", .data = sysclk_init, },
- { .compatible = "fsl,qoriq-sysclk-2.0", .data = sysclk_init, },
- { .compatible = "fsl,qoriq-core-pll-1.0", .data = core_pll_init, },
- { .compatible = "fsl,qoriq-core-pll-2.0", .data = core_pll_init, },
- { .compatible = "fsl,qoriq-core-mux-1.0", .data = core_mux_init, },
- { .compatible = "fsl,qoriq-core-mux-2.0", .data = core_mux_init, },
- {}
-};
-
-static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
-{
- of_clk_init(clk_match);
-
- return 0;
-}
-
-static const struct of_device_id ppc_clk_ids[] __initconst = {
- { .compatible = "fsl,qoriq-clockgen-1.0", },
- { .compatible = "fsl,qoriq-clockgen-2.0", },
- {}
-};
-
-static struct platform_driver ppc_corenet_clk_driver __initdata = {
- .driver = {
- .name = "ppc_corenet_clock",
- .owner = THIS_MODULE,
- .of_match_table = ppc_clk_ids,
- },
- .probe = ppc_corenet_clk_probe,
-};
-
-static int __init ppc_corenet_clk_init(void)
-{
- return platform_driver_register(&ppc_corenet_clk_driver);
-}
-subsys_initcall(ppc_corenet_clk_init);
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
new file mode 100644
index 0000000..7692cac
--- /dev/null
+++ b/drivers/clk/clk-qoriq.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * clock driver for Freescale PowerPC corenet SoCs.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+struct cmux_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u32 flags;
+};
+
+#define PLL_KILL BIT(31)
+#define CLKSEL_SHIFT 27
+#define CLKSEL_ADJUST BIT(0)
+#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw)
+
+static unsigned int clocks_per_pll;
+
+static int cmux_set_parent(struct clk_hw *hw, u8 idx)
+{
+ struct cmux_clk *clk = to_cmux_clk(hw);
+ u32 clksel;
+
+ clksel = ((idx / clocks_per_pll) << 2) + idx % clocks_per_pll;
+ if (clk->flags & CLKSEL_ADJUST)
+ clksel += 8;
+ clksel = (clksel & 0xf) << CLKSEL_SHIFT;
+ iowrite32be(clksel, clk->reg);
+
+ return 0;
+}
+
+static u8 cmux_get_parent(struct clk_hw *hw)
+{
+ struct cmux_clk *clk = to_cmux_clk(hw);
+ u32 clksel;
+
+ clksel = ioread32be(clk->reg);
+ clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
+ if (clk->flags & CLKSEL_ADJUST)
+ clksel -= 8;
+ clksel = (clksel >> 2) * clocks_per_pll + clksel % 4;
+
+ return clksel;
+}
+
+const struct clk_ops cmux_ops = {
+ .get_parent = cmux_get_parent,
+ .set_parent = cmux_set_parent,
+};
+
+static void __init core_mux_init(struct device_node *np)
+{
+ struct clk *clk;
+ struct clk_init_data init;
+ struct cmux_clk *cmux_clk;
+ struct device_node *node;
+ int rc, count, i;
+ u32 offset;
+ const char *clk_name;
+ const char **parent_names;
+
+ rc = of_property_read_u32(np, "reg", &offset);
+ if (rc) {
+ pr_err("%s: could not get reg property\n", np->name);
+ return;
+ }
+
+ /* get the input clock source count */
+ count = of_property_count_strings(np, "clock-names");
+ if (count < 0) {
+ pr_err("%s: get clock count error\n", np->name);
+ return;
+ }
+ parent_names = kzalloc((sizeof(char *) * count), GFP_KERNEL);
+ if (!parent_names) {
+ pr_err("%s: could not allocate parent_names\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < count; i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+
+ cmux_clk = kzalloc(sizeof(struct cmux_clk), GFP_KERNEL);
+ if (!cmux_clk) {
+ pr_err("%s: could not allocate cmux_clk\n", __func__);
+ goto err_name;
+ }
+ cmux_clk->reg = of_iomap(np, 0);
+ if (!cmux_clk->reg) {
+ pr_err("%s: could not map register\n", __func__);
+ goto err_clk;
+ }
+
+ node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
+ if (node && (offset >= 0x80))
+ cmux_clk->flags = CLKSEL_ADJUST;
+
+ rc = of_property_read_string_index(np, "clock-output-names",
+ 0, &clk_name);
+ if (rc) {
+ pr_err("%s: read clock names error\n", np->name);
+ goto err_clk;
+ }
+
+ init.name = clk_name;
+ init.ops = &cmux_ops;
+ init.parent_names = parent_names;
+ init.num_parents = count;
+ init.flags = 0;
+ cmux_clk->hw.init = &init;
+
+ clk = clk_register(NULL, &cmux_clk->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: could not register clock\n", clk_name);
+ goto err_clk;
+ }
+
+ rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (rc) {
+ pr_err("Could not register clock provider for node:%s\n",
+ np->name);
+ goto err_clk;
+ }
+ goto err_name;
+
+err_clk:
+ kfree(cmux_clk);
+err_name:
+ /* free *_names because they are reallocated when registered */
+ kfree(parent_names);
+}
+
+static void __init core_pll_init(struct device_node *np)
+{
+ u32 mult;
+ int i, rc, count;
+ const char *clk_name, *parent_name;
+ struct clk_onecell_data *onecell_data;
+ struct clk **subclks;
+ void __iomem *base;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("clk-ppc: iomap error\n");
+ return;
+ }
+
+ /* get the multiple of PLL */
+ mult = ioread32be(base);
+
+ /* check if this PLL is disabled */
+ if (mult & PLL_KILL) {
+ pr_debug("PLL:%s is disabled\n", np->name);
+ goto err_map;
+ }
+ mult = (mult >> 1) & 0x3f;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+ if (!parent_name) {
+ pr_err("PLL: %s must have a parent\n", np->name);
+ goto err_map;
+ }
+
+ count = of_property_count_strings(np, "clock-output-names");
+ if (count < 0 || count > 4) {
+ pr_err("%s: clock is not supported\n", np->name);
+ goto err_map;
+ }
+
+ /* output clock number per PLL */
+ clocks_per_pll = count;
+
+ subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL);
+ if (!subclks) {
+ pr_err("%s: could not allocate subclks\n", __func__);
+ goto err_map;
+ }
+
+ onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+ if (!onecell_data) {
+ pr_err("%s: could not allocate onecell_data\n", __func__);
+ goto err_clks;
+ }
+
+ for (i = 0; i < count; i++) {
+ rc = of_property_read_string_index(np, "clock-output-names",
+ i, &clk_name);
+ if (rc) {
+ pr_err("%s: could not get clock names\n", np->name);
+ goto err_cell;
+ }
+
+ /*
+ * when count == 4, there are 4 output clocks:
+ * /1, /2, /3, /4 respectively
+ * when count < 4, there are at least 2 output clocks:
+ * /1, /2, (/4, if count == 3) respectively.
+ */
+ if (count == 4)
+ subclks[i] = clk_register_fixed_factor(NULL, clk_name,
+ parent_name, 0, mult, 1 + i);
+ else
+
+ subclks[i] = clk_register_fixed_factor(NULL, clk_name,
+ parent_name, 0, mult, 1 << i);
+
+ if (IS_ERR(subclks[i])) {
+ pr_err("%s: could not register clock\n", clk_name);
+ goto err_cell;
+ }
+ }
+
+ onecell_data->clks = subclks;
+ onecell_data->clk_num = count;
+
+ rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
+ if (rc) {
+ pr_err("Could not register clk provider for node:%s\n",
+ np->name);
+ goto err_cell;
+ }
+
+ iounmap(base);
+ return;
+err_cell:
+ kfree(onecell_data);
+err_clks:
+ kfree(subclks);
+err_map:
+ iounmap(base);
+}
+
+static void __init sysclk_init(struct device_node *node)
+{
+ struct clk *clk;
+ const char *clk_name = node->name;
+ struct device_node *np = of_get_parent(node);
+ u32 rate;
+
+ if (!np) {
+ pr_err("ppc-clk: could not get parent node\n");
+ return;
+ }
+
+ if (of_property_read_u32(np, "clock-frequency", &rate)) {
+ of_node_put(node);
+ return;
+ }
+
+ of_property_read_string(np, "clock-output-names", &clk_name);
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static const struct of_device_id clk_match[] __initconst = {
+ { .compatible = "fsl,qoriq-sysclk-1.0", .data = sysclk_init, },
+ { .compatible = "fsl,qoriq-sysclk-2.0", .data = sysclk_init, },
+ { .compatible = "fsl,qoriq-core-pll-1.0", .data = core_pll_init, },
+ { .compatible = "fsl,qoriq-core-pll-2.0", .data = core_pll_init, },
+ { .compatible = "fsl,qoriq-core-mux-1.0", .data = core_mux_init, },
+ { .compatible = "fsl,qoriq-core-mux-2.0", .data = core_mux_init, },
+ {}
+};
+
+static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
+{
+ of_clk_init(clk_match);
+
+ return 0;
+}
+
+static const struct of_device_id ppc_clk_ids[] __initconst = {
+ { .compatible = "fsl,qoriq-clockgen-1.0", },
+ { .compatible = "fsl,qoriq-clockgen-2.0", },
+ {}
+};
+
+static struct platform_driver ppc_corenet_clk_driver __initdata = {
+ .driver = {
+ .name = "ppc_corenet_clock",
+ .owner = THIS_MODULE,
+ .of_match_table = ppc_clk_ids,
+ },
+ .probe = ppc_corenet_clk_probe,
+};
+
+static int __init ppc_corenet_clk_init(void)
+{
+ return platform_driver_register(&ppc_corenet_clk_driver);
+}
+subsys_initcall(ppc_corenet_clk_init);
+
+CLK_OF_DECLARE(ppc_core_pll_v1, "fsl,qoriq-core-pll-1.0", core_pll_init);
+CLK_OF_DECLARE(ppc_core_pll_v2, "fsl,qoriq-core-pll-2.0", core_pll_init);
+CLK_OF_DECLARE(ppc_core_mux_v1, "fsl,qoriq-core-mux-1.0", core_mux_init);
+CLK_OF_DECLARE(ppc_core_mux_v2, "fsl,qoriq-core-mux-2.0", core_mux_init);
--
1.8.0
^ permalink raw reply related
* [PATCH v2 14/19] powerpc/8xx: Const for TLB RPN forced value
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
Value 0x00f0 is used to force bits in TLB level 2 entry. This value is linked
to the page size and will vary when we change the page size. Lets define a const
for it in order to have it at only one place.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 19 +++++++++++++------
1 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index dcaee9f..8966262 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -40,6 +40,13 @@
#else
#define DO_8xx_CPU6(val, reg)
#endif
+
+/*
+ * Value for the bits that have fixed value in RPN entries.
+ * Also used for tagging DAR for DTLBerror.
+ */
+#define RPN_PATTERN 0x00f0
+
__HEAD
_ENTRY(_stext);
_ENTRY(_start);
@@ -211,7 +218,7 @@ MachineCheck:
EXCEPTION_PROLOG
mfspr r4,SPRN_DAR
stw r4,_DAR(r11)
- li r5,0x00f0
+ li r5,RPN_PATTERN
mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */
mfspr r5,SPRN_DSISR
stw r5,_DSISR(r11)
@@ -237,7 +244,7 @@ Alignment:
EXCEPTION_PROLOG
mfspr r4,SPRN_DAR
stw r4,_DAR(r11)
- li r5,0x00f0
+ li r5,RPN_PATTERN
mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */
mfspr r5,SPRN_DSISR
stw r5,_DSISR(r11)
@@ -341,7 +348,7 @@ InstructionTLBMiss:
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
- li r11, 0x00f0
+ li r11, RPN_PATTERN
rlwimi r10, r11, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */
DO_8xx_CPU6(0x2d80, r3)
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
@@ -445,7 +452,7 @@ DataStoreTLBMiss:
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
-2: li r11, 0x00f0
+2: li r11, RPN_PATTERN
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x3d80, r3)
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
@@ -479,7 +486,7 @@ DataTLBError:
EXCEPTION_PROLOG_0
mfspr r11, SPRN_DAR
- cmpwi cr0, r11, 0x00f0
+ cmpwi cr0, r11, RPN_PATTERN
beq- FixupDAR /* must be a buggy dcbX, icbi insn. */
DARFixed:/* Return from dcbx instruction bug workaround */
EXCEPTION_PROLOG_1
@@ -488,7 +495,7 @@ DARFixed:/* Return from dcbx instruction bug workaround */
stw r10,_DSISR(r11)
mr r5,r10
mfspr r4,SPRN_DAR
- li r10,0x00f0
+ li r10,RPN_PATTERN
mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
EXC_XFER_LITE(0x1400, handle_page_fault)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 11/19] powerpc/8xx: Use M_TW instead of M_TWB
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
Use M_TW instead of M_TWB for storing Level 1 table address as M_TWB requires
4k aligned tables, which is only the case with 4k pages.
Consequently, we have to calculate the level 1 table index by ourselves.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 48 ++++++++++++++++++---------------
1 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 4a49ff3..ad15070 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -276,8 +276,8 @@ SystemCall:
. = 0x1100
/*
* For the MPC8xx, this is a software tablewalk to load the instruction
- * TLB. It is modelled after the example in the Motorola manual. The task
- * switch loads the M_TWB register with the pointer to the first level table.
+ * TLB. The task switch loads the M_TW register with the pointer to the first
+ * level table.
* If we discover there is no second level table (value is zero) or if there
* is an invalid pte, we load that into the TLB, which causes another fault
* into the TLB Error interrupt where we can handle such problems.
@@ -299,7 +299,6 @@ InstructionTLBMiss:
#endif
DO_8xx_CPU6(0x3780, r3)
mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
- mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -307,14 +306,17 @@ InstructionTLBMiss:
#ifdef CONFIG_MODULES
/* Only modules will cause ITLB Misses as we always
* pin the first 8MB of kernel memory */
- andi. r11, r10, 0x0800 /* Address >= 0x80000000 */
+ andis. r11, r10, 0x8000 /* Address >= 0x80000000 */
+#endif
+ mfspr r11, SPRN_M_TW /* Get level 1 table base address */
+#ifdef CONFIG_MODULES
beq 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- rlwimi r10, r11, 0, 2, 19
+ lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
+ ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
3:
#endif
- lwz r11, 0(r10) /* Get the level 1 entry */
+ rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
+ lwzx r11, r10, r11 /* Get the level 1 entry */
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
@@ -375,18 +377,19 @@ DataStoreTLBMiss:
#endif
EXCEPTION_PROLOG_0
mtspr SPRN_SPRG_SCRATCH2, r10
- mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
+ mfspr r10, SPRN_MD_EPN
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andi. r11, r10, 0x0800
+ andis. r11, r10, 0x8000
+ mfspr r11, SPRN_M_TW /* Get level 1 table base address */
beq 3f
- lis r11, swapper_pg_dir@h
- ori r11, r11, swapper_pg_dir@l
- rlwimi r10, r11, 0, 2, 19
+ lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
+ ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
3:
- lwz r11, 0(r10) /* Get the level 1 entry */
+ rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
+ lwzx r11, r10, r11 /* Get the level 1 entry */
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
@@ -523,12 +526,12 @@ FixupDAR:/* Entry point for dcbx workaround. */
andis. r11, r10, 0x8000 /* Address >= 0x80000000 */
DO_8xx_CPU6(0x3780, r3)
mtspr SPRN_MD_EPN, r10
- mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */
+ mfspr r11, SPRN_M_TW /* Get level 1 table base address */
beq- 3f /* Branch if user space */
lis r11, (swapper_pg_dir-PAGE_OFFSET)@h
ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l
- rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */
-3: lwz r11, 0(r11) /* Get the level 1 entry */
+3: rlwinm r10, r10, 12, 20, 29 /* Extract level 1 index */
+ lwzx r11, r10, r11 /* Get the level 1 entry */
DO_8xx_CPU6(0x3b80, r3)
mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
@@ -537,6 +540,7 @@ FixupDAR:/* Entry point for dcbx workaround. */
lwz r3, 8(r0) /* restore r3 from memory */
#endif
/* concat physical page address(r11) and page offset(r10) */
+ mfspr r10, SPRN_SRR0
rlwimi r11, r10, 0, 20, 31
lwz r11,0(r11)
/* Check if it really is a dcbx instruction. */
@@ -692,11 +696,11 @@ start_here:
#ifdef CONFIG_8xx_CPU6
lis r4, cpu6_errata_word@h
ori r4, r4, cpu6_errata_word@l
- li r3, 0x3980
+ li r3, 0x3f80
stw r3, 12(r4)
lwz r3, 12(r4)
#endif
- mtspr SPRN_M_TWB, r6
+ mtspr SPRN_M_TW, r6
lis r4,2f@h
ori r4,r4,2f@l
tophys(r4,r4)
@@ -870,10 +874,10 @@ _GLOBAL(set_context)
lis r6, cpu6_errata_word@h
ori r6, r6, cpu6_errata_word@l
tophys (r4, r4)
- li r7, 0x3980
+ li r7, 0x3f80
stw r7, 12(r6)
lwz r7, 12(r6)
- mtspr SPRN_M_TWB, r4 /* Update MMU base address */
+ mtspr SPRN_M_TW, r4 /* Update MMU base address */
li r7, 0x3380
stw r7, 12(r6)
lwz r7, 12(r6)
@@ -881,7 +885,7 @@ _GLOBAL(set_context)
#else
mtspr SPRN_M_CASID,r3 /* Update context */
tophys (r4, r4)
- mtspr SPRN_M_TWB, r4 /* and pgd */
+ mtspr SPRN_M_TW, r4 /* and pgd */
#endif
SYNC
blr
--
1.7.1
^ permalink raw reply related
* [PATCH v2 16/19] powerpc/8xx: Better readibility of ERRATA CPU6 handling
From: Christophe Leroy @ 2014-08-29 9:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras
Cc: scottwood, linuxppc-dev, linux-kernel
This patch hiddes that SPR address needed for CPU6 ERRATA handling in the macro.
Then we don't have to worry about this address directly in the code.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/kernel/head_8xx.S | 29 ++++++++++++++++-------------
1 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 4dd6be0..a7af26e 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -33,12 +33,19 @@
/* Macro to make the code more readable. */
#ifdef CONFIG_8xx_CPU6
-#define DO_8xx_CPU6(val, reg) \
- li reg, val; \
- stw reg, 12(r0); \
- lwz reg, 12(r0);
+#define SPRN_MI_TWC_ADDR 0x2b80
+#define SPRN_MI_RPN_ADDR 0x2d80
+#define SPRN_MD_TWC_ADDR 0x3b80
+#define SPRN_MD_RPN_ADDR 0x3d80
+
+#define MTSPR_CPU6(spr, reg, treg) \
+ li treg, spr##_ADDR; \
+ stw treg, 12(r0); \
+ lwz treg, 12(r0); \
+ mtspr spr, reg
#else
-#define DO_8xx_CPU6(val, reg)
+#define MTSPR_CPU6(spr, reg, treg) \
+ mtspr spr, reg
#endif
/*
@@ -334,8 +341,7 @@ InstructionTLBMiss:
* for this "segment."
*/
ori r11,r11,1 /* Set valid bit */
- DO_8xx_CPU6(0x2b80, r3)
- mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
+ MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */
mfspr r11, SPRN_SRR0 /* Get effective address of fault */
/* Extract level 2 index */
rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
@@ -354,8 +360,7 @@ InstructionTLBMiss:
*/
li r11, RPN_PATTERN
rlwimi r10, r11, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */
- DO_8xx_CPU6(0x2d80, r3)
- mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
+ MTSPR_CPU6(SPRN_MI_RPN, r10, r3) /* Update TLB entry */
/* Restore registers */
#ifdef CONFIG_8xx_CPU6
@@ -424,8 +429,7 @@ DataStoreTLBMiss:
* It is bit 25 in the Linux PTE and bit 30 in the TWC
*/
rlwimi r11, r10, 32-5, 30, 30
- DO_8xx_CPU6(0x3b80, r3)
- mtspr SPRN_MD_TWC, r11
+ MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
* We also need to know if the insn is a load/store, so:
@@ -458,8 +462,7 @@ DataStoreTLBMiss:
*/
2: li r11, RPN_PATTERN
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
- DO_8xx_CPU6(0x3d80, r3)
- mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
+ MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
/* Restore registers */
#ifdef CONFIG_8xx_CPU6
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] powerpc: Check flat device tree version at boot
From: Grant Likely @ 2014-08-29 11:13 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Rob Herring, Rob Herring
In-Reply-To: <1409277356.9191.4.camel@concordia>
On 29 Aug 2014 02:56, "Michael Ellerman" <mpe@ellerman.id.au> wrote:
>
> On Thu, 2014-08-28 at 09:27 -0500, Rob Herring wrote:
> > On Thu, Aug 28, 2014 at 3:40 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
> > > In commit e6a6928c3ea1 "of/fdt: Convert FDT functions to use libfdt",
> > > the kernel stopped supporting old flat device tree formats. The minimum
> > > supported version is now 0x10.
> >
> > Ugg. Is that something which needs to be supported? Supporting it at
> > this point would mean adding support to libfdt.
>
> Well it would have been nice to keep supporting v2, dropping it broke
> kexec-tools for example. But it's done now, so we'll just deal with the
> fallout.
Umm, so we broke userspace? That's not okay. At the very least we
should investigate how much work is needed to bring v2 support into
libfdt, or up-rev the flat tree at runtime before we parse it.
We should be able to update it in-line. IIRC, the main difference
between v2 and v0x10 is that only the leaf node name is encoded into
the node instead of the full name. We can loop over the tree and
truncate all the names while filling the unused bytes with FDT NOP
tags. Should be simple. Something like the following:
fixup_old_device_tree(blob)
{
for (offset = fdt_next_node(blob, -1, &depth);
offset >= 0 && depth >= 0 && !rc;
offset = fdt_next_node(blob, offset, &depth)) {
char *pathp = fdt_get_name(blob, offset, NULL);
if (*pathp == '/') {
char *leaf = kbasename(pathp);
int len = strlen(pathp);
int newlen = strlen(leaf);
strcpy(pathp, leaf); /* copying in place, need
to check make sure this code is safe */
node->size = newlen /* fixme - this is just
pseudocode */
newlen = FDT_TAGALIGN(newlen);
while (newlen < len) {
*(pathp + newlen) = FDT_NOP;
newlen = FDT_TAGALIGN(newlen+1);
}
}
}
}
There's probable some more elegance that can be put into the above
block, but you get the idea. That could be run in-place without
copying the tree to another location, and it could possibly be done in
the boot wrapper. Then we'd also be able to get rid of the v2
compatibility code elsewhere in drivers/of/fdt.c because it would
already be taken care of.
g.
^ permalink raw reply
* Re: [PATCH v2 03/19] powerpc/8xx: exception InstructionAccess does not exist on MPC8xx
From: Joakim Tjernlund @ 2014-08-29 13:56 UTC (permalink / raw)
To: Christophe Leroy; +Cc: scottwood, linuxppc-dev, linux-kernel, Paul Mackerras
In-Reply-To: <20140829091437.B3FE71ABD63@localhost.localdomain>
Christophe Leroy <christophe.leroy@c-s.fr> wrote on 2014/08/29 11:14:37:
>
> Exception InstructionAccess does not exist on MPC8xx. No need to branch
there from somewhere else.
> Handling can be done directly in InstructionTLBError Exception.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>
> ---
> arch/powerpc/kernel/head_8xx.S | 17 +++++++----------
> 1 files changed, 7 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/kernel/head_8xx.S
b/arch/powerpc/kernel/head_8xx.S
> index 3af6db1..fbe5d10 100644
> --- a/arch/powerpc/kernel/head_8xx.S
> +++ b/arch/powerpc/kernel/head_8xx.S
> @@ -234,15 +234,9 @@ DataAccess:
> EXC_XFER_LITE(0x300, handle_page_fault)
>
> /* Instruction access exception.
> - * This is "never generated" by the MPC8xx. We jump to it for other
> - * translation errors.
> + * This is "never generated" by the MPC8xx.
> */
> - . = 0x400
> -InstructionAccess:
> - EXCEPTION_PROLOG
> - mr r4,r12
> - mr r5,r9
> - EXC_XFER_LITE(0x400, handle_page_fault)
> + EXCEPTION(0x400, InstructionAccess, unknown_exception, EXC_XFER_STD)
>
> /* External interrupt */
> EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
> @@ -382,7 +376,7 @@ InstructionTLBMiss:
> #endif
> mfspr r10, SPRN_SPRG_SCRATCH2
> EXCEPTION_EPILOG_0
> - b InstructionAccess
> + b InstructionTLBError
>
> . = 0x1200
> DataStoreTLBMiss:
> @@ -477,7 +471,10 @@ DataStoreTLBMiss:
> */
> . = 0x1300
> InstructionTLBError:
> - b InstructionAccess
> + EXCEPTION_PROLOG
> + mr r4,r12
> + mr r5,r9
> + EXC_XFER_LITE(0x1300, handle_page_fault)
This changes trap nr from 0x400 to 0x1300 for InstuctionAccess which I
think bad as
Linux uses the trap nr in arch/powerpc/mm/fault.c
Same comment for patch 7
Jocke
^ permalink raw reply
* Re: [PATCH] powerpc: Check flat device tree version at boot
From: Rob Herring @ 2014-08-29 14:31 UTC (permalink / raw)
To: Grant Likely; +Cc: Rob Herring, linuxppc-dev
In-Reply-To: <CACxGe6u7xK13UEgjM_BWtmXoskgVtJbVSB_wR2LUnAFgfybGSw@mail.gmail.com>
On Fri, Aug 29, 2014 at 6:13 AM, Grant Likely <grant.likely@linaro.org> wrote:
> On 29 Aug 2014 02:56, "Michael Ellerman" <mpe@ellerman.id.au> wrote:
>>
>> On Thu, 2014-08-28 at 09:27 -0500, Rob Herring wrote:
>> > On Thu, Aug 28, 2014 at 3:40 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
>> > > In commit e6a6928c3ea1 "of/fdt: Convert FDT functions to use libfdt",
>> > > the kernel stopped supporting old flat device tree formats. The minimum
>> > > supported version is now 0x10.
>> >
>> > Ugg. Is that something which needs to be supported? Supporting it at
>> > this point would mean adding support to libfdt.
>>
>> Well it would have been nice to keep supporting v2, dropping it broke
>> kexec-tools for example. But it's done now, so we'll just deal with the
>> fallout.
>
> Umm, so we broke userspace? That's not okay. At the very least we
> should investigate how much work is needed to bring v2 support into
> libfdt, or up-rev the flat tree at runtime before we parse it.
Would up-reving work? kexec-tools is broken or booting a new kernel
with kexec is broken?
> We should be able to update it in-line. IIRC, the main difference
> between v2 and v0x10 is that only the leaf node name is encoded into
> the node instead of the full name. We can loop over the tree and
> truncate all the names while filling the unused bytes with FDT NOP
> tags. Should be simple. Something like the following:
There is also the name property in v1-v3. I'm guessing linux ignores
that already?
>
> fixup_old_device_tree(blob)
> {
> for (offset = fdt_next_node(blob, -1, &depth);
> offset >= 0 && depth >= 0 && !rc;
> offset = fdt_next_node(blob, offset, &depth)) {
> char *pathp = fdt_get_name(blob, offset, NULL);
> if (*pathp == '/') {
> char *leaf = kbasename(pathp);
> int len = strlen(pathp);
> int newlen = strlen(leaf);
> strcpy(pathp, leaf); /* copying in place, need
> to check make sure this code is safe */
> node->size = newlen /* fixme - this is just
> pseudocode */
> newlen = FDT_TAGALIGN(newlen);
> while (newlen < len) {
> *(pathp + newlen) = FDT_NOP;
> newlen = FDT_TAGALIGN(newlen+1);
> }
> }
> }
>
> }
>
> There's probable some more elegance that can be put into the above
> block, but you get the idea. That could be run in-place without
> copying the tree to another location, and it could possibly be done in
> the boot wrapper. Then we'd also be able to get rid of the v2
> compatibility code elsewhere in drivers/of/fdt.c because it would
> already be taken care of.
That's what got us into this problem. ;)
Rob
^ permalink raw reply
* Re: [PATCH v2 17/19] powerpc/8xx: set PTE bit 22 off TLBmiss
From: Joakim Tjernlund @ 2014-08-29 14:39 UTC (permalink / raw)
To: Christophe Leroy; +Cc: scottwood, linuxppc-dev, linux-kernel, Paul Mackerras
In-Reply-To: <20140829091440.6DAD91ABD66@localhost.localdomain>
Christophe Leroy <christophe.leroy@c-s.fr> wrote on 2014/08/29 11:14:40:
>
> No need to re-set this bit at each TLB miss. Let's set it in the PTE.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>
> ---
> arch/powerpc/include/asm/pgtable-ppc32.h | 21 +++++++++++++++++++++
> arch/powerpc/include/asm/pte-8xx.h | 7 +++++--
> arch/powerpc/kernel/head_8xx.S | 10 ++--------
> 3 files changed, 28 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h
b/arch/powerpc/include/asm/pgtable-ppc32.h
> index 47edde8..c261792 100644
> --- a/arch/powerpc/include/asm/pgtable-ppc32.h
> +++ b/arch/powerpc/include/asm/pgtable-ppc32.h
> @@ -172,6 +172,26 @@ static inline unsigned long pte_update(pte_t *p,
> #ifdef PTE_ATOMIC_UPDATES
> unsigned long old, tmp;
>
> +#ifdef CONFIG_PPC_8xx
> + unsigned long tmp2;
> +
> + __asm__ __volatile__("\
> +1: lwarx %0,0,%4\n\
> + andc %1,%0,%5\n\
> + or %1,%1,%6\n\
> + /* 0x200 == Extended encoding, bit 22 */ \
> + /* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */
\
> + rlwimi %1,%1,32-2,0x200\n /* get _PAGE_USER */ \
> + rlwinm %3,%1,32-1,0x200\n /* get _PAGE_RW */ \
> + or %1,%3,%1\n\
> + xori %1,%1,0x200\n"
> + PPC405_ERR77(0,%4)
Should above PPC405_XXXX really be there? This is 8xx only
> +" stwcx. %1,0,%4\n\
> + bne- 1b"
> + : "=&r" (old), "=&r" (tmp), "=m" (*p), "=&r" (tmp2)
> + : "r" (p), "r" (clr), "r" (set), "m" (*p)
> + : "cc" );
> +#else /* CONFIG_PPC_8xx */
> __asm__ __volatile__("\
> 1: lwarx %0,0,%3\n\
> andc %1,%0,%4\n\
> @@ -182,6 +202,7 @@ static inline unsigned long pte_update(pte_t *p,
> : "=&r" (old), "=&r" (tmp), "=m" (*p)
> : "r" (p), "r" (clr), "r" (set), "m" (*p)
> : "cc" );
> +#endif /* CONFIG_PPC_8xx */
> #else /* PTE_ATOMIC_UPDATES */
> unsigned long old = pte_val(*p);
> *p = __pte((old & ~clr) | set);
> diff --git a/arch/powerpc/include/asm/pte-8xx.h
b/arch/powerpc/include/asm/pte-8xx.h
> index d44826e..dede1e7 100644
> --- a/arch/powerpc/include/asm/pte-8xx.h
> +++ b/arch/powerpc/include/asm/pte-8xx.h
> @@ -48,19 +48,22 @@
> */
> #define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */
> #define _PAGE_USER 0x0800 /* msb PP bits */
> +/* set when neither _PAGE_USER nor _PAGE_RW are set */
> +#define _PAGE_KNLRO 0x0200
>
> #define _PMD_PRESENT 0x0001
> #define _PMD_BAD 0x0ff0
> #define _PMD_PAGE_MASK 0x000c
> #define _PMD_PAGE_8M 0x000c
>
> -#define _PTE_NONE_MASK _PAGE_ACCESSED
> +#define _PTE_NONE_MASK (_PAGE_ACCESSED | _PAGE_KNLRO)
_PAGE_ACCESSED can be removed from PTE_NONE_MASK as 8xx no longer cheets.
See 2.4 commit
https://git.kernel.org/cgit/linux/kernel/git/wtarreau/linux-2.4.git/commit/?id=82582b970d04ad4bcfaa9d3f9c3c256619fd889f
>
> /* Until my rework is finished, 8xx still needs atomic PTE updates */
> #define PTE_ATOMIC_UPDATES 1
>
> /* We need to add _PAGE_SHARED to kernel pages */
> -#define _PAGE_KERNEL_RO (_PAGE_SHARED)
> +#define _PAGE_KERNEL_RO (_PAGE_SHARED | _PAGE_KNLRO)
> +#define _PAGE_KERNEL_ROX (_PAGE_EXEC | _PAGE_KNLRO)
> #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
>
> #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/kernel/head_8xx.S
b/arch/powerpc/kernel/head_8xx.S
> index a7af26e..48d3de8 100644
> --- a/arch/powerpc/kernel/head_8xx.S
> +++ b/arch/powerpc/kernel/head_8xx.S
> @@ -445,14 +445,8 @@ DataStoreTLBMiss:
> and r11, r11, r10
> rlwimi r10, r11, 0, _PAGE_PRESENT
> #endif
> - /* Honour kernel RO, User NA */
> - /* 0x200 == Extended encoding, bit 22 */
> - rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
> - /* r11 = (r10 & _PAGE_RW) >> 1 */
> - rlwinm r11, r10, 32-1, 0x200
> - or r10, r11, r10
> - /* invert RW and 0x200 bits */
> - xori r10, r10, _PAGE_RW | 0x200
> + /* invert RW */
> + xori r10, r10, _PAGE_RW
>
> /* The Linux PTE won't go exactly into the MMU TLB.
> * Software indicator bits 22 and 28 must be clear.
> --
> 1.7.1
>
^ permalink raw reply
* Re: [PATCH v2 02/19] powerpc/8xx: Use SCRATCH0 and SCRATCH1 also for TLB handlers
From: Joakim Tjernlund @ 2014-08-29 15:06 UTC (permalink / raw)
To: Christophe Leroy; +Cc: scottwood, linuxppc-dev, linux-kernel, Paul Mackerras
In-Reply-To: <20140829091437.832C41ABD65@localhost.localdomain>
Christophe Leroy <christophe.leroy@c-s.fr> wrote on 2014/08/29 11:14:37:
>
> SCRATCH0 and SCRATCH1 are only used in Exceptions prologs where no other
> exception can happen. There is therefore no need to preserve them
accross
> TLB handlers, we can use them there as in other exceptions. One of the
> advantages is that they do not suffer CPU6 errata unlike M_TW register.
Really nice! Some comments below
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>
> ---
> arch/powerpc/kernel/head_8xx.S | 104
++++++++++++----------------------
> 1 files changed, 36 insertions(+), 68 deletions(-)
>
> diff --git a/arch/powerpc/kernel/head_8xx.S
b/arch/powerpc/kernel/head_8xx.S
> index 1329c5a..3af6db1 100644
> --- a/arch/powerpc/kernel/head_8xx.S
> +++ b/arch/powerpc/kernel/head_8xx.S
> @@ -104,12 +104,15 @@ turn_on_mmu:
> * task's thread_struct.
> */
> #define EXCEPTION_PROLOG \
> - mtspr SPRN_SPRG_SCRATCH0,r10; \
> - mtspr SPRN_SPRG_SCRATCH1,r11; \
> - mfcr r10; \
> + EXCEPTION_PROLOG_0; \
> EXCEPTION_PROLOG_1; \
> EXCEPTION_PROLOG_2
>
> +#define EXCEPTION_PROLOG_0 \
> + mtspr SPRN_SPRG_SCRATCH0,r10; \
> + mtspr SPRN_SPRG_SCRATCH1,r11; \
> + mfcr r10
> +
> #define EXCEPTION_PROLOG_1 \
> mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
> andi. r11,r11,MSR_PR; \
> @@ -145,6 +148,14 @@ turn_on_mmu:
> SAVE_2GPRS(7, r11)
>
> /*
> + * Exception exit code.
> + */
> +#define EXCEPTION_EPILOG_0 \
> + mtcr r10; \
> + mfspr r10,SPRN_SPRG_SCRATCH0; \
> + mfspr r11,SPRN_SPRG_SCRATCH1
> +
> +/*
> * Note: code which follows this uses cr0.eq (set if from kernel),
> * r11, r12 (SRR0), and r9 (SRR1).
> *
> @@ -293,16 +304,8 @@ InstructionTLBMiss:
> #ifdef CONFIG_8xx_CPU6
> stw r3, 8(r0)
Perhaps you can use SPRN_DAR to stash R3 now that it is free ?
Jocke
^ permalink raw reply
* Re: [PATCH v2 00/19] powerpc/8xx: Optimise MMU TLB handling and add support of 16k pages
From: Joakim Tjernlund @ 2014-08-29 15:21 UTC (permalink / raw)
To: Christophe Leroy; +Cc: scottwood, linuxppc-dev, linux-kernel, Paul Mackerras
In-Reply-To: <20140829091324.D71E61ABD63@localhost.localdomain>
Christophe Leroy <christophe.leroy@c-s.fr> wrote on 2014/08/29 11:13:24:
>
> This patchset:
> 1) provides several MMU TLB handling optimisation on MPC8xx.
> 2) adds support of 16k pages on MPC8xx.
> All changes have been successfully tested on a custom board equipped
with MPC885
>
> The two differences with first version of the patch are:
> 1) I removed the patch number 10, which was implementing a 16 bit
alignment of the
> PGDIR. It is not worth potentially wasting up to 64k of memory just for
removing one
> instruction (ori).
> 2) I managed to preserve r11 while calculating the level 2 address,
therefore
> no more need to save r11 into CR.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> Tested-by: Christophe Leroy <christophe.leroy@c-s.fr>
This looks good but I need to look harder, some minor critique
though(already sent)
As you are optimizing I think the impl.of powerpc/8xx: Invalidate non
present TLBs
in 2.4 is better than 3.x, compare:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/powerpc/mm/fault.c?id=5efab4a02c89c252fb4cce097aafde5f8208dbfe
with
https://git.kernel.org/cgit/linux/kernel/git/wtarreau/linux-2.4.git/commit/?id=da5c5609e86fb12061f2c05a6ddd80ffc46592b2
This will free the TLB before you jump to xxx_page_fault which might need
a TLB before invalidation
and it isolates this 8xx quirk in 8xx specific code.
Jocke
^ permalink raw reply
* Re: [PATCH v2 17/19] powerpc/8xx: set PTE bit 22 off TLBmiss
From: Scott Wood @ 2014-08-29 18:41 UTC (permalink / raw)
To: Christophe Leroy; +Cc: linuxppc-dev, Paul Mackerras, linux-kernel
In-Reply-To: <20140829091440.6DAD91ABD66@localhost.localdomain>
On Fri, 2014-08-29 at 11:14 +0200, Christophe Leroy wrote:
> No need to re-set this bit at each TLB miss. Let's set it in the PTE.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>
> ---
> arch/powerpc/include/asm/pgtable-ppc32.h | 21 +++++++++++++++++++++
> arch/powerpc/include/asm/pte-8xx.h | 7 +++++--
> arch/powerpc/kernel/head_8xx.S | 10 ++--------
> 3 files changed, 28 insertions(+), 10 deletions(-)
>
When you post a vN+1 please indicate below the --- what changed sinced
vN.
-Scott
> diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
> index 47edde8..c261792 100644
> --- a/arch/powerpc/include/asm/pgtable-ppc32.h
> +++ b/arch/powerpc/include/asm/pgtable-ppc32.h
> @@ -172,6 +172,26 @@ static inline unsigned long pte_update(pte_t *p,
> #ifdef PTE_ATOMIC_UPDATES
> unsigned long old, tmp;
>
> +#ifdef CONFIG_PPC_8xx
> + unsigned long tmp2;
> +
> + __asm__ __volatile__("\
> +1: lwarx %0,0,%4\n\
> + andc %1,%0,%5\n\
> + or %1,%1,%6\n\
> + /* 0x200 == Extended encoding, bit 22 */ \
> + /* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \
> + rlwimi %1,%1,32-2,0x200\n /* get _PAGE_USER */ \
> + rlwinm %3,%1,32-1,0x200\n /* get _PAGE_RW */ \
> + or %1,%3,%1\n\
> + xori %1,%1,0x200\n"
> + PPC405_ERR77(0,%4)
> +" stwcx. %1,0,%4\n\
> + bne- 1b"
> + : "=&r" (old), "=&r" (tmp), "=m" (*p), "=&r" (tmp2)
> + : "r" (p), "r" (clr), "r" (set), "m" (*p)
> + : "cc" );
> +#else /* CONFIG_PPC_8xx */
> __asm__ __volatile__("\
> 1: lwarx %0,0,%3\n\
> andc %1,%0,%4\n\
> @@ -182,6 +202,7 @@ static inline unsigned long pte_update(pte_t *p,
> : "=&r" (old), "=&r" (tmp), "=m" (*p)
> : "r" (p), "r" (clr), "r" (set), "m" (*p)
> : "cc" );
> +#endif /* CONFIG_PPC_8xx */
> #else /* PTE_ATOMIC_UPDATES */
> unsigned long old = pte_val(*p);
> *p = __pte((old & ~clr) | set);
> diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
> index d44826e..dede1e7 100644
> --- a/arch/powerpc/include/asm/pte-8xx.h
> +++ b/arch/powerpc/include/asm/pte-8xx.h
> @@ -48,19 +48,22 @@
> */
> #define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */
> #define _PAGE_USER 0x0800 /* msb PP bits */
> +/* set when neither _PAGE_USER nor _PAGE_RW are set */
> +#define _PAGE_KNLRO 0x0200
>
> #define _PMD_PRESENT 0x0001
> #define _PMD_BAD 0x0ff0
> #define _PMD_PAGE_MASK 0x000c
> #define _PMD_PAGE_8M 0x000c
>
> -#define _PTE_NONE_MASK _PAGE_ACCESSED
> +#define _PTE_NONE_MASK (_PAGE_ACCESSED | _PAGE_KNLRO)
>
> /* Until my rework is finished, 8xx still needs atomic PTE updates */
> #define PTE_ATOMIC_UPDATES 1
>
> /* We need to add _PAGE_SHARED to kernel pages */
> -#define _PAGE_KERNEL_RO (_PAGE_SHARED)
> +#define _PAGE_KERNEL_RO (_PAGE_SHARED | _PAGE_KNLRO)
> +#define _PAGE_KERNEL_ROX (_PAGE_EXEC | _PAGE_KNLRO)
> #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
>
> #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
> index a7af26e..48d3de8 100644
> --- a/arch/powerpc/kernel/head_8xx.S
> +++ b/arch/powerpc/kernel/head_8xx.S
> @@ -445,14 +445,8 @@ DataStoreTLBMiss:
> and r11, r11, r10
> rlwimi r10, r11, 0, _PAGE_PRESENT
> #endif
> - /* Honour kernel RO, User NA */
> - /* 0x200 == Extended encoding, bit 22 */
> - rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
> - /* r11 = (r10 & _PAGE_RW) >> 1 */
> - rlwinm r11, r10, 32-1, 0x200
> - or r10, r11, r10
> - /* invert RW and 0x200 bits */
> - xori r10, r10, _PAGE_RW | 0x200
> + /* invert RW */
> + xori r10, r10, _PAGE_RW
>
> /* The Linux PTE won't go exactly into the MMU TLB.
> * Software indicator bits 22 and 28 must be clear.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox