Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Jul 2009 14:57:32 +0200
From:      Michal Hajduk <mih@semihalf.com>
To:        Mark Tinguely <tinguely@casselton.net>
Cc:        freebsd-arm@freebsd.org
Subject:   Re: pmap problem in FreeBSD current - PS
Message-ID:  <4A5B2F3C.4030501@semihalf.com>
In-Reply-To: <4A5AF2DA.9050101@semihalf.com>
References:  <200907101454.n6AEs7nJ087492@casselton.net> <4A5AF2DA.9050101@semihalf.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Michal Hajduk wrote:
> Hi Mark,
>
> I've corrected busdma_machdep instead of adding this PVF_REF flag to arm
> pmap code and it works good.
> My patch:
> ===========================================================
> diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
> index a8b2de9..b55a714 100644
> --- a/sys/arm/arm/busdma_machdep.c
> +++ b/sys/arm/arm/busdma_machdep.c
> ....
I've found another problem in busdma_machdep.c in function 
bus_dmamem_alloc.
After write-back invalidate operation there is no tlb flush.
Below there is complete patch:

============================================================
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index a8b2de9..9562615 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -631,10 +631,11 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, 
int flags,
((vm_offset_t)*vaddr & PAGE_MASK));
newmap->origbuffer = *vaddr;
newmap->allocbuffer = tmpaddr;
- cpu_idcache_wbinv_range((vm_offset_t)*vaddr,
- dmat->maxsize);
- cpu_l2cache_wbinv_range((vm_offset_t)*vaddr,
- dmat->maxsize);
+ cpu_dcache_wbinv_range((vm_offset_t)*vaddr &
+ ~PAGE_MASK, PAGE_SIZE);
+ cpu_l2cache_wbinv_range((vm_offset_t)*vaddr &
+ ~PAGE_MASK, PAGE_SIZE);
+ cpu_tlb_flushID_SE((vm_offset_t)*vaddr);
*vaddr = tmpaddr;
} else
newmap->origbuffer = newmap->allocbuffer = NULL;

============================================================

> I've also checked your patch and it didn't help (I had a panic)
> ...
> uhub0: 1 port with 1 removable, self powered
> Root mount waiting for: usbus0
> panic: blockable sleep lock (sleep mutex) vm page queue mutex @ 
> /home/mih/git/marvell-current/sys/arm/arm/pmap.c:1947
> KDB: enter: panic
> [thread pid 15 tid 100028 ]
> Stopped at $d: ldrb r15, [r15, r15, ror r15]!
>
> Many thanks,
> Michał Hajduk
>
Can we move vm_page_unlock_queues() (line 1693) and vm_page_lock_queues to
pmap_get_pv_entry() ? Is it added only because of pagedaemon_wakeup()?

If this is correct, I've prepared a patch:
===========================================================
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index 3cdab65..b4ffbbf 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -1690,10 +1690,8 @@ pmap_enter_pv(struct vm_page *pg, struct pv_entry 
*pve, pmap_t pm,
TAILQ_INSERT_HEAD(&pm->pm_pvlist, pve, pv_plist);
if ((km = PMAP_OWNED(pmap_kernel())))
PMAP_UNLOCK(pmap_kernel());
- vm_page_unlock_queues();
if ((pve = pmap_get_pv_entry()) == NULL)
panic("pmap_kenter_internal: no pv entries");
- vm_page_lock_queues();
if (km)
PMAP_LOCK(pmap_kernel());
}
@@ -2904,10 +2902,8 @@ pmap_kenter_internal(vm_offset_t va, vm_offset_t 
pa, int flags)
vm_page_lock_queues();
if (!TAILQ_EMPTY(&m->md.pv_list) || m->md.pv_kva) {
/* release vm_page lock for pv_entry UMA */
- vm_page_unlock_queues();
if ((pve = pmap_get_pv_entry()) == NULL)
panic("pmap_kenter_internal: no pv entries");
- vm_page_lock_queues();
PMAP_LOCK(pmap_kernel());
pmap_enter_pv(m, pve, pmap_kernel(), va,
PVF_WRITE | PVF_UNMAN);
@@ -2984,8 +2980,8 @@ pmap_kremove(vm_offset_t va)
pmap_free_pv_entry(pve);
PMAP_UNLOCK(pmap_kernel());
vm_page_unlock_queues();
- cpu_dcache_wbinv_range(va, PAGE_SIZE);
- cpu_l2cache_wbinv_range(va, PAGE_SIZE);
+ cpu_dcache_wbinv_range(va & ~PAGE_MASK, PAGE_SIZE);
+ cpu_l2cache_wbinv_range(va & ~PAGE_MASK, PAGE_SIZE);
cpu_tlb_flushD_SE(va);
cpu_cpwait();
*pte = 0;
@@ -3935,8 +3931,11 @@ pmap_get_pv_entry(void)
pv_entry_t ret_value;
pv_entry_count++;
- if (pv_entry_count > pv_entry_high_water)
+ if (pv_entry_count > pv_entry_high_water) {
+ vm_page_unlock_queues();
pagedaemon_wakeup();
+ vm_page_lock_queues();
+ }
ret_value = uma_zalloc(pvzone, M_NOWAIT);
return ret_value;
}
==========================================================

With this patch I didn't observe LORs (as well as with your + mine patch).

Thanks for your help.

Best regards,
Michał Hajduk



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4A5B2F3C.4030501>