On Wed, 2016-05-11 at 17:03 +0200, Christophe Leroy wrote:
> Memory: 124428K/131072K available (3748K kernel code, 188K rwdata,
> 648K rodata, 508K init, 290K bss, 6644K reserved)
> Kernel virtual memory layout:
>   * 0xfffdf000..0xfffff000  : fixmap
>   * 0xfde00000..0xfe000000  : consistent mem
>   * 0xfddf6000..0xfde00000  : early ioremap
>   * 0xc9000000..0xfddf6000  : vmalloc & ioremap
> SLUB: HWalign=16, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> 
> Today, IMMR is mapped 1:1 at startup
> 
> Mapping IMMR 1:1 is just wrong because it may overlap with another
> area. On most mpc8xx boards it is OK as IMMR is set to 0xff000000
> but for instance on EP88xC board, IMMR is at 0xfa200000 which
> overlaps with VM ioremap area
> 
> This patch fixes the virtual address for remapping IMMR with the fixmap
> regardless of the value of IMMR.
> 
> The size of IMMR area is 256kbytes (CPM at offset 0, security engine
> at offset 128k) so a 512k page is enough
> 
> Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>
> ---
> v2: No change
> 
>  arch/powerpc/include/asm/fixmap.h |  7 +++++++
>  arch/powerpc/kernel/asm-offsets.c |  8 ++++++++
>  arch/powerpc/kernel/head_8xx.S    | 11 ++++++-----
>  arch/powerpc/mm/mmu_decl.h        |  7 +++++++
>  arch/powerpc/sysdev/cpm_common.c  | 15 ++++++++++++---
>  5 files changed, 40 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/fixmap.h
> b/arch/powerpc/include/asm/fixmap.h
> index 90f604b..4508b32 100644
> --- a/arch/powerpc/include/asm/fixmap.h
> +++ b/arch/powerpc/include/asm/fixmap.h
> @@ -51,6 +51,13 @@ enum fixed_addresses {
>       FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel
> mappings */
>       FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
>  #endif
> +#ifdef CONFIG_PPC_8xx
> +     /* For IMMR we need an aligned 512K area */
> +#define FIX_IMMR_SIZE        (512 * 1024 / PAGE_SIZE)
> +     FIX_IMMR_START,
> +     FIX_IMMR_BASE = __ALIGN_MASK(FIX_IMMR_START, FIX_IMMR_SIZE - 1) - 1 +
> +
> +                    FIX_IMMR_SIZE,
> +#endif

What happens if FIX_IMMR_START is, for example, 0x100?  Then
"__ALIGN_MASK(FIX_IMMR_START, FIX_IMMR_SIZE - 1) - 1" would be 0xff -- you've
gone backwards.  FIX_IMMR_BASE would be 0x17f, translating to an address of
0xffe80000.  IMMR would end at 0xfff00000.  The kmap range would begin at
0xffeff000 and you'd have an overlap.

I think what you want is:
        FIX_IMMR_BASE = (FIX_IMMR_START & ~(FIX_IMMR_SIZE - 1)) + 
                        FIX_IMMR_SIZE - 1,


>       /* FIX_PCIE_MCFG, */
>       __end_of_fixed_addresses
>  };
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm
> -offsets.c
> index 9ea0955..2652233 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -68,6 +68,10 @@
>  #include "../mm/mmu_decl.h"
>  #endif
>  
> +#ifdef CONFIG_PPC_8xx
> +#include <asm/fixmap.h>
> +#endif
> +
>  int main(void)
>  {
>       DEFINE(THREAD, offsetof(struct task_struct, thread));
> @@ -783,5 +787,9 @@ int main(void)
>  
>       DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER);
>  
> +#ifdef CONFIG_PPC_8xx
> +     DEFINE(VIRT_IMMR_BASE, __fix_to_virt(FIX_IMMR_BASE));
> +#endif
> +
>       return 0;
>  }
> diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
> index 80c6947..378a185 100644
> --- a/arch/powerpc/kernel/head_8xx.S
> +++ b/arch/powerpc/kernel/head_8xx.S
> @@ -30,6 +30,7 @@
>  #include <asm/ppc_asm.h>
>  #include <asm/asm-offsets.h>
>  #include <asm/ptrace.h>
> +#include <asm/fixmap.h>
>  
>  /* Macro to make the code more readable. */
>  #ifdef CONFIG_8xx_CPU6
> @@ -763,7 +764,7 @@ start_here:
>   * virtual to physical.  Also, set the cache mode since that is defined
>   * by TLB entries and perform any additional mapping (like of the IMMR).
>   * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
> - * 24 Mbytes of data, and the 8M IMMR space.  Anything not covered by
> + * 24 Mbytes of data, and the 512k IMMR space.  Anything not covered by
>   * these mappings is mapped by page tables.
>   */
>  initial_mmu:
> @@ -812,7 +813,7 @@ initial_mmu:
>       ori     r8, r8, MD_APG_INIT@l
>       mtspr   SPRN_MD_AP, r8
>  
> -     /* Map another 8 MByte at the IMMR to get the processor
> +     /* Map a 512k page for the IMMR to get the processor
>        * internal registers (among other things).
>        */
>  #ifdef CONFIG_PIN_TLB
> @@ -820,12 +821,12 @@ initial_mmu:
>       mtspr   SPRN_MD_CTR, r10
>  #endif
>       mfspr   r9, 638                 /* Get current IMMR */
> -     andis.  r9, r9, 0xff80          /* Get 8Mbyte boundary
> */
> +     andis.  r9, r9, 0xfff8          /* Get 512 kbytes
> boundary */
>  
> -     mr      r8, r9                  /* Create vaddr for TLB */
> +     lis     r8, VIRT_IMMR_BASE@h    /* Create vaddr for TLB */
>       ori     r8, r8, MD_EVALID       /* Mark it valid */
>       mtspr   SPRN_MD_EPN, r8
> -     li      r8, MD_PS8MEG           /* Set 8M byte page */
> +     li      r8, MD_PS512K | MD_GUARDED      /* Set 512k byte page
> */
>       ori     r8, r8, MD_SVALID       /* Make it valid */
>       mtspr   SPRN_MD_TWC, r8
>       mr      r8, r9                  /* Create paddr for TLB */
> diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
> index 6af6532..a41fab9 100644
> --- a/arch/powerpc/mm/mmu_decl.h
> +++ b/arch/powerpc/mm/mmu_decl.h
> @@ -106,6 +106,13 @@ struct hash_pte;
>  extern struct hash_pte *Hash, *Hash_end;
>  extern unsigned long Hash_size, Hash_mask;
>  
> +#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
> +#ifdef CONFIG_PPC_8xx
> +#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
> +#else
> +#define VIRT_IMMR_BASE PHYS_IMMR_BASE
> +#endif

