arch/powerpc/mm/book3s64/hash_tlb.c

Source file repositories/reference/linux-study-clean/arch/powerpc/mm/book3s64/hash_tlb.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/mm/book3s64/hash_tlb.c
Extension
.c
Size
7421 bytes
Lines
257
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * This file contains the routines for flushing entries from the
 * TLB and MMU hash table.
 *
 *  Derived from arch/ppc64/mm/init.c:
 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
 *
 *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
 *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
 *    Copyright (C) 1996 Paul Mackerras
 *
 *  Derived from "arch/i386/mm/init.c"
 *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
 *
 *  Dave Engebretsen <engebret@us.ibm.com>
 *      Rework for PPC64 port.
 */

#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
#include <asm/bug.h>
#include <asm/pte-walk.h>
#include <kunit/visibility.h>

#include <trace/events/thp.h>

DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
EXPORT_SYMBOL_IF_KUNIT(ppc64_tlb_batch);

/*
 * A linux PTE was changed and the corresponding hash table entry
 * neesd to be flushed. This function will either perform the flush
 * immediately or will batch it up if the current CPU has an active
 * batch on it.
 */
void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
		     pte_t *ptep, unsigned long pte, int huge)
{
	unsigned long vpn;
	struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
	unsigned long vsid;
	unsigned int psize;
	int ssize;
	real_pte_t rpte;
	int i, offset;

	i = batch->index;

	/*
	 * Get page size (maybe move back to caller).
	 *
	 * NOTE: when using special 64K mappings in 4K environment like
	 * for SPEs, we obtain the page size from the slice, which thus
	 * must still exist (and thus the VMA not reused) at the time
	 * of this call
	 */
	if (huge) {
#ifdef CONFIG_HUGETLB_PAGE
		psize = get_slice_psize(mm, addr);
		/* Mask the address for the correct page size */
		addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1);
		if (unlikely(psize == MMU_PAGE_16G))
			offset = PTRS_PER_PUD;
		else
			offset = PTRS_PER_PMD;
#else
		BUG();
		psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
#endif
	} else {
		psize = pte_pagesize_index(mm, addr, pte);
		/*
		 * Mask the address for the standard page size.  If we
		 * have a 64k page kernel, but the hardware does not
		 * support 64k pages, this might be different from the
		 * hardware page size encoded in the slice table.
		 */
		addr &= PAGE_MASK;
		offset = PTRS_PER_PTE;
	}


	/* Build full vaddr */
	if (!is_kernel_addr(addr)) {
		ssize = user_segment_size(addr);

Annotation

Implementation Notes