arch/m68k/mm/mcfmmu.c

Source file repositories/reference/linux-study-clean/arch/m68k/mm/mcfmmu.c

File Facts

System
Linux kernel
Corpus path
arch/m68k/mm/mcfmmu.c
Extension
.c
Size
7264 bytes
Lines
271
Domain
Architecture Layer
Bucket
arch/m68k
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
/*
 * Based upon linux/arch/m68k/mm/sun3mmu.c
 * Based upon linux/arch/ppc/mm/mmu_context.c
 *
 * Implementations of mm routines specific to the Coldfire MMU.
 *
 * Copyright (c) 2008 Freescale Semiconductor, Inc.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/memblock.h>

#include <asm/setup.h>
#include <asm/page.h>
#include <asm/mmu_context.h>
#include <asm/mcf_pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>

#define KMAPAREA(x)	((x >= VMALLOC_START) && (x < KMAP_END))

mm_context_t next_mmu_context;
unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
atomic_t nr_free_contexts;
struct mm_struct *context_mm[LAST_CONTEXT+1];
unsigned long num_pages;

/*
 * ColdFire paging_init derived from sun3.
 */
void __init paging_init(void)
{
	pgd_t *pg_dir;
	pte_t *pg_table;
	unsigned long address, size;
	unsigned long next_pgtable;
	int i;

	pg_dir = swapper_pg_dir;
	memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));

	size = num_pages * sizeof(pte_t);
	size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
	next_pgtable = (unsigned long) memblock_alloc_or_panic(size, PAGE_SIZE);

	pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;

	address = PAGE_OFFSET;
	while (address < (unsigned long)high_memory) {
		pg_table = (pte_t *) next_pgtable;
		next_pgtable += PTRS_PER_PTE * sizeof(pte_t);
		pgd_val(*pg_dir) = (unsigned long) pg_table;
		pg_dir++;

		/* now change pg_table to kernel virtual addresses */
		for (i = 0; i < PTRS_PER_PTE; ++i, ++pg_table) {
			pte_t pte = pfn_pte(virt_to_pfn((void *)address),
					    PAGE_INIT);
			if (address >= (unsigned long) high_memory)
				pte_val(pte) = 0;

			set_pte(pg_table, pte);
			address += PAGE_SIZE;
		}
	}

	current->mm = NULL;
}

int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
{
	unsigned long flags, mmuar, mmutr;
	struct mm_struct *mm;
	pgd_t *pgd;
	p4d_t *p4d;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte = NULL;
	int ret = -1;
	int asid;

	local_irq_save(flags);

	mmuar = (dtlb) ? mmu_read(MMUAR) :
		regs->pc + (extension_word * sizeof(long));

Annotation

Implementation Notes