mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-19 17:11:03 +00:00
arm64: mm: Allocate ASIDs in pairs
Commit 0c8ea531b7
upstream.
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: Mark Rutland <mark.rutland@arm.com>
Tested-by: Laura Abbott <labbott@redhat.com>
Tested-by: Shanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
00ff7de671
commit
a8bad38cff
2 changed files with 18 additions and 8 deletions
|
@ -17,6 +17,7 @@
|
|||
#define __ASM_MMU_H
|
||||
|
||||
#define MMCF_AARCH32 0x1 /* mm context flag for AArch32 executables */
|
||||
#define USER_ASID_FLAG (UL(1) << 48)
|
||||
|
||||
typedef struct {
|
||||
atomic64_t id;
|
||||
|
|
|
@ -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)
|
||||
|
@ -104,7 +113,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;
|
||||
}
|
||||
|
||||
|
@ -156,16 +165,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)
|
||||
|
@ -182,7 +191,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)
|
||||
|
|
Loading…
Reference in a new issue