From 0cc812d4faea6917c73b35e4b5e91780b18522ba Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Tue, 11 Nov 2014 21:14:56 -0600 Subject: powerpc/fsl: Force coherent memory on e500mc derivatives In CoreNet systems it is not allowed to mix M and non-M mappings to the same memory, and coherent DMA accesses are considered to be M mappings for this purpose. Ignoring this has been observed to cause hard lockups in non-SMP kernels on e6500. Furthermore, e6500 implements the LRAT (logical to real address table) which allows KVM guests to control the WIMGE bits. This means that KVM cannot force the M bit on the way it usually does, so the guest had better set it itself. Signed-off-by: Scott Wood Change-Id: I083bdc9dd7990d475b8ae48680a8e63012998e93 Reviewed-on: http://git.am.freescale.net:8181/24841 Tested-by: Review Code-CDREVIEW Reviewed-by: Mihai Caraman Reviewed-by: Matthew Weigel diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index 8d1569c..bdd531b 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h @@ -105,7 +105,8 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); * the processor might need it for DMA coherency. */ #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) -#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU) +#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU) || \ + defined(CONFIG_PPC_E500MC) #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) #else #define _PAGE_BASE (_PAGE_BASE_NC) diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index ed6ee71..ea9c605 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -1322,11 +1322,14 @@ skpinv: addi r6,r6,1 /* Increment */ sync isync -/* The mapping only needs to be cache-coherent on SMP */ -#ifdef CONFIG_SMP -#define M_IF_SMP MAS2_M +/* + * The mapping only needs to be cache-coherent on SMP, except on + * Freescale e500mc derivatives where it's also needed for coherent DMA. + */ +#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) +#define M_IF_NEEDED MAS2_M #else -#define M_IF_SMP 0 +#define M_IF_NEEDED 0 #endif /* 6. Setup KERNELBASE mapping in TLB[0] @@ -1341,7 +1344,7 @@ skpinv: addi r6,r6,1 /* Increment */ ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l mtspr SPRN_MAS1,r6 - LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET | M_IF_SMP) + LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET | M_IF_NEEDED) mtspr SPRN_MAS2,r6 rlwinm r5,r5,0,0,25 diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S index e988a40..464f8c1 100644 --- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S @@ -165,11 +165,14 @@ skpinv: addi r6,r6,1 /* Increment */ TLBSYNC #endif -/* The mapping only needs to be cache-coherent on SMP */ -#ifdef CONFIG_SMP -#define M_IF_SMP MAS2_M +/* + * The mapping only needs to be cache-coherent on SMP, except on + * Freescale e500mc derivatives where it's also needed for coherent DMA. + */ +#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) +#define M_IF_NEEDED MAS2_M #else -#define M_IF_SMP 0 +#define M_IF_NEEDED 0 #endif #if defined(ENTRY_MAPPING_BOOT_SETUP) @@ -180,8 +183,8 @@ skpinv: addi r6,r6,1 /* Increment */ lis r6,(MAS1_VALID|MAS1_IPROT)@h ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l mtspr SPRN_MAS1,r6 - lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h - ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l + lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@h + ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@l mtspr SPRN_MAS2,r6 #ifdef ENTRY_DEEPSLEEP_SETUP LOAD_REG_IMMEDIATE(r8, MEMORY_START) diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index 37cb697..e52e121 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c @@ -114,7 +114,7 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys, tsize = __ilog2(size) - 10; -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) if ((flags & _PAGE_NO_CACHE) == 0) flags |= _PAGE_COHERENT; #endif -- cgit v0.10.2