Release 4.14 arch/powerpc/mm/mmu_context_book3s64.c
/*
* MMU context allocation for 64-bit kernels.
*
* Copyright (C) 2004 Anton Blanchard, IBM Corp. <anton@samba.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
#include <linux/export.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
static DEFINE_SPINLOCK(mmu_context_lock);
static DEFINE_IDA(mmu_context_ida);
static int alloc_context_id(int min_id, int max_id)
{
int index, err;
again:
if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
return -ENOMEM;
spin_lock(&mmu_context_lock);
err = ida_get_new_above(&mmu_context_ida, min_id, &index);
spin_unlock(&mmu_context_lock);
if (err == -EAGAIN)
goto again;
else if (err)
return err;
if (index > max_id) {
spin_lock(&mmu_context_lock);
ida_remove(&mmu_context_ida, index);
spin_unlock(&mmu_context_lock);
return -ENOMEM;
}
return index;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Paul Mackerras | 80 | 71.43% | 1 | 16.67% |
Sonny Rao | 12 | 10.71% | 1 | 16.67% |
Michael Ellerman | 10 | 8.93% | 2 | 33.33% |
Anton Blanchard | 6 | 5.36% | 1 | 16.67% |
Alexander Graf | 4 | 3.57% | 1 | 16.67% |
Total | 112 | 100.00% | 6 | 100.00% |
void hash__reserve_context_id(int id)
{
int rc, result = 0;
do {
if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
break;
spin_lock(&mmu_context_lock);
rc = ida_get_new_above(&mmu_context_ida, id, &result);
spin_unlock(&mmu_context_lock);
} while (rc == -EAGAIN);
WARN(result != id, "mmu: Failed to reserve context id %d (rc %d)\n", id, result);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 76 | 100.00% | 1 | 100.00% |
Total | 76 | 100.00% | 1 | 100.00% |
int hash__alloc_context_id(void)
{
unsigned long max;
if (mmu_has_feature(MMU_FTR_68_BIT_VA))
max = MAX_USER_CONTEXT;
else
max = MAX_USER_CONTEXT_65BIT_VA;
return alloc_context_id(MIN_USER_CONTEXT, max);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 22 | 62.86% | 2 | 50.00% |
Michael Ellerman | 13 | 37.14% | 2 | 50.00% |
Total | 35 | 100.00% | 4 | 100.00% |
EXPORT_SYMBOL_GPL(hash__alloc_context_id);
static int hash__init_new_context(struct mm_struct *mm)
{
int index;
index = hash__alloc_context_id();
if (index < 0)
return index;
/*
* We do switch_slb() early in fork, even before we setup the
* mm->context.addr_limit. Default to max task size so that we copy the
* default values to paca which will help us to handle slb miss early.
*/
mm->context.addr_limit = DEFAULT_MAP_WINDOW_USER64;
/*
* 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
* forced down to 4K.
*
* For book3s we have MMU_NO_CONTEXT set to be ~0. Hence check
* explicitly against context.id == 0. This ensures that we properly
* initialize context slice details for newly allocated mm's (which will
* have id == 0) and don't alter context slice inherited via fork (which
* will have id != 0).
*
* We should not be calling init_new_context() on init_mm. Hence a
* check against 0 is OK.
*/
if (mm->context.id == 0)
slice_set_user_psize(mm, mmu_virtual_psize);
subpage_prot_init_new_context(mm);
return index;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michael Ellerman | 45 | 71.43% | 1 | 25.00% |
Aneesh Kumar K.V | 18 | 28.57% | 3 | 75.00% |
Total | 63 | 100.00% | 4 | 100.00% |
static int radix__init_new_context(struct mm_struct *mm)
{
unsigned long rts_field;
int index, max_id;
max_id = (1 << mmu_pid_bits) - 1;
index = alloc_context_id(mmu_base_pid, max_id);
if (index < 0)
return index;
/*
* set the process table entry,
*/
rts_field = radix__get_tree_size();
process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE);
/*
* Order the above store with subsequent update of the PID
* register (at which point HW can start loading/caching
* the entry) and the corresponding load by the MMU from
* the L2 cache.
*/
asm volatile("ptesync;isync" : : : "memory");
mm->context.npu_context = NULL;
return index;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 36 | 40.00% | 2 | 33.33% |
Michael Ellerman | 28 | 31.11% | 1 | 16.67% |
Benjamin Herrenschmidt | 18 | 20.00% | 2 | 33.33% |
Alistair Popple | 8 | 8.89% | 1 | 16.67% |
Total | 90 | 100.00% | 6 | 100.00% |
int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
int index;
if (radix_enabled())
index = radix__init_new_context(mm);
else
index = hash__init_new_context(mm);
if (index < 0)
return index;
mm->context.id = index;
#ifdef CONFIG_PPC_64K_PAGES
mm->context.pte_frag = NULL;
#endif
#ifdef CONFIG_SPAPR_TCE_IOMMU
mm_iommu_init(mm);
#endif
atomic_set(&mm->context.active_cpus, 0);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 22 | 23.66% | 2 | 20.00% |
Alexander Graf | 17 | 18.28% | 1 | 10.00% |
Michael Ellerman | 14 | 15.05% | 1 | 10.00% |
Benjamin Herrenschmidt | 12 | 12.90% | 1 | 10.00% |
Alexey Kardashevskiy | 10 | 10.75% | 1 | 10.00% |
Stephen Rothwell | 8 | 8.60% | 1 | 10.00% |
Paul Mackerras | 4 | 4.30% | 1 | 10.00% |
David Gibson | 4 | 4.30% | 1 | 10.00% |
Tseng-Hui (Frank) Lin | 2 | 2.15% | 1 | 10.00% |
Total | 93 | 100.00% | 10 | 100.00% |
void __destroy_context(int context_id)
{
spin_lock(&mmu_context_lock);
ida_remove(&mmu_context_ida, context_id);
spin_unlock(&mmu_context_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Paul Mackerras | 21 | 75.00% | 1 | 33.33% |
Alexander Graf | 5 | 17.86% | 1 | 33.33% |
Anton Blanchard | 2 | 7.14% | 1 | 33.33% |
Total | 28 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL_GPL(__destroy_context);
#ifdef CONFIG_PPC_64K_PAGES
static void destroy_pagetable_page(struct mm_struct *mm)
{
int count;
void *pte_frag;
struct page *page;
pte_frag = mm->context.pte_frag;
if (!pte_frag)
return;
page = virt_to_page(pte_frag);
/* drop all the pending references */
count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT;
/* We allow PTE_FRAG_NR fragments from a PTE page */
if (page_ref_sub_and_test(page, PTE_FRAG_NR - count)) {
pgtable_page_dtor(page);
free_hot_cold_page(page, 0);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 81 | 94.19% | 1 | 50.00% |
JoonSoo Kim | 5 | 5.81% | 1 | 50.00% |
Total | 86 | 100.00% | 2 | 100.00% |
#else
static inline void destroy_pagetable_page(struct mm_struct *mm)
{
return;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 13 | 100.00% | 1 | 100.00% |
Total | 13 | 100.00% | 1 | 100.00% |
#endif
void destroy_context(struct mm_struct *mm)
{
#ifdef CONFIG_SPAPR_TCE_IOMMU
WARN_ON_ONCE(!list_empty(&mm->context.iommu_group_mem_list));
#endif
if (radix_enabled()) {
/*
* Radix doesn't have a valid bit in the process table
* entries. However we know that at least P9 implementation
* will avoid caching an entry with an invalid RTS field,
* and 0 is invalid. So this will do.
*/
process_tb[mm->context.id].prtb0 = 0;
} else
subpage_prot_free(mm);
destroy_pagetable_page(mm);
__destroy_context(mm->context.id);
mm->context.id = MMU_NO_CONTEXT;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 28 | 35.90% | 2 | 22.22% |
Alexander Graf | 18 | 23.08% | 1 | 11.11% |
Alexey Kardashevskiy | 17 | 21.79% | 2 | 22.22% |
Paul Mackerras | 8 | 10.26% | 1 | 11.11% |
Benjamin Herrenschmidt | 4 | 5.13% | 1 | 11.11% |
Tseng-Hui (Frank) Lin | 2 | 2.56% | 1 | 11.11% |
Michael Ellerman | 1 | 1.28% | 1 | 11.11% |
Total | 78 | 100.00% | 9 | 100.00% |
#ifdef CONFIG_PPC_RADIX_MMU
void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
{
if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
isync();
mtspr(SPRN_PID, next->context.id);
isync();
asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
} else {
mtspr(SPRN_PID, next->context.id);
isync();
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Benjamin Herrenschmidt | 33 | 54.10% | 1 | 50.00% |
Aneesh Kumar K.V | 28 | 45.90% | 1 | 50.00% |
Total | 61 | 100.00% | 2 | 100.00% |
#endif
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Aneesh Kumar K.V | 337 | 41.66% | 8 | 25.81% |
Paul Mackerras | 151 | 18.67% | 1 | 3.23% |
Michael Ellerman | 112 | 13.84% | 4 | 12.90% |
Benjamin Herrenschmidt | 67 | 8.28% | 5 | 16.13% |
Alexander Graf | 55 | 6.80% | 1 | 3.23% |
Alexey Kardashevskiy | 27 | 3.34% | 2 | 6.45% |
Sonny Rao | 12 | 1.48% | 1 | 3.23% |
Anton Blanchard | 10 | 1.24% | 1 | 3.23% |
Alistair Popple | 8 | 0.99% | 1 | 3.23% |
Stephen Rothwell | 8 | 0.99% | 1 | 3.23% |
Tseng-Hui (Frank) Lin | 7 | 0.87% | 1 | 3.23% |
JoonSoo Kim | 5 | 0.62% | 1 | 3.23% |
David Gibson | 4 | 0.49% | 1 | 3.23% |
Tejun Heo | 3 | 0.37% | 1 | 3.23% |
Jimi Xenidis | 2 | 0.25% | 1 | 3.23% |
Paul Gortmaker | 1 | 0.12% | 1 | 3.23% |
Total | 809 | 100.00% | 31 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.