0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/mm.h>
0021 #include <linux/init.h>
0022 #include <linux/export.h>
0023
0024 #include <asm/mmu_context.h>
0025
0026
0027
0028
0029
0030 void *abatron_pteptrs[2];
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #define NO_CONTEXT ((unsigned long) -1)
0045 #define LAST_CONTEXT 32767
0046 #define FIRST_CONTEXT 1
0047
0048 static unsigned long next_mmu_context;
0049 static unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
0050
0051 unsigned long __init_new_context(void)
0052 {
0053 unsigned long ctx = next_mmu_context;
0054
0055 while (test_and_set_bit(ctx, context_map)) {
0056 ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
0057 if (ctx > LAST_CONTEXT)
0058 ctx = 0;
0059 }
0060 next_mmu_context = (ctx + 1) & LAST_CONTEXT;
0061
0062 return ctx;
0063 }
0064 EXPORT_SYMBOL_GPL(__init_new_context);
0065
0066
0067
0068
0069 int init_new_context(struct task_struct *t, struct mm_struct *mm)
0070 {
0071 mm->context.id = __init_new_context();
0072 mm->context.sr0 = CTX_TO_VSID(mm->context.id, 0);
0073
0074 if (!kuep_is_disabled())
0075 mm->context.sr0 |= SR_NX;
0076 if (!kuap_is_disabled())
0077 mm->context.sr0 |= SR_KS;
0078
0079 return 0;
0080 }
0081
0082
0083
0084
0085 void __destroy_context(unsigned long ctx)
0086 {
0087 clear_bit(ctx, context_map);
0088 }
0089 EXPORT_SYMBOL_GPL(__destroy_context);
0090
0091
0092
0093
0094 void destroy_context(struct mm_struct *mm)
0095 {
0096 preempt_disable();
0097 if (mm->context.id != NO_CONTEXT) {
0098 __destroy_context(mm->context.id);
0099 mm->context.id = NO_CONTEXT;
0100 }
0101 preempt_enable();
0102 }
0103
0104
0105
0106
0107 void __init mmu_context_init(void)
0108 {
0109
0110 context_map[0] = (1 << FIRST_CONTEXT) - 1;
0111 next_mmu_context = FIRST_CONTEXT;
0112 }
0113
0114 void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
0115 {
0116 long id = next->context.id;
0117
0118 if (id < 0)
0119 panic("mm_struct %p has no context ID", next);
0120
0121 isync();
0122
0123 update_user_segments(next->context.sr0);
0124
0125 if (IS_ENABLED(CONFIG_BDI_SWITCH))
0126 abatron_pteptrs[1] = next->pgd;
0127
0128 if (!mmu_has_feature(MMU_FTR_HPTE_TABLE))
0129 mtspr(SPRN_SDR1, rol32(__pa(next->pgd), 4) & 0xffff01ff);
0130
0131 mb();
0132 isync();
0133 }
0134 EXPORT_SYMBOL(switch_mmu_context);