]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge branch 'context-id-fix' into fixes
authorMichael Ellerman <mpe@ellerman.id.au>
Thu, 13 Jun 2019 05:00:34 +0000 (15:00 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 13 Jun 2019 05:00:34 +0000 (15:00 +1000)
This merges a fix for a bug in our context id handling on 64-bit hash
CPUs.

The fix was written against v5.1 to ease backporting to stable
releases. Here we are merging it up to a v5.2-rc2 base, which involves
a bit of manual resolution.

It also adds a test case for the bug.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1  2 
arch/powerpc/mm/book3s64/mmu_context.c

index cb2b08635508b7cbff91a76504442e531a25a3f2,8751ae2e2d040cad9f8c7b6701c8d7c53a4213c3..6d8f06b04022023e07379bee424f34a596359e8e
@@@ -59,17 -97,6 +97,11 @@@ static int hash__init_new_context(struc
  {
        int index;
  
-       index = hash__alloc_context_id();
-       if (index < 0)
-               return index;
 +      mm->context.hash_context = kmalloc(sizeof(struct hash_mm_context),
 +                                         GFP_KERNEL);
-       if (!mm->context.hash_context) {
-               ida_free(&mmu_context_ida, index);
++      if (!mm->context.hash_context)
 +              return -ENOMEM;
-       }
 +
        /*
         * The old code would re-promote on fork, we don't do that when using
         * slices as it could cause problem promoting slices that have been
         * We should not be calling init_new_context() on init_mm. Hence a
         * check against 0 is OK.
         */
 -      if (mm->context.id == 0)
 +      if (mm->context.id == 0) {
 +              memset(mm->context.hash_context, 0, sizeof(struct hash_mm_context));
                slice_init_new_context_exec(mm);
-                               ida_free(&mmu_context_ida, index);
 +      } else {
 +              /* This is fork. Copy hash_context details from current->mm */
 +              memcpy(mm->context.hash_context, current->mm->context.hash_context, sizeof(struct hash_mm_context));
 +#ifdef CONFIG_PPC_SUBPAGE_PROT
 +              /* inherit subpage prot detalis if we have one. */
 +              if (current->mm->context.hash_context->spt) {
 +                      mm->context.hash_context->spt = kmalloc(sizeof(struct subpage_prot_table),
 +                                                              GFP_KERNEL);
 +                      if (!mm->context.hash_context->spt) {
 +                              kfree(mm->context.hash_context);
 +                              return -ENOMEM;
 +                      }
 +              }
 +#endif
++      }
  
 -      if (index < 0)
+       index = realloc_context_ids(&mm->context);
 -
 -      subpage_prot_init_new_context(mm);
++      if (index < 0) {
++#ifdef CONFIG_PPC_SUBPAGE_PROT
++              kfree(mm->context.hash_context->spt);
++#endif
++              kfree(mm->context.hash_context);
+               return index;
 +      }
  
        pkey_mm_init(mm);
        return index;