|
@@ -39,7 +39,16 @@ static cpumask_t tlb_flush_pending;
|
|
|
|
|
|
#define ASID_MASK (~GENMASK(asid_bits - 1, 0))
|
|
|
#define ASID_FIRST_VERSION (1UL << asid_bits)
|
|
|
-#define NUM_USER_ASIDS ASID_FIRST_VERSION
|
|
|
+
|
|
|
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
|
|
+#define NUM_USER_ASIDS (ASID_FIRST_VERSION >> 1)
|
|
|
+#define asid2idx(asid) (((asid) & ~ASID_MASK) >> 1)
|
|
|
+#define idx2asid(idx) (((idx) << 1) & ~ASID_MASK)
|
|
|
+#else
|
|
|
+#define NUM_USER_ASIDS (ASID_FIRST_VERSION)
|
|
|
+#define asid2idx(asid) ((asid) & ~ASID_MASK)
|
|
|
+#define idx2asid(idx) asid2idx(idx)
|
|
|
+#endif
|
|
|
|
|
|
/* Get the ASIDBits supported by the current CPU */
|
|
|
static u32 get_cpu_asid_bits(void)
|
|
@@ -98,7 +107,7 @@ static void flush_context(unsigned int cpu)
|
|
|
*/
|
|
|
if (asid == 0)
|
|
|
asid = per_cpu(reserved_asids, i);
|
|
|
- __set_bit(asid & ~ASID_MASK, asid_map);
|
|
|
+ __set_bit(asid2idx(asid), asid_map);
|
|
|
per_cpu(reserved_asids, i) = asid;
|
|
|
}
|
|
|
|
|
@@ -153,16 +162,16 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
|
|
|
* We had a valid ASID in a previous life, so try to re-use
|
|
|
* it if possible.
|
|
|
*/
|
|
|
- asid &= ~ASID_MASK;
|
|
|
- if (!__test_and_set_bit(asid, asid_map))
|
|
|
+ if (!__test_and_set_bit(asid2idx(asid), asid_map))
|
|
|
return newasid;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Allocate a free ASID. If we can't find one, take a note of the
|
|
|
- * currently active ASIDs and mark the TLBs as requiring flushes.
|
|
|
- * We always count from ASID #1, as we use ASID #0 when setting a
|
|
|
- * reserved TTBR0 for the init_mm.
|
|
|
+ * currently active ASIDs and mark the TLBs as requiring flushes. We
|
|
|
+ * always count from ASID #2 (index 1), as we use ASID #0 when setting
|
|
|
+ * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd
|
|
|
+ * pairs.
|
|
|
*/
|
|
|
asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx);
|
|
|
if (asid != NUM_USER_ASIDS)
|
|
@@ -179,7 +188,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
|
|
|
set_asid:
|
|
|
__set_bit(asid, asid_map);
|
|
|
cur_idx = asid;
|
|
|
- return asid | generation;
|
|
|
+ return idx2asid(asid) | generation;
|
|
|
}
|
|
|
|
|
|
void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
|