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

Commit 99afa69a authored by Will Deacon's avatar Will Deacon Committed by Gerrit - the friendly Code Review server
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)
[ghackmann@google.com: adjust context]
Signed-off-by: default avatarGreg Hackmann <ghackmann@google.com>
Change-Id: Ie9dd8ca183007c486ef13fd3c560223d263bef4b
Git-Commit: b7032349
Git-repo: git://android.googlesource.com/kernel/common.git


Signed-off-by: default avatarVinayak Menon <vinmenon@codeaurora.org>
parent c5dfc5b5
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)