busdma_machdep.c with more than 512M memory

Neel Natu neelnatu at gmail.com
Fri Sep 10 05:52:41 UTC 2010


Hi JC,

On Mon, Sep 6, 2010 at 12:38 AM, Jayachandran C.
<c.jayachandran at gmail.com> wrote:
> On Mon, Sep 6, 2010 at 1:04 PM, Jayachandran C.
> <c.jayachandran at gmail.com> wrote:
>> On Wed, Sep 1, 2010 at 12:37 PM, Jayachandran C.
>> <c.jayachandran at gmail.com> wrote:
>>> I was looking at a few crashes I see with PCI drivers, and I think it
>>> is caused by an issue in busdma_machdep.c where physical address is
>>> directly converted using MIPS_PHYS_TO_KSEG1. I have not looked at it
>>> in detail, but it looks obviously wrong.
>>>
>>> Any suggestions on how to fix thiis is welcome, it probably needs an
>>> uncached TLB entry. On 64bit we could use XKPHYS uncached.
>>>
>>>
>>> ---
>>>  632         if (newmap->flags & DMAMAP_UNCACHEABLE) {
>>>  633                 void *tmpaddr = (void *)*vaddr;
>>>  634
>>>  635                 if (tmpaddr) {
>>>  636                         tmpaddr = (void
>>> *)MIPS_PHYS_TO_KSEG1(vtophys(tmpaddr));
>>>  637                         newmap->origbuffer = *vaddr;
>>>  638                         newmap->allocbuffer = tmpaddr;
>>>  639                         mips_dcache_wbinv_range((vm_offset_t)*vaddr,
>>>  640                             dmat->maxsize);
>>>  641                         *vaddr = tmpaddr;
>>>  642                 }
>>> ---
>>> 1361                 bpage->busaddr = pmap_kextract(bpage->vaddr);
>>> 1362                 bpage->vaddr_nocache =
>>> 1363                     (vm_offset_t)MIPS_PHYS_TO_KSEG1(bpage->busaddr);
>>> 1364                 mtx_lock(&bounce_lock);
>>
>> Based on Juli's suggestion, I have a patch (attached) to switch the
>> calls to pmap_mapdev/pmap_unmapdev.
>>
>> Seems to work for me now, please review.
>
> That was an older version of the patch, here is the correct version.
>

This assumes that pmap_mapdev() always returns an uncached mapping
which is true for n64 kernels but not for o32 kernels with memory
beyond 512MB.

Any objections if I commit the following patch that makes
pmap_mapdev() always return an uncached mapping.

Index: sys/mips/mips/pmap.c
===================================================================
--- sys/mips/mips/pmap.c	(revision 212404)
+++ sys/mips/mips/pmap.c	(working copy)
@@ -828,8 +828,8 @@
 /*
  * add a wired page to the kva
  */
- /* PMAP_INLINE */ void
-pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+static void
+pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int attr)
 {
 	pt_entry_t *pte;
 	pt_entry_t opte, npte;
@@ -837,13 +837,8 @@
 #ifdef PMAP_DEBUG
 	printf("pmap_kenter:  va: %p -> pa: %p\n", (void *)va, (void *)pa);
 #endif
-	npte = TLBLO_PA_TO_PFN(pa) | PTE_D | PTE_V | PTE_G | PTE_W;
+	npte = TLBLO_PA_TO_PFN(pa) | PTE_D | PTE_V | PTE_G | PTE_W | attr;

-	if (is_cacheable_mem(pa))
-		npte |= PTE_C_CACHE;
-	else
-		npte |= PTE_C_UNCACHED;
-
 	pte = pmap_pte(kernel_pmap, va);
 	opte = *pte;
 	*pte = npte;
@@ -851,6 +846,19 @@
 		pmap_update_page(kernel_pmap, va, npte);
 }

+void
+pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+{
+	int attr;
+
+	if (is_cacheable_mem(pa))
+		attr = PTE_C_CACHE;
+	else
+		attr = PTE_C_UNCACHED;
+
+	pmap_kenter_attr(va, pa, attr);
+}
+
 /*
  * remove a page from the kernel pagetables
  */
@@ -2863,7 +2871,7 @@
 			panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
 		pa = trunc_page(pa);
 		for (tmpva = va; size > 0;) {
-			pmap_kenter(tmpva, pa);
+			pmap_kenter_attr(tmpva, pa, PTE_C_UNCACHED);
 			size -= PAGE_SIZE;
 			tmpva += PAGE_SIZE;
 			pa += PAGE_SIZE;

best
Neel

> Thanks,
> JC.
>


More information about the freebsd-mips mailing list