Date: Wed, 03 Nov 2010 11:08:39 -0500 From: Mark Tinguely <marktinguely@gmail.com> To: Olivier Houchard <cognet@FreeBSD.ORG> Cc: Mark Tinguely <tinguely@casselton.net>, freebsd-arm@FreeBSD.ORG Subject: (for archive) Re: Performance of SheevaPlug on 8-stable Message-ID: <4CD18907.1080209@gmail.com> In-Reply-To: <20100322150633.GA18277@ci0.org> References: <4B951CE2.6040507@semihalf.com> <201003221455.o2MEt4V5068925@casselton.net> <20100322150633.GA18277@ci0.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Olivier Houchard wrote: > On Mon, Mar 22, 2010 at 09:55:04AM -0500, Mark Tinguely wrote: > >> On Mon, 08 Mar 2010 16:50:58, Grzegorz Bernacki said: >> >> >>> This is probably caused by mechanism which turns of cache for shared pages. >>> When I add applied following path: >>> >>> diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c >>> index 390dc3c..d17c0cc 100644 >>> --- a/sys/arm/arm/pmap.c >>> +++ b/sys/arm/arm/pmap.c >>> @@ -1401,6 +1401,8 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va) >>> */ >>> >>> TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) { >>> + if (pv->pv_flags & PVF_EXEC) >>> + return; >>> /* generate a count of the pv_entry uses */ >>> if (pv->pv_flags & PVF_WRITE) { >>> if (pv->pv_pmap == pmap_kernel()) >>> >>> execution time of 'test' program is: >>> mv78100-4# time ./test >>> 5.000u 0.000s 0:05.40 99.8% 40+1324k 0+0io 0pf+0w >>> >>> and without this path is: >>> mv78100-4# time ./test >>> 295.000u 0.000s 4:56.01 99.7% 40+1322k 0+0io 0pf+0w >>> >>> >>> I think we need to handle executable pages in different way. >>> >>> grzesiek >>> >> Good going Oliver and thank-you on the pmap_enter_pv kernel map patch Revision >> 205425. >> >> Last week, before this patch, Maks Verver was so kind to put some statements >> in the VM (vm_page_free_toq()) for the SheevaPlug because I could not cause >> these paths with the Gumstix emulator. Maks, could you add to >> vm_phys_free_pages(): >> >> if (m->md.pv_kva) >> + { >> + printf("vm_phys_free_pages: md.pv_kva 0x%08x\n", m->md.pv_kva); >> m->md.pv_kva = 0; >> + } >> >> Even on the Gumstix emulator with the current patch, pmap_fix_cache() still >> has many executable pages that have both a kernel and user pv_entry. Looks >> like something like the above patch is still needed. >> >> > > I added a few printf and saw the same thing, however isn't assuming we > shouldn't modify the cache settings if the page is executable a bit dangerous ? > Or did I misread your patch ? > > Olivier > > I am cleaning up my old files. I thought I would put some numbers to this old thread into the archive in case this comes up again. Warning: The bus dma sync code for VIVT caches will only perform cache sync operations on the calling virtual address. It works correctly because the I/O request maps the page to a KVA and uses this address to perform the I/O. If the page is becomes shared when mapped to the KVA, then pmap_fix_cache routine cleans out the cache for every current share mapping and disables the cache on the page table entry. We are talking about NOT performing the cache operations on a shared executable. I think this will not be a problem for reading an executable page for the follow reasons: 0) I/O may cause a context change and flush the caches anyway. (very weak reason). 1) We should not be changing the contents of the executable file while the program is active without performing caches operations. 2) The executable page has been previously accessed and leaving part of the executable contents in the level 1 cache, then there should also be a RAM cached version in the buffer cache and we won't do DMA. --- I put some counters into pmap_fix_cache and found that: About 1% of the calls to pmap_fix_cache that has at least one executable mapping, also has one mapping that is not executable. In other words, the vast majority of executable pages have only executable mappings. About 89% of the pages that call pmap_fix_cache, also share the page with another pmap. It appears most are shared with another user pmap. About 4% of the pages that call pmap_fix_cache has at least one writable mapping. Of those pages that call pmap_fix_cache that have at least one writable mapping; About 80% of time, this is a user mapped write. IMO, user mapped writes must perform the cache operations. I came up with a modification that ignores the cache fixing only for the kernel mapped writes. I don't know if this too conservative to do any good, but it should be safer than ignoring the cache maintenance routines for all executable mappings. Index: arm/arm/pmap.c =================================================================== --- arm/arm/pmap.c (revision 214743) +++ arm/arm/pmap.c (working copy) @@ -1309,6 +1309,7 @@ int pmwc = 0; int writable = 0, kwritable = 0, uwritable = 0; int entries = 0, kentries = 0, uentries = 0; + int exec = 0, ncaches = 0; struct pv_entry *pv; mtx_assert(&vm_page_queue_mtx, MA_OWNED); @@ -1335,7 +1336,19 @@ uentries++; entries++; } + if (pv->pv_flags & PVF_EXEC) + exec++; + if (pv->pv_flags & PVF_NC) + ncaches++; } + /* don't cache if there is kernel mapping to otherwise + * read-only executable mappings. + */ + if (exec && (exec == entries + kentries) && + (writable == 0 || (writable == kwritable)) && + (ncaches == 0)) + return; + /* * check if the user duplicate mapping has * been removed. The conditions that I chose to bypass the cache operations are: (line 1) pure executable mapped page. (line 2) either not writable or only writable to the kernel map (cluster IO can make this >1) (line 3) this is not a request to turn caches back on. --Mark.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4CD18907.1080209>