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