Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Aug 2012 10:50:23 -0700
From:      Juli Mallett <jmallett@FreeBSD.org>
To:        Paul Ambrose <ambrosehua@gmail.com>
Cc:        freebsd-mips@freebsd.org
Subject:   Re: tlb.c tlb_invalidate_all_user simplified
Message-ID:  <CACVs6=81jSiw8t_6iQGYx9AKhH_kYMB=AYtguhJ0mwFA845XYg@mail.gmail.com>
In-Reply-To: <CAMwoQQ6sFSh3MuPivwszTUOF0tWZRYMxtwEjtbRLE0X%2Bpx_Xfw@mail.gmail.com>
References:  <CAMwoQQ6sFSh3MuPivwszTUOF0tWZRYMxtwEjtbRLE0X%2Bpx_Xfw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Actually, tlb_invalidate_all_user is beneath the pmap layer, and
checks for a NULL pmap are useful here because tlb_invalidate_all_user
may be passed a NULL pmap by the caller deliberately.  When a NULL
pmap is passed, the behavior is changed: rather than ejecting from the
TLB any entries which belong to a specific user pmap, it ejects all
entries from the pmap that do not belong to the kernel.  This is
necessary because user address spaces are partitioned within the
(shared) TLB by something called an Address Space ID (ASID).  We
allocate these linearly and keep a generation count to know whether
one is currently valid.  (This way we can avoid removing entries owned
by a task from the TLB during most context switches.)  That is, to
know whether a given pmap already has a valid ASID assigned to it.
Because the ASID field is 8 bits, we must increment that generation
count every time we allocate our 256th (actually 255th since ASID 0 is
reserved) ASID, and know that any entries in the TLB belonging to
tasks from the previous run of ASIDs must be removed.  So we call
tlb_invalidate_all_user(NULL), which flushes all user entries, without
flushing kernel entries and requiring the kernel to reload a bunch of
TLB entries just to keep running.

I hope that's remotely clear.  The need and use of this function touch
upon just about every complicated result of the MIPS TLB being
software managed.

Thanks,
Juli.

On Fri, Aug 10, 2012 at 4:57 AM, Paul Ambrose <ambrosehua@gmail.com> wrote:
> when I saw this commit,
> commit e60abd7cb37fb1b66e8b0c48050aa56732c73e90
> Author: alc <alc@FreeBSD.org>
> Date:   Fri Aug 10 05:00:50 2012 +0000
>
>     Merge r134393 from amd64/i386:
>       The machine-independent parts of the virtual memory system always
> pass a
>       valid pmap to the pmap functions that require one.  Remove the checks
> for
>       NULL.  (These checks have their origins in the Mach pmap.c that was
>       integrated into BSD.  None of the new code written specifically for
>       FreeBSD included them.)
>
> according to the description here, pmap should not be null, I think
> tlb_invalidate_all_user(struct  pmap * pmap),  in mips/mips/tlb.c
> ----------------------------------------------------------------------------------------------------
> tlb_invalidate_all_user(struct pmap *pmap)
> {
> register_t asid;
> register_t s;
> unsigned i;
>
> s = intr_disable();
> asid = mips_rd_entryhi() & TLBHI_ASID_MASK;
>
> for (i = mips_rd_wired(); i < num_tlbentries; i++) {
> register_t uasid;
>
> mips_wr_index(i);
> tlb_read();
>
> uasid = mips_rd_entryhi() & TLBHI_ASID_MASK;
> if (pmap == NULL) {
> /*
>  * Invalidate all non-kernel entries.
>  */
> if (uasid == 0)
> continue;
> } else {
> /*
>  * Invalidate this pmap's entries.
>  */
> if (uasid != pmap_asid(pmap))
> continue;
> }
> tlb_invalidate_one(i);
> }
>
> mips_wr_entryhi(asid);
> intr_restore(s);
> }
> ---------------------------------------------------------------------------
> could be simplified like this:
> ---------------------------------------------------------------------------
> tlb_invalidate_all_user(struct pmap *pmap)
> {
> register_t asid;
> register_t s;
> unsigned i;
>
> s = intr_disable();
> asid = mips_rd_entryhi() & TLBHI_ASID_MASK;
>
> for (i = mips_rd_wired(); i < num_tlbentries; i++) {
> register_t uasid;
>
> mips_wr_index(i);
> tlb_read();
>
> uasid = mips_rd_entryhi() & TLBHI_ASID_MASK;
>          if ((uasid != pmap_asid(pmap)) || (uasid == 0))
> continue;
> tlb_invalidate_one(i);
> }
>
> mips_wr_entryhi(asid);
> intr_restore(s);
> }
>
> funcntion tlb_invalidate_all_user(struct pmap *pmap) is ONLY called like
> this:
> pmap_activate -> pmap_alloc_asid -> tlb_invalidate_all_user, I think the
> pmap passed
> fullfils the assumption. How do you like it ?
> _______________________________________________
> freebsd-mips@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-mips
> To unsubscribe, send any mail to "freebsd-mips-unsubscribe@freebsd.org"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CACVs6=81jSiw8t_6iQGYx9AKhH_kYMB=AYtguhJ0mwFA845XYg>