Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a391263c authored by Will Deacon's avatar Will Deacon Committed by Russell King
Browse files

ARM: 8203/1: mm: try to re-use old ASID assignments following a rollover



Rather than unconditionally allocating a fresh ASID to an mm from an
older generation, attempt to re-use the old assignment where possible.

This can bring performance benefits on systems where the ASID is used to
tag things other than the TLB (e.g. branch prediction resources).

Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 2b94fe2a
Loading
Loading
Loading
Loading
+34 −24
Original line number Diff line number Diff line
@@ -184,22 +184,31 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
	u64 asid = atomic64_read(&mm->context.id);
	u64 generation = atomic64_read(&asid_generation);

	if (asid != 0 && is_reserved_asid(asid)) {
	if (asid != 0) {
		/*
		 * Our current ASID was active during a rollover, we can
		 * continue to use it and this was just a false alarm.
		 * If our current ASID was active during a rollover, we
		 * can continue to use it and this was just a false alarm.
		 */
		asid = generation | (asid & ~ASID_MASK);
	} else {
		if (is_reserved_asid(asid))
			return generation | (asid & ~ASID_MASK);

		/*
		 * 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))
			goto bump_gen;
	}

	/*
		 * 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 reserve ASID #0 to switch via TTBR0 and to
		 * avoid speculative page table walks from hitting in
		 * any partial walk caches, which could be populated
		 * from overlapping level-1 descriptors used to map both
		 * the module area and the userspace stack.
	 * 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 reserve ASID #0 to switch
	 * via TTBR0 and to avoid speculative page table walks from hitting
	 * in any partial walk caches, which could be populated from
	 * overlapping level-1 descriptors used to map both the module
	 * area and the userspace stack.
	 */
	asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx);
	if (asid == NUM_USER_ASIDS) {
@@ -208,12 +217,13 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
		flush_context(cpu);
		asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
	}

	__set_bit(asid, asid_map);
	cur_idx = asid;

bump_gen:
	asid |= generation;
	cpumask_clear(mm_cpumask(mm));
	}

	return asid;
}