root/arch/powerpc/mm/book3s32/mmu_context.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __init_new_context
  2. init_new_context
  3. __destroy_context
  4. destroy_context
  5. mmu_context_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * This file contains the routines for handling the MMU on those
   4  * PowerPC implementations where the MMU substantially follows the
   5  * architecture specification.  This includes the 6xx, 7xx, 7xxx,
   6  * and 8260 implementations but excludes the 8xx and 4xx.
   7  *  -- paulus
   8  *
   9  *  Derived from arch/ppc/mm/init.c:
  10  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  11  *
  12  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  13  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  14  *    Copyright (C) 1996 Paul Mackerras
  15  *
  16  *  Derived from "arch/i386/mm/init.c"
  17  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  18  */
  19 
  20 #include <linux/mm.h>
  21 #include <linux/init.h>
  22 #include <linux/export.h>
  23 
  24 #include <asm/mmu_context.h>
  25 
  26 /*
  27  * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
  28  * (virtual segment identifiers) for each context.  Although the
  29  * hardware supports 24-bit VSIDs, and thus >1 million contexts,
  30  * we only use 32,768 of them.  That is ample, since there can be
  31  * at most around 30,000 tasks in the system anyway, and it means
  32  * that we can use a bitmap to indicate which contexts are in use.
  33  * Using a bitmap means that we entirely avoid all of the problems
  34  * that we used to have when the context number overflowed,
  35  * particularly on SMP systems.
  36  *  -- paulus.
  37  */
  38 #define NO_CONTEXT              ((unsigned long) -1)
  39 #define LAST_CONTEXT            32767
  40 #define FIRST_CONTEXT           1
  41 
  42 /*
  43  * This function defines the mapping from contexts to VSIDs (virtual
  44  * segment IDs).  We use a skew on both the context and the high 4 bits
  45  * of the 32-bit virtual address (the "effective segment ID") in order
  46  * to spread out the entries in the MMU hash table.  Note, if this
  47  * function is changed then arch/ppc/mm/hashtable.S will have to be
  48  * changed to correspond.
  49  *
  50  *
  51  * CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
  52  *                               & 0xffffff)
  53  */
  54 
  55 static unsigned long next_mmu_context;
  56 static unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
  57 
  58 unsigned long __init_new_context(void)
  59 {
  60         unsigned long ctx = next_mmu_context;
  61 
  62         while (test_and_set_bit(ctx, context_map)) {
  63                 ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
  64                 if (ctx > LAST_CONTEXT)
  65                         ctx = 0;
  66         }
  67         next_mmu_context = (ctx + 1) & LAST_CONTEXT;
  68 
  69         return ctx;
  70 }
  71 EXPORT_SYMBOL_GPL(__init_new_context);
  72 
  73 /*
  74  * Set up the context for a new address space.
  75  */
  76 int init_new_context(struct task_struct *t, struct mm_struct *mm)
  77 {
  78         mm->context.id = __init_new_context();
  79 
  80         return 0;
  81 }
  82 
  83 /*
  84  * Free a context ID. Make sure to call this with preempt disabled!
  85  */
  86 void __destroy_context(unsigned long ctx)
  87 {
  88         clear_bit(ctx, context_map);
  89 }
  90 EXPORT_SYMBOL_GPL(__destroy_context);
  91 
  92 /*
  93  * We're finished using the context for an address space.
  94  */
  95 void destroy_context(struct mm_struct *mm)
  96 {
  97         preempt_disable();
  98         if (mm->context.id != NO_CONTEXT) {
  99                 __destroy_context(mm->context.id);
 100                 mm->context.id = NO_CONTEXT;
 101         }
 102         preempt_enable();
 103 }
 104 
 105 /*
 106  * Initialize the context management stuff.
 107  */
 108 void __init mmu_context_init(void)
 109 {
 110         /* Reserve context 0 for kernel use */
 111         context_map[0] = (1 << FIRST_CONTEXT) - 1;
 112         next_mmu_context = FIRST_CONTEXT;
 113 }

/* [<][>][^][v][top][bottom][index][help] */