linux/arch/arm64/mm
Will Deacon 0ebea80880 arm64: mm: keep reserved ASIDs in sync with mm after multiple rollovers
Under some unusual context-switching patterns, it is possible to end up
with multiple threads from the same mm running concurrently with
different ASIDs:

1. CPU x schedules task t with mm p containing ASID a and generation g
   This task doesn't block and the CPU doesn't context switch.
   So:
     * per_cpu(active_asid, x) = {g,a}
     * p->context.id = {g,a}

2. Some other CPU generates an ASID rollover. The global generation is
   now (g + 1). CPU x is still running t, with no context switch and
   so per_cpu(reserved_asid, x) = {g,a}

3. CPU y schedules task t', which shares mm p with t. The generation
   mismatches, so we take the slowpath and hit the reserved ASID from
   CPU x. p is then updated so that p->context.id = {g + 1,a}

4. CPU y schedules some other task u, which has an mm != p.

5. Some other CPU generates *another* CPU rollover. The global
   generation is now (g + 2). CPU x is still running t, with no context
   switch and so per_cpu(reserved_asid, x) = {g,a}.

6. CPU y once again schedules task t', but now *fails* to hit the
   reserved ASID from CPU x because of the generation mismatch. This
   results in a new ASID being allocated, despite the fact that t is
   still running on CPU x with the same mm.

Consequently, TLBIs (e.g. as a result of CoW) will not be synchronised
between the two threads.

This patch fixes the problem by updating all of the matching reserved
ASIDs when we hit on the slowpath (i.e. in step 3 above). This keeps
the reserved ASIDs in-sync with the mm and avoids the problem.

Reported-by: Tony Thompson <anthony.thompson@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2015-11-26 15:27:10 +00:00
..
cache.S arm64: use ENDPIPROC() to annotate position independent assembler routines 2015-10-12 16:19:45 +01:00
context.c arm64: mm: keep reserved ASIDs in sync with mm after multiple rollovers 2015-11-26 15:27:10 +00:00
copypage.c arm64: export __cpu_{clear,copy}_user_page functions 2014-07-08 17:30:51 +01:00
dma-mapping.c arm64: simplify dma_get_ops 2015-11-17 12:05:18 +00:00
dump.c arm64: Make the kernel page dump utility aware of the CONT bit 2015-10-08 18:39:57 +01:00
extable.c arm64: MMU fault handling and page table management 2012-09-17 13:41:57 +01:00
fault.c arm64: mm: fix fault_info table xFSC decoding 2015-11-25 15:49:16 +00:00
flush.c arm64: force CONFIG_SMP=y and remove redundant #ifdefs 2015-07-27 11:08:40 +01:00
hugetlbpage.c arm64: hugetlb: remove paragraph about writing to FSF 2015-07-27 11:08:40 +01:00
init.c arm64: Fix build with CONFIG_ZONE_DMA=n 2015-10-29 16:58:00 +00:00
ioremap.c arm64: add ioremap physical address information 2015-01-23 15:29:06 +00:00
kasan_init.c arm64: kasan: fix issues reported by sparse 2015-10-13 14:54:42 +01:00
Makefile arm64: add KASAN support 2015-10-12 17:46:36 +01:00
mm.h arm64: add better page protections to arm64 2015-01-22 14:54:29 +00:00
mmap.c mm: expose arch_mmap_rnd when available 2015-04-14 16:49:05 -07:00
mmu.c arm64: early_alloc: Fix check for allocation failure 2015-11-25 12:14:25 +00:00
pageattr.c arm64/mm: use PAGE_ALIGNED instead of IS_ALIGNED 2015-10-28 18:36:32 +00:00
pgd.c arm64: move PGD_SIZE definition to pgalloc.h 2015-10-12 17:46:30 +01:00
proc-macros.S arm64: mm: increase VA range of identity map 2015-03-23 11:35:29 +00:00
proc.S arm64 updates for 4.4: 2015-11-04 14:47:13 -08:00