Hi, From: "ext Guzman Lugo, Fernando" <x0095840@xxxxxx> Subject: RE: [PATCH 1/4] [OMAPZOOM] DSPBRIDGE: Memory lock for DMM. Date: Fri, 27 Mar 2009 03:04:39 +0100 > > Hi, > I am resending this patch because the previous one has an error. > > > From 81c5b93ad42c40179c2b271f61814f0b4035440c Mon Sep 17 00:00:00 2001 > From: Hari Kanigeri <h-kanigeri2@xxxxxx> > Date: Thu, 26 Mar 2009 15:47:50 -0500 > Subject: [PATCH] DSPBRIDGE: Memory lock for DMM. > > Lock down the pages that are mapped to DSP virtual memory to prevent from > getting swapped out Hm....for this page swapping case, I think that handling this issue in kernel may cause more complexity and this can be avoided by "mlock()" for that buffer in userland? This looks more sipmpler? > > Signed-off-by: Hari Kanigeri <h-kanigeri2@xxxxxx> > --- > arch/arm/plat-omap/include/dspbridge/dbdefs.h | 3 + > drivers/dsp/bridge/hw/hw_mmu.h | 1 + > drivers/dsp/bridge/wmd/io_sm.c | 24 +++-- > drivers/dsp/bridge/wmd/tiomap3430.c | 133 +++++++++++++++++++++++- > 4 files changed, 144 insertions(+), 17 deletions(-) > > diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat-omap/include/dspbridge/dbdefs.h > index 7f5a2bf..9782693 > --- a/arch/arm/plat-omap/include/dspbridge/dbdefs.h > +++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h > @@ -571,6 +571,9 @@ bit 6 - MMU element size = 64bit (valid only for non mixed page entries) > > #define DSP_MAPVMALLOCADDR 0x00000080 > > +#define DSP_MAPDONOTLOCK 0x00000100 > + > + > #define GEM_CACHE_LINE_SIZE 128 > #define GEM_L1P_PREFETCH_SIZE 128 > > diff --git a/drivers/dsp/bridge/hw/hw_mmu.h b/drivers/dsp/bridge/hw/hw_mmu.h > index 065f0dd..b1e2458 > --- a/drivers/dsp/bridge/hw/hw_mmu.h > +++ b/drivers/dsp/bridge/hw/hw_mmu.h > @@ -51,6 +51,7 @@ struct HW_MMUMapAttrs_t { > enum HW_Endianism_t endianism; > enum HW_ElementSize_t elementSize; > enum HW_MMUMixedSize_t mixedSize; > + bool donotlockmpupage; > } ; > > extern HW_STATUS HW_MMU_Enable(const void __iomem *baseAddress); > diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c > index bd936eb..301bd72 100755 > --- a/drivers/dsp/bridge/wmd/io_sm.c > +++ b/drivers/dsp/bridge/wmd/io_sm.c > @@ -553,6 +553,8 @@ func_cont1: > mapAttrs = DSP_MAPLITTLEENDIAN; > mapAttrs |= DSP_MAPPHYSICALADDR; > mapAttrs |= DSP_MAPELEMSIZE32; > + mapAttrs |= DSP_MAPDONOTLOCK; > + > while (numBytes && DSP_SUCCEEDED(status)) { > /* To find the max. page size with which both PA & VA are > * aligned */ > @@ -690,18 +692,18 @@ func_cont: > mapAttrs = DSP_MAPLITTLEENDIAN; > mapAttrs |= DSP_MAPPHYSICALADDR; > mapAttrs |= DSP_MAPELEMSIZE32; > + mapAttrs |= DSP_MAPDONOTLOCK; > + > /* Map the L4 peripherals */ > - { > - i = 0; > - while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) { > - status = hIOMgr->pIntfFxns->pfnBrdMemMap > - (hIOMgr->hWmdContext, > - L4PeripheralTable[i].physAddr, > - L4PeripheralTable[i].dspVirtAddr, > - HW_PAGE_SIZE_4KB, mapAttrs); > - DBC_Assert(DSP_SUCCEEDED(status)); > - i++; > - } > + i = 0; > + while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) { > + status = hIOMgr->pIntfFxns->pfnBrdMemMap > + (hIOMgr->hWmdContext, L4PeripheralTable[i].physAddr, > + L4PeripheralTable[i].dspVirtAddr, HW_PAGE_SIZE_4KB, > + mapAttrs); > + if (DSP_FAILED(status)) > + break; > + i++; > } > > if (DSP_SUCCEEDED(status)) { > diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c > index 7f20574..1a97305 100755 > --- a/drivers/dsp/bridge/wmd/tiomap3430.c > +++ b/drivers/dsp/bridge/wmd/tiomap3430.c > @@ -28,6 +28,8 @@ > > /* ----------------------------------- Host OS */ > #include <dspbridge/host_os.h> > +#include <linux/mm.h> > +#include <linux/mmzone.h> > #include "../arch/arm/mach-omap2/prcm-regs.h" > #include "../arch/arm/mach-omap2/cm-regbits-34xx.h" > #include "../arch/arm/mach-omap2/ti-compat.h" > @@ -90,6 +92,7 @@ > #define MMU_LARGE_PAGE_MASK 0xFFFF0000 > #define MMU_SMALL_PAGE_MASK 0xFFFFF000 > #define PAGES_II_LVL_TABLE 512 > +#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) > > #define MMU_GFLUSH 0x60 > > @@ -1372,6 +1375,11 @@ static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext, > return DSP_EINVALIDARG; > } > } > + if (attrs & DSP_MAPDONOTLOCK) > + hwAttrs.donotlockmpupage = 1; > + else > + hwAttrs.donotlockmpupage = 0; > + > if (attrs & DSP_MAPVMALLOCADDR) { > status = MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr, > ulNumBytes, ulMapAttr); > @@ -1488,12 +1496,20 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext, > u32 remBytes; > u32 remBytesL2; > u32 vaCurr; > + struct page *pg; > DSP_STATUS status = DSP_SOK; > struct WMD_DEV_CONTEXT *pDevContext = hDevContext; > struct PgTableAttrs *pt = pDevContext->pPtAttrs; > + u32 pacount = 0; > + u32 *pPhysAddrPageTbl = NULL; > + u32 temp; > + u32 patemp = 0; > + u32 pAddr; > + u32 numof4KPages = 0; > > DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, " > "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes); > + pPhysAddrPageTbl = DMM_GetPhysicalAddrTable(); > vaCurr = ulVirtAddr; > remBytes = ulNumBytes; > remBytesL2 = 0; > @@ -1542,6 +1558,19 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext, > /* vaCurr aligned to pteSize? */ > if ((pteSize != 0) && (remBytesL2 >= pteSize) && > !(vaCurr & (pteSize - 1))) { > + /* Collect Physical addresses from VA */ > + pAddr = (pteVal & ~(pteSize - 1)); > + if (pteSize == HW_PAGE_SIZE_64KB) > + numof4KPages = 16; > + else > + numof4KPages = 1; > + temp = 0; > + while (temp++ < numof4KPages) { > + pPhysAddrPageTbl[pacount++] = > + pAddr; > + pAddr += HW_PAGE_SIZE_4KB; > + } > + > if (HW_MMU_PteClear(pteAddrL2, > vaCurr, pteSize) == RET_OK) { > status = DSP_SOK; > @@ -1602,6 +1631,20 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext, > * get flushed */ > EXIT_LOOP: > flush_all(pDevContext); > + temp = 0; > + while (temp < pacount) { > + patemp = pPhysAddrPageTbl[temp]; > + if (pfn_valid(__phys_to_pfn(patemp))) { > + pg = phys_to_page(patemp); > + if (page_count(pg) <= 0) > + printk(KERN_INFO "DSPBRIDGE:UNMAP function: " > + "COUNT 0 FOR PA 0x%x, size = 0x%x\n", > + patemp, ulNumBytes); > + SetPageDirty(pg); > + page_cache_release(pg); > + } > + temp++; > + } > DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x " > "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2); > DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, " > @@ -1633,11 +1676,20 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > u32 temp = 0; > u32 numUsrPgs; > struct task_struct *curr_task = current; > + struct vm_area_struct *vma; > + u32 write = 0; > + > > DBG_Trace(DBG_ENTER, "TIOMAP_VirtToPhysical: START:ulMpuAddr=%x, " > "ulNumBytes=%x\n", ulMpuAddr, ulNumBytes); > if (physicalAddrTable == NULL) > return DSP_EMEMORY; > + down_read(&mm->mmap_sem); > + vma = find_vma(mm, ulMpuAddr); > + up_read(&mm->mmap_sem); > + > + if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) > + write = 1; > while (ulNumBytes) { > DBG_Trace(DBG_LEVEL4, "TIOMAP_VirtToPhysical:Read the next PGD " > "and PMD entry\n"); > @@ -1660,7 +1712,7 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > * page tables > */ > numUsrPgs = get_user_pages(curr_task, mm, ulMpuAddr, 1, > - true, 0, NULL, NULL); > + write, 1, NULL, NULL); > up_read(&mm->mmap_sem); > /* Get the first level page table entry information */ > /* Read the pointer to first level page table entry */ > @@ -1704,7 +1756,7 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > * the page tables */ > if (numUsrPgs <= PAGES_II_LVL_TABLE) { > get_user_pages(curr_task, mm, > - ulMpuAddr, numUsrPgs, true, 0, > + ulMpuAddr, numUsrPgs, write, 1, > NULL, NULL); > DBG_Trace(DBG_LEVEL4, > "get_user_pages, numUsrPgs" > @@ -1712,7 +1764,7 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > } else { > get_user_pages(curr_task, mm, > ulMpuAddr, PAGES_II_LVL_TABLE, > - true, 0, NULL, NULL); > + write, 1, NULL, NULL); > DBG_Trace(DBG_LEVEL4, > "get_user_pages, numUsrPgs" > "= %d\n", PAGES_II_LVL_TABLE); > @@ -1737,7 +1789,12 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > pAddr = pteVal & MMU_LARGE_PAGE_MASK; > chunkSz = HW_PAGE_SIZE_64KB; > numEntries = 16; > - numof4KPages = 16; > + if (ulNumBytes >= HW_PAGE_SIZE_64KB) > + numof4KPages = 16; > + else { > + numof4KPages = ulNumBytes / > + HW_PAGE_SIZE_4KB; > + } > break; > case HW_PAGE_SIZE_4KB: > pAddr = pteVal & MMU_SMALL_PAGE_MASK; > @@ -1769,7 +1826,10 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > ulMpuAddr += chunkSz; > /* Update the number of bytes that > * are copied */ > - ulNumBytes -= chunkSz; > + if (chunkSz > ulNumBytes) > + ulNumBytes = 0; > + else > + ulNumBytes -= chunkSz; > DBG_Trace(DBG_LEVEL4, > "TIOMAP_VirtToPhysical: mpuCurr" > " = %x, pagesize = %x, " > @@ -1792,10 +1852,16 @@ static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr, > switch (pteSize) { > case HW_PAGE_SIZE_16MB: > pAddr = pteVal & MMU_SSECTION_ADDR_MASK; > + if (ulNumBytes >= HW_PAGE_SIZE_16MB) { > chunkSz = HW_PAGE_SIZE_16MB; > numEntries = 16; > numof4KPages = 4096; > - break; > + } else { > + chunkSz = HW_PAGE_SIZE_1MB; > + numEntries = 1; > + numof4KPages = 256; > + } > + break; > case HW_PAGE_SIZE_1MB: > pAddr = pteVal & MMU_SECTION_ADDR_MASK; > chunkSz = HW_PAGE_SIZE_1MB; > @@ -1909,9 +1975,64 @@ static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va, > u32 L2BaseVa = 0; > u32 L2BasePa = 0; > u32 L2PageNum = 0; > + u32 num4KEntries = 0; > + u32 temp = 0; > + struct page *pg; > + u32 patemp; > + > DSP_STATUS status = DSP_SOK; > DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, " > "size %x, attrs %x\n", pt, pa, va, size, attrs); > + /* Lock the MPU pages that are getting mapped if this > + * attribute is set */ > + if (attrs->donotlockmpupage == 0) { > + switch (size) { > + case HW_PAGE_SIZE_64KB: > + num4KEntries = 16; > + break; > + case HW_PAGE_SIZE_4KB: > + num4KEntries = 1; > + break; > + case HW_PAGE_SIZE_16MB: > + num4KEntries = 4096; > + break; > + case HW_PAGE_SIZE_1MB: > + num4KEntries = 256; > + break; > + default: > + return DSP_EFAIL; > + } > + patemp = pa; > + while (temp++ < num4KEntries) { > + /* FIXME: This is a hack to avoid getting pages for > + * video overlay */ > + if (pfn_valid(__phys_to_pfn(patemp))) { > + pg = phys_to_page(patemp); > + get_page(pg); > + } > + if (page_count(pg) <= 1) { > + printk(KERN_EMERG "DSPBRIDGE:MAP function: " > + "COUNT 0 FOR PA 0x%x\n", patemp); > + printk(KERN_EMERG "Bad page state" > + KERN_EMERG "in process '%s'\n" > + KERN_EMERG "page:%p flags:0x%0*lx " > + KERN_EMERG "mapping:%p mapcount:%d " > + KERN_EMERG "count:%d\n" > + KERN_EMERG "Trying to fix it up, but " > + KERN_EMERG "a reboot is needed\n" > + KERN_EMERG "Backtrace:\n", > + current->comm, pg, > + (int)(2*sizeof(unsigned long)), > + (unsigned long)pg->flags, pg->mapping, > + page_mapcount(pg), page_count(pg)); > + dump_stack(); > + BUG_ON(1); > + } > + > + patemp += HW_PAGE_SIZE_4KB; > + } > + } > + attrs->donotlockmpupage = 0; > L1BaseVa = pt->L1BaseVa; > pgTblVa = L1BaseVa; > if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) { > -- > 1.5.6.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html