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

Commit b7032349 authored by Will Deacon's avatar Will Deacon Committed by Greg Kroah-Hartman
Browse files

FROMLIST: arm64: mm: Allocate ASIDs in pairs



In preparation for separate kernel/user ASIDs, allocate them in pairs
for each mm_struct. The bottom bit distinguishes the two: if it is set,
then the ASID will map only userspace.

Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
Tested-by: default avatarLaura Abbott <labbott@redhat.com>
Tested-by: default avatarShanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
(cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git


 commit 0c8ea531b7740754cf374ca8b7510655f569c5e3)

Change-Id: I283c99292b165e04ff1b6b9cb5806805974ae915
[ghackmann@google.com: adjust context]
Signed-off-by: default avatarGreg Hackmann <ghackmann@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 4ea2126b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#ifndef __ASM_MMU_H
#define __ASM_MMU_H

#define USER_ASID_FLAG	(UL(1) << 48)

typedef struct {
	atomic64_t	id;
	void		*vdso;
+17 −8
Original line number Diff line number Diff line
@@ -38,7 +38,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

static void flush_context(unsigned int cpu)
{
@@ -65,7 +74,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;
	}

@@ -120,16 +129,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)
@@ -146,7 +155,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)