From e98f36e86bdfbeb1728ab0de4f2be367d6283963 Mon Sep 17 00:00:00 2001 From: Roy Pledge Date: Tue, 14 Jul 2015 17:22:02 -0400 Subject: fsl_usdpaa: Remove TLB entries when unmapping memory TLB1 entries must be removed when unmapping a DMA map from a process so they don't point to the wrong physical memory if a new map reuses the same virtual address Signed-off-by: Roy Pledge diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index e52e121..360a0ce 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c @@ -147,6 +147,18 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys, loadcam_entry(index); } +void cleartlbcam(unsigned long virt, unsigned int pid) +{ + int i = 0; + for (i = 0; i < NUM_TLBCAMS; i++) { + if (tlbcam_addrs[i].start == virt) { + TLBCAM[i].MAS1 = 0; + loadcam_entry(i); + return; + } + } +} + unsigned long calc_cam_sz(unsigned long ram, unsigned long virt, phys_addr_t phys) { diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index dbbba8d..5880a74 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -94,6 +94,8 @@ extern void _tlbia(void); void settlbcam(int index, unsigned long virt, phys_addr_t phys, unsigned long size, unsigned long flags, unsigned int pid); +void cleartlbcam(unsigned long virt, unsigned int pid); + #ifdef CONFIG_PPC32 extern void mapin_ram(void); diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa.c b/drivers/staging/fsl_qbman/fsl_usdpaa.c index 55223cd..0c54657 100644 --- a/drivers/staging/fsl_qbman/fsl_usdpaa.c +++ b/drivers/staging/fsl_qbman/fsl_usdpaa.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Physical address range of the memory reservation, exported for mm/mem.c */ static u64 phys_start; @@ -1117,6 +1118,7 @@ static long ioctl_dma_unmap(struct ctx *ctx, void __user *arg) struct mem_fragment *current_frag; size_t sz; unsigned long base; + unsigned long vaddr; down_write(¤t->mm->mmap_sem); vma = find_vma(current->mm, (unsigned long)arg); @@ -1150,9 +1152,19 @@ map_match: } current_frag = map->root_frag; + vaddr = (unsigned long) map->virt_addr; for (i = 0; i < map->frag_count; i++) { DPA_ASSERT(current_frag->refs > 0); --current_frag->refs; + /* + * Make sure we invalidate the TLB entry for + * this fragment, otherwise a remap of a different + * page to this vaddr would give acces to an + * incorrect piece of memory + */ + cleartlbcam(vaddr, mfspr(SPRN_PID)); + + vaddr += current_frag->len; current_frag = list_entry(current_frag->list.prev, struct mem_fragment, list); } -- cgit v0.10.2