aboutsummaryrefslogtreecommitdiff
path: root/libgloss/mips/hal/mips64_tlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/mips/hal/mips64_tlb.c')
-rw-r--r--libgloss/mips/hal/mips64_tlb.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/libgloss/mips/hal/mips64_tlb.c b/libgloss/mips/hal/mips64_tlb.c
new file mode 100644
index 0000000..6e96e75
--- /dev/null
+++ b/libgloss/mips/hal/mips64_tlb.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017-2018 MIPS Tech, LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "cache.h"
+#include <mips/hal.h>
+
+/* Writes hi, lo0, lo1 and mask into the TLB entry specified by index */
+void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16
+m64_tlbwi2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1,
+ unsigned long long mask,
+ int index)
+{
+ mips64_setentryhi (hi);
+ mips64_setentrylo0 (lo0);
+ mips64_setentrylo1 (lo1);
+ mips64_setpagemask (mask);
+ mips64_setindex (index);
+ mips_ehb ();
+ mips_tlbwi ();
+ return;
+}
+
+/*
+ * Writes hi, lo0, lo1 and mask into the TLB entry specified by the
+ * Random register.
+*/
+void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16
+m64_tlbwr2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1,
+ unsigned long long mask)
+{
+ mips64_setentryhi (hi);
+ mips64_setentrylo0 (lo0);
+ mips64_setentrylo1 (lo1);
+ mips64_setpagemask (mask);
+ mips_ehb ();
+ mips_tlbwr ();
+ return;
+}
+
+/*
+ * Probes the TLB for an entry matching hi and if present rewrites that entry,
+ * otherwise updates a random entry. A safe way to update the TLB.
+*/
+int __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16
+m64_tlbrwr2 (tlbhi64_t hi, tlblo64_t lo0, tlblo64_t lo1,
+ unsigned long long mask)
+{
+ tlbhi64_t prev_hi;
+ int index;
+
+ prev_hi = mips64_getentryhi ();
+ mips64_setentryhi (hi);
+
+ mips_ehb (); /* mtc0 hazard on tlbp */
+ mips_tlbp ();
+ mips_ehb (); /* tlbp hazard on mfc0 */
+
+ index = mips64_getindex ();
+
+ mips64_setentrylo0 (lo0);
+ mips64_setentrylo1 (lo1);
+ mips64_setpagemask (mask);
+
+ mips_ehb (); /* mtc0 hazard on tlbwi/tlbwr */
+
+ if (index < 0)
+ mips_tlbwr ();
+ else
+ mips_tlbwi ();
+
+ mips64_setentryhi (prev_hi);
+
+ return index;
+}
+
+/*
+ * Reads the TLB entry specified index, and returns the EntryHi,
+ * EntryLo0, EntryLo1 and PageMask parts in *phi, *plo0, *plo1 and *pmask
+ * respectively.
+*/
+void _MIPS_HAL_NOMIPS16
+m64_tlbri2 (tlbhi64_t *phi, tlblo64_t *plo0, tlblo64_t *plo1,
+ unsigned long long *pmask, int index)
+{
+ mips64_setindex (index);
+ mips_ehb (); /* mtc0 hazard on tlbr */
+ mips_tlbr ();
+ mips_ehb (); /* tlbr hazard on mfc0 */
+ *phi = mips64_getentryhi ();
+ *plo0 = mips64_getentrylo0 ();
+ *plo1 = mips64_getentrylo1 ();
+ *pmask = mips64_getpagemask ();
+ return;
+}
+
+/*
+ * Probes the TLB for an entry matching hi and returns its index, or -1 if
+ * not found. If found, then the EntryLo0, EntryLo1 and PageMask parts of the
+ * entry are also returned in *plo0, *plo1 and *pmask respectively.
+*/
+int __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16
+m64_tlbprobe2 (tlbhi64_t hi, tlblo64_t *plo0, tlblo64_t *plo1,
+ unsigned long long *pmask)
+{
+ tlbhi64_t prev_hi;
+ int index;
+
+ prev_hi = mips64_getentryhi ();
+ mips64_setentryhi (hi);
+
+ mips_ehb (); /* mtc0 hazard on tlbp */
+ mips_tlbp ();
+ mips_ehb (); /* tlbp hazard on mfc0 */
+
+ index = mips64_getindex ();
+
+ if (index >= 0)
+ {
+ mips_tlbr ();
+ mips_ehb (); /* tlbr hazard on mfc0 */
+ *plo0 = mips64_getentrylo0 ();
+ *plo1 = mips64_getentrylo1 ();
+ *pmask = mips64_getpagemask ();
+ }
+ else
+ index = -1;
+
+ mips64_setentryhi (prev_hi);
+
+ return index;
+}
+
+/* Probes the TLB for an entry matching hi, and if present invalidates it */
+void __attribute__ ((use_hazard_barrier_return)) _MIPS_HAL_NOMIPS16
+m64_tlbinval (tlbhi64_t hi)
+{
+ int index, tmp_idx;
+ tlbhi64_t prev_hi, tmp_hi;
+ register const unsigned long zero = 0;
+ unsigned long cfg;
+
+ prev_hi = mips64_getentryhi ();
+ mips64_setentryhi (hi);
+
+ mips_ehb (); /* mtc0 hazard on tlbp */
+ mips_tlbp ();
+ mips_ehb (); /* tlbp hazard on mfc0 */
+
+ index = mips64_getindex ();
+
+ if (index < 0)
+ goto restore;
+
+ mips64_setentrylo0 (zero);
+ mips64_setentrylo1 (zero);
+
+ /* Check if Config4 is implemented */
+ cfg = mips64_getconfig3 ();
+ if ((cfg & CFG3_M) != 0)
+ {
+ cfg = mips64_getconfig4 ();
+ if ((cfg & CFG4_IE_MASK) != 0)
+ {
+ tmp_hi = C0_ENTRYHI_EHINV_MASK;
+ goto do_tlbwi;
+ }
+ }
+
+ tmp_hi = (tlbhi64_t) ((unsigned long) KSEG0_BASE - 0x4000);
+
+ do
+ {
+ tmp_hi = tmp_hi + 0x4000;
+ mips64_setentryhi (tmp_hi);
+ mips_ehb (); /* mtc0 hazard on tlbp */
+ mips_tlbp ();
+ mips_ehb (); /* tlbp hazard on mfc0 */
+ tmp_idx = mips64_getindex ();
+ }
+ while (tmp_idx >= 0);
+
+ mips64_setindex (index); /* restore Index */
+
+do_tlbwi:
+ mips64_setentryhi (tmp_hi);
+ mips_ehb (); /* mtc0 hazard on tlbp */
+ mips_tlbwi ();
+ mips_ehb (); /* tlbwi hazard on mfc0 */
+
+restore:
+ mips64_setentryhi (prev_hi); /* restore EntryHi */
+
+ return;
+}