Skip to content

Commit f88f42f

Browse files
murzinvwilldeacon
authored andcommitted
arm64: context: Free up kernel ASIDs if KPTI is not in use
We can extend user ASID space if it turns out that system does not require KPTI. We start with kernel ASIDs reserved because CPU caps are not finalized yet and free them up lazily on the next rollover if we confirm than KPTI is not in use. Reviewed-by: Catalin Marinas <[email protected]> Signed-off-by: Vladimir Murzin <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent edf9081 commit f88f42f

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

arch/arm64/mm/context.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,9 @@ static cpumask_t tlb_flush_pending;
2929
#define ASID_MASK (~GENMASK(asid_bits - 1, 0))
3030
#define ASID_FIRST_VERSION (1UL << asid_bits)
3131

32-
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
33-
#define NUM_USER_ASIDS (ASID_FIRST_VERSION >> 1)
34-
#define asid2idx(asid) (((asid) & ~ASID_MASK) >> 1)
35-
#define idx2asid(idx) (((idx) << 1) & ~ASID_MASK)
36-
#else
37-
#define NUM_USER_ASIDS (ASID_FIRST_VERSION)
32+
#define NUM_USER_ASIDS ASID_FIRST_VERSION
3833
#define asid2idx(asid) ((asid) & ~ASID_MASK)
3934
#define idx2asid(idx) asid2idx(idx)
40-
#endif
4135

4236
/* Get the ASIDBits supported by the current CPU */
4337
static u32 get_cpu_asid_bits(void)
@@ -77,13 +71,33 @@ void verify_cpu_asid_bits(void)
7771
}
7872
}
7973

74+
static void set_kpti_asid_bits(void)
75+
{
76+
unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned long);
77+
/*
78+
* In case of KPTI kernel/user ASIDs are allocated in
79+
* pairs, the bottom bit distinguishes the two: if it
80+
* is set, then the ASID will map only userspace. Thus
81+
* mark even as reserved for kernel.
82+
*/
83+
memset(asid_map, 0xaa, len);
84+
}
85+
86+
static void set_reserved_asid_bits(void)
87+
{
88+
if (arm64_kernel_unmapped_at_el0())
89+
set_kpti_asid_bits();
90+
else
91+
bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
92+
}
93+
8094
static void flush_context(void)
8195
{
8296
int i;
8397
u64 asid;
8498

8599
/* Update the list of reserved ASIDs and the ASID bitmap. */
86-
bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
100+
set_reserved_asid_bits();
87101

88102
for_each_possible_cpu(i) {
89103
asid = atomic64_xchg_relaxed(&per_cpu(active_asids, i), 0);
@@ -261,6 +275,14 @@ static int asids_init(void)
261275
panic("Failed to allocate bitmap for %lu ASIDs\n",
262276
NUM_USER_ASIDS);
263277

278+
/*
279+
* We cannot call set_reserved_asid_bits() here because CPU
280+
* caps are not finalized yet, so it is safer to assume KPTI
281+
* and reserve kernel ASID's from beginning.
282+
*/
283+
if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0))
284+
set_kpti_asid_bits();
285+
264286
pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
265287
return 0;
266288
}

0 commit comments

Comments
 (0)