Where could that definition of PHYS_IMMR_BASE possibly be used other than 8xx?
 82xx, 83xx, etc. don't have SPRN_IMMR.

Can you move this into mmu-8xx.h?

> #ifdef CONFIG_PPC_EARLY_DEBUG_CPM
> -static u32 __iomem *cpm_udbg_txdesc =
> -     (u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR;
> +static u32 __iomem *cpm_udbg_txdesc;
>  
>  static void udbg_putc_cpm(char c)
>  {
> -     u8 __iomem *txbuf = (u8 __iomem __force
> *)in_be32(&cpm_udbg_txdesc[1]);
> +     static u8 __iomem *txbuf;
> +
> +     if (unlikely(txbuf == NULL))
> +             txbuf = (u8 __iomem __force *)
> +                      (in_be32(&cpm_udbg_txdesc[1]) - PHYS_IMMR_BASE +
> +                       VIRT_IMMR_BASE);

You've just broken udbg on 82xx.

Also, please don't use unlikely or other optimizations that make the code
harder to read (such as setting txbuf only if it's NULL) in non-performance
-critical code.
 
>       if (c == '\n')
>               udbg_putc_cpm('\r');
> @@ -56,6 +61,10 @@ static void udbg_putc_cpm(char c)
>  
>  void __init udbg_init_cpm(void)
>  {
> +     cpm_udbg_txdesc = (u32 __iomem __force *)
> +                       (CONFIG_PPC_EARLY_DEBUG_CPM_ADDR - PHYS_IMMR_BASE
> +
> +                        VIRT_IMMR_BASE);
> +
>       if (cpm_udbg_txdesc) {

If there's an init function why are you doing init-on-first-use in
udbg_putc_cpm()?

-Scott

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to