Linux PARISC architecture development
 help / color / mirror / Atom feed
From: Helge Deller <deller@gmx.de>
To: John David Anglin <dave.anglin@bell.net>,
	linux-parisc@vger.kernel.org,
	James Bottomley <James.Bottomley@HansenPartnership.com>
Subject: Re: [PATCH][RFC] parisc: Optimize TLB flush functions based on timing results
Date: Fri, 29 May 2015 22:46:01 +0200	[thread overview]
Message-ID: <5568D009.5040101@gmx.de> (raw)
In-Reply-To: <BLU436-SMTP15817EC2AF63935C13FDE1197C90@phx.gbl>

On 29.05.2015 22:40, John David Anglin wrote:
> So, the threshold for the whole cache flush is roughly the size of the cache.

It's exactly the size of the cache, because of this line in arch/parisc/kernel/cache.c:
         if (parisc_cache_flush_threshold > cache_info.dc_size)
                 parisc_cache_flush_threshold = cache_info.dc_size;

So, if the calculated threshold is bigger than the cache, the code chooses
the cache size.

Helge


>
> On 2015-05-29 4:34 PM, Helge Deller wrote:
>> On 29.05.2015 22:13, Helge Deller wrote:
>>> This patch optimizes the TLB flushing functions flush_tlb_mm() and
>>> __flush_tlb_range() in a way that it adds timing routines to calculate
>>> the optimal size up to which flushes of small TLB ranges perform faster
>>> than when performing a full TLB shootdown.
>>>
>>> Here are some timing results for a rp5470 and J5000 machine:
>>>
>>> Machine: rp5470, PA8700, 875 MHz
>>> I-cache         : 768 KB
>>> D-cache         : 1536 KB (WB, direct mapped)
>>> ITLB entries    : 240
>>> DTLB entries    : 240 - shared with ITLB
>>>
>>> Whole cache flush 692084 cycles, flushing 13214592 bytes 5904392 cycles
>>> Setting cache flush threshold to 1512 kB.
>>> Whole TLB flush 40990 cycles, flushing 4096000 bytes 448989 cycles
>>> Setting TLB flush threshold to 368 kB.
>>>
>>> Machine: J5000/785, PA8500, 440MHz
>>> I-cache         : 512 KB
>>> D-cache         : 1024 KB (WB, direct mapped)
>>> ITLB entries    : 160
>>> DTLB entries    : 160 - shared with ITLB
>>>
>>> Whole cache flush 268605 cycles, flushing 13214592 bytes 1861037 cycles
>>> Setting cache flush threshold to 1024 kB
>>> Whole TLB flush 14131 cycles, flushing 13221888 bytes 769329 cycles
>>> Setting TLB flush threshold to 240 kB
>>
>>
>> One more machine:
>> Machine: C8000, PA8800, 2 CPUs each 900 MHz
>> I-cache         : 32768 KB
>> D-cache         : 32768 KB (WB, direct mapped)
>> ITLB entries    : 240
>> DTLB entries    : 240 - shared with ITLB
>>
>> Whole cache flush 4298354 cycles, flushing 13214592 bytes 1440513 cycles
>> Setting cache flush threshold to 32768 kB
>> Whole TLB flush 15625 cycles, flushing 13221888 bytes 781230 cycles
>> Setting TLB flush threshold to 260 kB
>>
>>
>>> Signed-off-by: Helge Deller <deller@gmx.de>
>>>
>>> diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h
>>> index 9d086a5..5e81e17 100644
>>> --- a/arch/parisc/include/asm/tlbflush.h
>>> +++ b/arch/parisc/include/asm/tlbflush.h
>>> @@ -24,40 +24,25 @@ extern void flush_tlb_all_local(void *);
>>>
>>>   #define smp_flush_tlb_all()    flush_tlb_all()
>>>
>>> -/*
>>> - * flush_tlb_mm()
>>> - *
>>> - * XXX This code is NOT valid for HP-UX compatibility processes,
>>> - * (although it will probably work 99% of the time). HP-UX
>>> - * processes are free to play with the space id's and save them
>>> - * over long periods of time, etc. so we have to preserve the
>>> - * space and just flush the entire tlb. We need to check the
>>> - * personality in order to do that, but the personality is not
>>> - * currently being set correctly.
>>> - *
>>> - * Of course, Linux processes could do the same thing, but
>>> - * we don't support that (and the compilers, dynamic linker,
>>> - * etc. do not do that).
>>> - */
>>> +int __flush_tlb_range(unsigned long sid,
>>> +    unsigned long start, unsigned long end);
>>> +
>>> +#define flush_tlb_range(vma, start, end) \
>>> +    __flush_tlb_range((vma)->vm_mm->context, start, end)
>>> +
>>> +#define flush_tlb_kernel_range(start, end) \
>>> +    __flush_tlb_range(0, start, end)
>>>
>>>   static inline void flush_tlb_mm(struct mm_struct *mm)
>>>   {
>>> -    BUG_ON(mm == &init_mm); /* Should never happen */
>>> -
>>> -#if 1 || defined(CONFIG_SMP)
>>> -    flush_tlb_all();
>>> -#else
>>> -    /* FIXME: currently broken, causing space id and protection ids
>>> -     *  to go out of sync, resulting in faults on userspace accesses.
>>> -     */
>>> -    if (mm) {
>>> -        if (mm->context != 0)
>>> -            free_sid(mm->context);
>>> -        mm->context = alloc_sid();
>>> -        if (mm == current->active_mm)
>>> -            load_context(mm->context);
>>> +    struct vm_area_struct *vma;
>>> +
>>> +    for (vma = mm->mmap; vma; vma = vma->vm_next) {
>>> +        /* exit loop if flush_tlb_all() was called. */
>>> +        if (unlikely(__flush_tlb_range(mm->context,
>>> +                vma->vm_start, vma->vm_end)))
>>> +            return;
>>>       }
>>> -#endif
>>>   }
>>>
>>>   static inline void flush_tlb_page(struct vm_area_struct *vma,
>>> @@ -76,11 +61,4 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
>>>       purge_tlb_end(flags);
>>>   }
>>>
>>> -void __flush_tlb_range(unsigned long sid,
>>> -    unsigned long start, unsigned long end);
>>> -
>>> -#define flush_tlb_range(vma,start,end) __flush_tlb_range((vma)->vm_mm->context,start,end)
>>> -
>>> -#define flush_tlb_kernel_range(start, end) __flush_tlb_range(0,start,end)
>>> -
>>>   #endif
>>> diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
>>> index f6448c7..4eac923 100644
>>> --- a/arch/parisc/kernel/cache.c
>>> +++ b/arch/parisc/kernel/cache.c
>>> @@ -342,12 +342,15 @@ EXPORT_SYMBOL(flush_data_cache_local);
>>>   EXPORT_SYMBOL(flush_kernel_icache_range_asm);
>>>
>>>   #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
>>> -int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
>>> +static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
>>> +
>>> +#define FLUSH_TLB_THRESHOLD (2*1024*1024) /* 2MB initial TLB threshold */
>>> +static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD;
>>>
>>>   void __init parisc_setup_cache_timing(void)
>>>   {
>>>       unsigned long rangetime, alltime;
>>> -    unsigned long size;
>>> +    unsigned long size, start;
>>>
>>>       alltime = mfctl(16);
>>>       flush_data_cache();
>>> @@ -364,14 +367,42 @@ void __init parisc_setup_cache_timing(void)
>>>       /* Racy, but if we see an intermediate value, it's ok too... */
>>>       parisc_cache_flush_threshold = size * alltime / rangetime;
>>>
>>> -    parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1);
>>> +    parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold);
>>>       if (!parisc_cache_flush_threshold)
>>>           parisc_cache_flush_threshold = FLUSH_THRESHOLD;
>>>
>>>       if (parisc_cache_flush_threshold > cache_info.dc_size)
>>>           parisc_cache_flush_threshold = cache_info.dc_size;
>>>
>>> -    printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
>>> +    printk(KERN_INFO "Setting cache flush threshold to %lu kB\n",
>>> +        parisc_cache_flush_threshold/1024);
>>> +
>>> +    /* calculate TLB flush threshold */
>>> +
>>> +    alltime = mfctl(16);
>>> +    flush_tlb_all();
>>> +    alltime = mfctl(16) - alltime;
>>> +
>>> +    size = PAGE_SIZE;
>>> +    start = (unsigned long) _text;
>>> +    rangetime = mfctl(16);
>>> +    while (start < (unsigned long) _end) {
>>> +        flush_tlb_kernel_range(start, start + PAGE_SIZE);
>>> +        start += PAGE_SIZE;
>>> +        size += PAGE_SIZE;
>>> +    }
>>> +    rangetime = mfctl(16) - rangetime;
>>> +
>>> +    printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n",
>>> +        alltime, size, rangetime);
>>> +
>>> +    parisc_tlb_flush_threshold = size * alltime / rangetime;
>>> +    parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold);
>>> +    if (!parisc_tlb_flush_threshold)
>>> +        parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD;
>>> +
>>> +    printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n",
>>> +        parisc_tlb_flush_threshold/1024);
>>>   }
>>>
>>>   extern void purge_kernel_dcache_page_asm(unsigned long);
>>> @@ -418,32 +449,39 @@ void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
>>>   }
>>>   EXPORT_SYMBOL(purge_tlb_entries);
>>>
>>> -void __flush_tlb_range(unsigned long sid, unsigned long start,
>>> +/* __flush_tlb_range()
>>> + *
>>> + * returns 1 if all TLBs were flushed.
>>> + */
>>> +int __flush_tlb_range(unsigned long sid, unsigned long start,
>>>                  unsigned long end)
>>>   {
>>> -    unsigned long npages;
>>> +    unsigned long size;
>>>
>>> -    npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
>>> -    if (npages >= 512)  /* 2MB of space: arbitrary, should be tuned */
>>> +    size = (end - start);
>>> +    if (size >= parisc_tlb_flush_threshold) {
>>>           flush_tlb_all();
>>> +        return 1;
>>> +    }
>>>       else {
>>>           unsigned long flags;
>>>
>>>           purge_tlb_start(flags);
>>>           mtsp(sid, 1);
>>>           if (split_tlb) {
>>> -              while (npages--) {
>>> +            while (start < end) {
>>>                   pdtlb(start);
>>>                   pitlb(start);
>>>                   start += PAGE_SIZE;
>>>               }
>>>           } else {
>>> -            while (npages--) {
>>> +            while (start < end) {
>>>                   pdtlb(start);
>>>                   start += PAGE_SIZE;
>>>               }
>>>           }
>>>           purge_tlb_end(flags);
>>> +        return 0;
>>>       }
>>>   }
>>>
>>>
>>
>>
>>
>
>


  reply	other threads:[~2015-05-29 20:46 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-29 20:13 [PATCH][RFC] parisc: Optimize TLB flush functions based on timing results Helge Deller
2015-05-29 20:34 ` Helge Deller
2015-05-29 20:40   ` John David Anglin
2015-05-29 20:46     ` Helge Deller [this message]
2015-07-01 21:18   ` [PATCH][RFC] parisc: Fix some PTE/TLB race conditions and optimize __flush_tlb_range " John David Anglin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5568D009.5040101@gmx.de \
    --to=deller@gmx.de \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=dave.anglin@bell.net \
    --cc=linux-parisc@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox