linux-mips
[Top] [All Lists]

Re: [RFC] Flush huge TLB

To: David Daney <david.daney@cavium.com>
Subject: Re: [RFC] Flush huge TLB
From: Hillf Danton <dhillf@gmail.com>
Date: Fri, 14 Oct 2011 21:09:37 +0800
Cc: Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org, "Jayachandran C." <jayachandranc@netlogicmicro.com>
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=wT6pf7V5Z7C+x+EMT2UVHGikKdnfQBqGA1EWx9u4LGU=; b=FiDCEsnCIzhhHeOLsXqMJljwdF7uA5ePJ5atsCZZAP8GwHLYh2k32FkfA4xZkQIY49 ZwhYQ0WFqDWs7DTYq/UBcSFNEB8RTL2+qp87Rt5ckxCuU1YdWO7tJ5mD/0t1M6NDdAuc +M5CrOhSB1DbubQbdEcQiI3LWYS4I94vYh9TA=
In-reply-to: <4E932897.9050301@cavium.com>
References: <CAJd=RBBPd6frOA5zCg5juHuWdZ6wHzmOhhufgGhUCOc=rkNEzA@mail.gmail.com> <4E932897.9050301@cavium.com>
Sender: linux-mips-bounce@linux-mips.org
On Tue, Oct 11, 2011 at 1:17 AM, David Daney <david.daney@cavium.com> wrote:
> On 10/09/2011 05:53 AM, Hillf Danton wrote:
>>
>> When flushing TLB, if @vma is backed by huge page, huge TLB should be
>> flushed,
>> due to the fact that huge page is defined to be far from normal page, and
>> the
>> flushing is shorten a bit.
>>
>> Any comment is welcome.
>>
>
> Note that the current implementation works, but is not optimal.
>
>> Thanks
>>
>> Signed-off-by: Hillf Danton<dhillf@gmail.com>
>> ---
>>
>> --- a/arch/mips/mm/tlb-r4k.c    Mon May 30 21:17:04 2011
>> +++ b/arch/mips/mm/tlb-r4k.c    Sun Oct  9 20:50:06 2011
>> @@ -120,22 +120,35 @@ void local_flush_tlb_range(struct vm_are
>>
>>        if (cpu_context(cpu, mm) != 0) {
>>                unsigned long size, flags;
>> +               int huge = is_vm_hugetlb_page(vma);
>>
>>                ENTER_CRITICAL(flags);
>> -               size = (end - start + (PAGE_SIZE - 1))>>  PAGE_SHIFT;
>> -               size = (size + 1)>>  1;
>> +               if (huge) {
>> +                       size = (end - start) / HPAGE_SIZE;
>
>> +             } else {
>> +                     size = (end - start + (PAGE_SIZE - 1))>>
>>  PAGE_SHIFT;
>> +                     size = (size + 1)>>  1;
>> +             }
>
> Perhaps:
>        if (huge) {
>                start = round_down(start, HPAGE_SIZE);
>                end = round_up(start, HPAGE_SIZE);
>                size = (end - start) >> HPAGE_SHIFT;
>        } else {
>                start = round_down(start, PAGE_SIZE << 1);
>                end = round_up(start, PAGE_SIZE << 1);
>                size = (end - start) >> (PAGE_SHIFT + 1);
>        }
> .
> .
> .
>
>>                if (size<= current_cpu_data.tlbsize/2) {
>
> Has anybody benchmarked this heuristic?  I guess it seems reasonable.
>
>>                        int oldpid = read_c0_entryhi();
>>                        int newpid = cpu_asid(cpu, mm);
>>
>> -                       start&= (PAGE_MASK<<  1);
>> -                       end += ((PAGE_SIZE<<  1) - 1);
>> -                       end&= (PAGE_MASK<<  1);
>> +                       if (huge) {
>> +                               start&= HPAGE_MASK;
>> +                               end&= HPAGE_MASK;
>> +                       } else {
>> +                               start&= (PAGE_MASK<<  1);
>> +                               end += ((PAGE_SIZE<<  1) - 1);
>> +                               end&= (PAGE_MASK<<  1);
>> +                       }
>
> This stuff is done above so is removed.
>
>
>>                        while (start<  end) {
>>                                int idx;
>>
>>                                write_c0_entryhi(start | newpid);
>> -                               start += (PAGE_SIZE<<  1);
>> +                               if (huge)
>> +                                       start += HPAGE_SIZE;
>> +                               else
>> +                                       start += (PAGE_SIZE<<  1);
>>                                mtc0_tlbw_hazard();
>>                                tlb_probe();
>>                                tlb_probe_hazard();
>>
>>
>
> If we do something like that, then...
>
> Acked-by: David Daney <david.daney@cavium.com>
>

Thanks David. It is re-prepared as the following.

----------------------------------------------------------------------------
Subject: Flush huge TLB
From: Hillf Danton <dhillf@gmail.com>

When flushing TLB, if @vma is backed by huge page, we could flush huge TLB,
due to that huge page is defined to be far from normal page.

Signed-off-by: Hillf Danton <dhillf@gmail.com>
Acked-by: David Daney <david.daney@cavium.com>
---

--- a/arch/mips/mm/tlb-r4k.c    Mon May 30 21:17:04 2011
+++ b/arch/mips/mm/tlb-r4k.c    Sun Oct  9 20:50:06 2011
@@ -120,22 +120,30 @@ void local_flush_tlb_range(struct vm_are

        if (cpu_context(cpu, mm) != 0) {
                unsigned long size, flags;
+               int huge = is_vm_hugetlb_page(vma);

                ENTER_CRITICAL(flags);
-               size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-               size = (size + 1) >> 1;
+               if (huge) {
+                       start = round_down(start, HPAGE_SIZE);
+                       end = round_up(end, HPAGE_SIZE);
+                       size = (end - start) >> HPAGE_SHIFT;
+               } else {
+                       start = round_down(start, PAGE_SIZE << 1);
+                       end = round_up(end, PAGE_SIZE << 1);
+                       size = (end - start) >> (PAGE_SHIFT + 1);
+               }
                if (size <= current_cpu_data.tlbsize/2) {
                        int oldpid = read_c0_entryhi();
                        int newpid = cpu_asid(cpu, mm);

-                       start &= (PAGE_MASK << 1);
-                       end += ((PAGE_SIZE << 1) - 1);
-                       end &= (PAGE_MASK << 1);
                        while (start < end) {
                                int idx;

                                write_c0_entryhi(start | newpid);
-                               start += (PAGE_SIZE << 1);
+                               if (huge)
+                                       start += HPAGE_SIZE;
+                               else
+                                       start += (PAGE_SIZE << 1);
                                mtc0_tlbw_hazard();
                                tlb_probe();
                                tlb_probe_hazard();
<Prev in Thread] Current Thread [Next in Thread>