diff options
Diffstat (limited to 'arch/metag/mm/mmu-meta2.c')
-rw-r--r-- | arch/metag/mm/mmu-meta2.c | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/arch/metag/mm/mmu-meta2.c b/arch/metag/mm/mmu-meta2.c deleted file mode 100644 index 8b668a69c980..000000000000 --- a/arch/metag/mm/mmu-meta2.c +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2008,2009,2010,2011 Imagination Technologies Ltd. - * - * Meta 2 enhanced mode MMU handling code. - * - */ - -#include <linux/mm.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/bootmem.h> -#include <linux/syscore_ops.h> - -#include <asm/mmu.h> -#include <asm/mmu_context.h> - -unsigned long mmu_read_first_level_page(unsigned long vaddr) -{ - unsigned int cpu = hard_processor_id(); - unsigned long offset, linear_base, linear_limit; - unsigned int phys0; - pgd_t *pgd, entry; - - if (is_global_space(vaddr)) - vaddr &= ~0x80000000; - - offset = vaddr >> PGDIR_SHIFT; - - phys0 = metag_in32(mmu_phys0_addr(cpu)); - - /* Top bit of linear base is always zero. */ - linear_base = (phys0 >> PGDIR_SHIFT) & 0x1ff; - - /* Limit in the range 0 (4MB) to 9 (2GB). */ - linear_limit = 1 << ((phys0 >> 8) & 0xf); - linear_limit += linear_base; - - /* - * If offset is below linear base or above the limit then no - * mapping exists. - */ - if (offset < linear_base || offset > linear_limit) - return 0; - - offset -= linear_base; - pgd = (pgd_t *)mmu_get_base(); - entry = pgd[offset]; - - return pgd_val(entry); -} - -unsigned long mmu_read_second_level_page(unsigned long vaddr) -{ - return __builtin_meta2_cacherd((void *)(vaddr & PAGE_MASK)); -} - -unsigned long mmu_get_base(void) -{ - unsigned int cpu = hard_processor_id(); - unsigned long stride; - - stride = cpu * LINSYSMEMTnX_STRIDE; - - /* - * Bits 18:2 of the MMCU_TnLocal_TABLE_PHYS1 register should be - * used as an offset to the start of the top-level pgd table. - */ - stride += (metag_in32(mmu_phys1_addr(cpu)) & 0x7fffc); - - if (is_global_space(PAGE_OFFSET)) - stride += LINSYSMEMTXG_OFFSET; - - return LINSYSMEMT0L_BASE + stride; -} - -#define FIRST_LEVEL_MASK 0xffffffc0 -#define SECOND_LEVEL_MASK 0xfffff000 -#define SECOND_LEVEL_ALIGN 64 - -static void repriv_mmu_tables(void) -{ - unsigned long phys0_addr; - unsigned int g; - - /* - * Check that all the mmu table regions are priv protected, and if not - * fix them and emit a warning. If we left them without priv protection - * then userland processes would have access to a 2M window into - * physical memory near where the page tables are. - */ - phys0_addr = MMCU_T0LOCAL_TABLE_PHYS0; - for (g = 0; g < 2; ++g) { - unsigned int t, phys0; - unsigned long flags; - for (t = 0; t < 4; ++t) { - __global_lock2(flags); - phys0 = metag_in32(phys0_addr); - if ((phys0 & _PAGE_PRESENT) && !(phys0 & _PAGE_PRIV)) { - pr_warn("Fixing priv protection on T%d %s MMU table region\n", - t, - g ? "global" : "local"); - phys0 |= _PAGE_PRIV; - metag_out32(phys0, phys0_addr); - } - __global_unlock2(flags); - - phys0_addr += MMCU_TnX_TABLE_PHYSX_STRIDE; - } - - phys0_addr += MMCU_TXG_TABLE_PHYSX_OFFSET - - 4*MMCU_TnX_TABLE_PHYSX_STRIDE; - } -} - -#ifdef CONFIG_METAG_SUSPEND_MEM -static void mmu_resume(void) -{ - /* - * If a full suspend to RAM has happened then the original bad MMU table - * priv may have been restored, so repriv them again. - */ - repriv_mmu_tables(); -} -#else -#define mmu_resume NULL -#endif /* CONFIG_METAG_SUSPEND_MEM */ - -static struct syscore_ops mmu_syscore_ops = { - .resume = mmu_resume, -}; - -void __init mmu_init(unsigned long mem_end) -{ - unsigned long entry, addr; - pgd_t *p_swapper_pg_dir; -#ifdef CONFIG_KERNEL_4M_PAGES - unsigned long mem_size = mem_end - PAGE_OFFSET; - unsigned int pages = DIV_ROUND_UP(mem_size, 1 << 22); - unsigned int second_level_entry = 0; - unsigned long *second_level_table; -#endif - - /* - * Now copy over any MMU pgd entries already in the mmu page tables - * over to our root init process (swapper_pg_dir) map. This map is - * then inherited by all other processes, which means all processes - * inherit a map of the kernel space. - */ - addr = META_MEMORY_BASE; - entry = pgd_index(META_MEMORY_BASE); - p_swapper_pg_dir = pgd_offset_k(0) + entry; - - while (entry < (PTRS_PER_PGD - pgd_index(META_MEMORY_BASE))) { - unsigned long pgd_entry; - /* copy over the current MMU value */ - pgd_entry = mmu_read_first_level_page(addr); - pgd_val(*p_swapper_pg_dir) = pgd_entry; - - p_swapper_pg_dir++; - addr += PGDIR_SIZE; - entry++; - } - -#ifdef CONFIG_KERNEL_4M_PAGES - /* - * At this point we can also map the kernel with 4MB pages to - * reduce TLB pressure. - */ - second_level_table = alloc_bootmem_pages(SECOND_LEVEL_ALIGN * pages); - - addr = PAGE_OFFSET; - entry = pgd_index(PAGE_OFFSET); - p_swapper_pg_dir = pgd_offset_k(0) + entry; - - while (pages > 0) { - unsigned long phys_addr, second_level_phys; - pte_t *pte = (pte_t *)&second_level_table[second_level_entry]; - - phys_addr = __pa(addr); - - second_level_phys = __pa(pte); - - pgd_val(*p_swapper_pg_dir) = ((second_level_phys & - FIRST_LEVEL_MASK) | - _PAGE_SZ_4M | - _PAGE_PRESENT); - - pte_val(*pte) = ((phys_addr & SECOND_LEVEL_MASK) | - _PAGE_PRESENT | _PAGE_DIRTY | - _PAGE_ACCESSED | _PAGE_WRITE | - _PAGE_CACHEABLE | _PAGE_KERNEL); - - p_swapper_pg_dir++; - addr += PGDIR_SIZE; - /* Second level pages must be 64byte aligned. */ - second_level_entry += (SECOND_LEVEL_ALIGN / - sizeof(unsigned long)); - pages--; - } - load_pgd(swapper_pg_dir, hard_processor_id()); - flush_tlb_all(); -#endif - - repriv_mmu_tables(); - register_syscore_ops(&mmu_syscore_ops); -} |