arch/sparc/mm/leon_mm.c

Source file repositories/reference/linux-study-clean/arch/sparc/mm/leon_mm.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/mm/leon_mm.c
Extension
.c
Size
8192 bytes
Lines
347
Domain
Architecture Layer
Bucket
arch/sparc
Inferred role
Architecture Layer: implementation source
Status
source 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
/*
 *  linux/arch/sparc/mm/leon_m.c
 *
 * Copyright (C) 2004 Konrad Eisele (eiselekd@web.de, konrad@gaisler.com) Gaisler Research
 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
 *
 * do srmmu probe in software
 *
 */

#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/asi.h>
#include <asm/leon.h>
#include <asm/tlbflush.h>

#include "mm_32.h"

int leon_flush_during_switch = 1;
static int srmmu_swprobe_trace;

static inline unsigned long leon_get_ctable_ptr(void)
{
	unsigned int retval;

	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
			     "=r" (retval) :
			     "r" (SRMMU_CTXTBL_PTR),
			     "i" (ASI_LEON_MMUREGS));
	return (retval & SRMMU_CTX_PMASK) << 4;
}


unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr)
{

	unsigned int ctxtbl;
	unsigned int pgd, pmd, ped;
	unsigned int ptr;
	unsigned int lvl, pte;
	unsigned int ctx;
	unsigned int paddr_calc;

	if (srmmu_swprobe_trace)
		printk(KERN_INFO "swprobe: trace on\n");

	ctxtbl = leon_get_ctable_ptr();
	if (!(ctxtbl)) {
		if (srmmu_swprobe_trace)
			printk(KERN_INFO "swprobe: leon_get_ctable_ptr returned 0=>0\n");
		return 0;
	}
	if (!_pfn_valid(PFN(ctxtbl))) {
		if (srmmu_swprobe_trace)
			printk(KERN_INFO
			       "swprobe: !_pfn_valid(%x)=>0\n",
			       PFN(ctxtbl));
		return 0;
	}

	ctx = srmmu_get_context();
	if (srmmu_swprobe_trace)
		printk(KERN_INFO "swprobe:  --- ctx (%x) ---\n", ctx);

	pgd = LEON_BYPASS_LOAD_PA(ctxtbl + (ctx * 4));

	if (((pgd & SRMMU_ET_MASK) == SRMMU_ET_PTE)) {
		if (srmmu_swprobe_trace)
			printk(KERN_INFO "swprobe: pgd is entry level 3\n");
		lvl = 3;
		pte = pgd;
		goto ready;
	}
	if (((pgd & SRMMU_ET_MASK) != SRMMU_ET_PTD)) {
		if (srmmu_swprobe_trace)
			printk(KERN_INFO "swprobe: pgd is invalid => 0\n");
		return 0;
	}

	if (srmmu_swprobe_trace)
		printk(KERN_INFO "swprobe:  --- pgd (%x) ---\n", pgd);

	ptr = (pgd & SRMMU_PTD_PMASK) << 4;
	ptr += ((((vaddr) >> LEON_PGD_SH) & LEON_PGD_M) * 4);
	if (!_pfn_valid(PFN(ptr)))
		return 0;

	pmd = LEON_BYPASS_LOAD_PA(ptr);

Annotation

Implementation Notes