summaryrefslogtreecommitdiff
path: root/arch/unicore32/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/unicore32/mm')
-rw-r--r--arch/unicore32/mm/Kconfig41
-rw-r--r--arch/unicore32/mm/Makefile14
-rw-r--r--arch/unicore32/mm/alignment.c524
-rw-r--r--arch/unicore32/mm/cache-ucv2.S209
-rw-r--r--arch/unicore32/mm/extable.c21
-rw-r--r--arch/unicore32/mm/fault.c481
-rw-r--r--arch/unicore32/mm/flush.c94
-rw-r--r--arch/unicore32/mm/init.c261
-rw-r--r--arch/unicore32/mm/ioremap.c242
-rw-r--r--arch/unicore32/mm/mm.h31
-rw-r--r--arch/unicore32/mm/mmu.c513
-rw-r--r--arch/unicore32/mm/pgd.c102
-rw-r--r--arch/unicore32/mm/proc-macros.S142
-rw-r--r--arch/unicore32/mm/proc-syms.c19
-rw-r--r--arch/unicore32/mm/proc-ucv2.S131
-rw-r--r--arch/unicore32/mm/tlb-ucv2.S86
16 files changed, 0 insertions, 2911 deletions
diff --git a/arch/unicore32/mm/Kconfig b/arch/unicore32/mm/Kconfig
deleted file mode 100644
index 82759b6aba67..000000000000
--- a/arch/unicore32/mm/Kconfig
+++ /dev/null
@@ -1,41 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-comment "Processor Type"
-
-# Select CPU types depending on the architecture selected. This selects
-# which CPUs we support in the kernel image, and the compiler instruction
-# optimiser behaviour.
-
-config CPU_UCV2
- def_bool y
-
-comment "Processor Features"
-
-config CPU_ICACHE_DISABLE
- bool "Disable I-Cache (I-bit)"
- help
- Say Y here to disable the processor instruction cache. Unless
- you have a reason not to or are unsure, say N.
-
-config CPU_DCACHE_DISABLE
- bool "Disable D-Cache (D-bit)"
- help
- Say Y here to disable the processor data cache. Unless
- you have a reason not to or are unsure, say N.
-
-config CPU_DCACHE_WRITETHROUGH
- bool "Force write through D-cache"
- help
- Say Y here to use the data cache in writethrough mode. Unless you
- specifically require this or are unsure, say N.
-
-config CPU_DCACHE_LINE_DISABLE
- bool "Disable D-cache line ops"
- default y
- help
- Say Y here to disable the data cache line operations.
-
-config CPU_TLB_SINGLE_ENTRY_DISABLE
- bool "Disable TLB single entry ops"
- default y
- help
- Say Y here to disable the TLB single entry operations.
diff --git a/arch/unicore32/mm/Makefile b/arch/unicore32/mm/Makefile
deleted file mode 100644
index 8106260583ab..000000000000
--- a/arch/unicore32/mm/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the linux unicore-specific parts of the memory manager.
-#
-
-obj-y := extable.o fault.o init.o pgd.o mmu.o
-obj-y += flush.o ioremap.o
-
-obj-$(CONFIG_MODULES) += proc-syms.o
-
-obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
-
-obj-$(CONFIG_CPU_UCV2) += cache-ucv2.o tlb-ucv2.o proc-ucv2.o
-
diff --git a/arch/unicore32/mm/alignment.c b/arch/unicore32/mm/alignment.c
deleted file mode 100644
index 2ea98f7a4156..000000000000
--- a/arch/unicore32/mm/alignment.c
+++ /dev/null
@@ -1,524 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/alignment.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-/*
- * TODO:
- * FPU ldm/stm not handling
- */
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/sched/debug.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/uaccess.h>
-#include <linux/pgtable.h>
-
-#include <asm/tlbflush.h>
-#include <asm/unaligned.h>
-
-#include "mm.h"
-
-#define CODING_BITS(i) (i & 0xe0000120)
-
-#define LDST_P_BIT(i) (i & (1 << 28)) /* Preindex */
-#define LDST_U_BIT(i) (i & (1 << 27)) /* Add offset */
-#define LDST_W_BIT(i) (i & (1 << 25)) /* Writeback */
-#define LDST_L_BIT(i) (i & (1 << 24)) /* Load */
-
-#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 27)) == 0)
-
-#define LDSTH_I_BIT(i) (i & (1 << 26)) /* half-word immed */
-#define LDM_S_BIT(i) (i & (1 << 26)) /* write ASR from BSR */
-#define LDM_H_BIT(i) (i & (1 << 6)) /* select r0-r15 or r16-r31 */
-
-#define RN_BITS(i) ((i >> 19) & 31) /* Rn */
-#define RD_BITS(i) ((i >> 14) & 31) /* Rd */
-#define RM_BITS(i) (i & 31) /* Rm */
-
-#define REGMASK_BITS(i) (((i & 0x7fe00) >> 3) | (i & 0x3f))
-#define OFFSET_BITS(i) (i & 0x03fff)
-
-#define SHIFT_BITS(i) ((i >> 9) & 0x1f)
-#define SHIFT_TYPE(i) (i & 0xc0)
-#define SHIFT_LSL 0x00
-#define SHIFT_LSR 0x40
-#define SHIFT_ASR 0x80
-#define SHIFT_RORRRX 0xc0
-
-union offset_union {
- unsigned long un;
- signed long sn;
-};
-
-#define TYPE_ERROR 0
-#define TYPE_FAULT 1
-#define TYPE_LDST 2
-#define TYPE_DONE 3
-#define TYPE_SWAP 4
-#define TYPE_COLS 5 /* Coprocessor load/store */
-
-#define get8_unaligned_check(val, addr, err) \
- __asm__( \
- "1: ldb.u %1, [%2], #1\n" \
- "2:\n" \
- " .pushsection .fixup,\"ax\"\n" \
- " .align 2\n" \
- "3: mov %0, #1\n" \
- " b 2b\n" \
- " .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .popsection\n" \
- : "=r" (err), "=&r" (val), "=r" (addr) \
- : "0" (err), "2" (addr))
-
-#define get8t_unaligned_check(val, addr, err) \
- __asm__( \
- "1: ldb.u %1, [%2], #1\n" \
- "2:\n" \
- " .pushsection .fixup,\"ax\"\n" \
- " .align 2\n" \
- "3: mov %0, #1\n" \
- " b 2b\n" \
- " .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .popsection\n" \
- : "=r" (err), "=&r" (val), "=r" (addr) \
- : "0" (err), "2" (addr))
-
-#define get16_unaligned_check(val, addr) \
- do { \
- unsigned int err = 0, v, a = addr; \
- get8_unaligned_check(val, a, err); \
- get8_unaligned_check(v, a, err); \
- val |= v << 8; \
- if (err) \
- goto fault; \
- } while (0)
-
-#define put16_unaligned_check(val, addr) \
- do { \
- unsigned int err = 0, v = val, a = addr; \
- __asm__( \
- "1: stb.u %1, [%2], #1\n" \
- " mov %1, %1 >> #8\n" \
- "2: stb.u %1, [%2]\n" \
- "3:\n" \
- " .pushsection .fixup,\"ax\"\n" \
- " .align 2\n" \
- "4: mov %0, #1\n" \
- " b 3b\n" \
- " .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 4b\n" \
- " .long 2b, 4b\n" \
- " .popsection\n" \
- : "=r" (err), "=&r" (v), "=&r" (a) \
- : "0" (err), "1" (v), "2" (a)); \
- if (err) \
- goto fault; \
- } while (0)
-
-#define __put32_unaligned_check(ins, val, addr) \
- do { \
- unsigned int err = 0, v = val, a = addr; \
- __asm__( \
- "1: "ins" %1, [%2], #1\n" \
- " mov %1, %1 >> #8\n" \
- "2: "ins" %1, [%2], #1\n" \
- " mov %1, %1 >> #8\n" \
- "3: "ins" %1, [%2], #1\n" \
- " mov %1, %1 >> #8\n" \
- "4: "ins" %1, [%2]\n" \
- "5:\n" \
- " .pushsection .fixup,\"ax\"\n" \
- " .align 2\n" \
- "6: mov %0, #1\n" \
- " b 5b\n" \
- " .popsection\n" \
- " .pushsection __ex_table,\"a\"\n" \
- " .align 3\n" \
- " .long 1b, 6b\n" \
- " .long 2b, 6b\n" \
- " .long 3b, 6b\n" \
- " .long 4b, 6b\n" \
- " .popsection\n" \
- : "=r" (err), "=&r" (v), "=&r" (a) \
- : "0" (err), "1" (v), "2" (a)); \
- if (err) \
- goto fault; \
- } while (0)
-
-#define get32_unaligned_check(val, addr) \
- do { \
- unsigned int err = 0, v, a = addr; \
- get8_unaligned_check(val, a, err); \
- get8_unaligned_check(v, a, err); \
- val |= v << 8; \
- get8_unaligned_check(v, a, err); \
- val |= v << 16; \
- get8_unaligned_check(v, a, err); \
- val |= v << 24; \
- if (err) \
- goto fault; \
- } while (0)
-
-#define put32_unaligned_check(val, addr) \
- __put32_unaligned_check("stb.u", val, addr)
-
-#define get32t_unaligned_check(val, addr) \
- do { \
- unsigned int err = 0, v, a = addr; \
- get8t_unaligned_check(val, a, err); \
- get8t_unaligned_check(v, a, err); \
- val |= v << 8; \
- get8t_unaligned_check(v, a, err); \
- val |= v << 16; \
- get8t_unaligned_check(v, a, err); \
- val |= v << 24; \
- if (err) \
- goto fault; \
- } while (0)
-
-#define put32t_unaligned_check(val, addr) \
- __put32_unaligned_check("stb.u", val, addr)
-
-static void
-do_alignment_finish_ldst(unsigned long addr, unsigned long instr,
- struct pt_regs *regs, union offset_union offset)
-{
- if (!LDST_U_BIT(instr))
- offset.un = -offset.un;
-
- if (!LDST_P_BIT(instr))
- addr += offset.un;
-
- if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
- regs->uregs[RN_BITS(instr)] = addr;
-}
-
-static int
-do_alignment_ldrhstrh(unsigned long addr, unsigned long instr,
- struct pt_regs *regs)
-{
- unsigned int rd = RD_BITS(instr);
-
- /* old value 0x40002120, can't judge swap instr correctly */
- if ((instr & 0x4b003fe0) == 0x40000120)
- goto swp;
-
- if (LDST_L_BIT(instr)) {
- unsigned long val;
- get16_unaligned_check(val, addr);
-
- /* signed half-word? */
- if (instr & 0x80)
- val = (signed long)((signed short)val);
-
- regs->uregs[rd] = val;
- } else
- put16_unaligned_check(regs->uregs[rd], addr);
-
- return TYPE_LDST;
-
-swp:
- /* only handle swap word
- * for swap byte should not active this alignment exception */
- get32_unaligned_check(regs->uregs[RD_BITS(instr)], addr);
- put32_unaligned_check(regs->uregs[RM_BITS(instr)], addr);
- return TYPE_SWAP;
-
-fault:
- return TYPE_FAULT;
-}
-
-static int
-do_alignment_ldrstr(unsigned long addr, unsigned long instr,
- struct pt_regs *regs)
-{
- unsigned int rd = RD_BITS(instr);
-
- if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
- goto trans;
-
- if (LDST_L_BIT(instr))
- get32_unaligned_check(regs->uregs[rd], addr);
- else
- put32_unaligned_check(regs->uregs[rd], addr);
- return TYPE_LDST;
-
-trans:
- if (LDST_L_BIT(instr))
- get32t_unaligned_check(regs->uregs[rd], addr);
- else
- put32t_unaligned_check(regs->uregs[rd], addr);
- return TYPE_LDST;
-
-fault:
- return TYPE_FAULT;
-}
-
-/*
- * LDM/STM alignment handler.
- *
- * There are 4 variants of this instruction:
- *
- * B = rn pointer before instruction, A = rn pointer after instruction
- * ------ increasing address ----->
- * | | r0 | r1 | ... | rx | |
- * PU = 01 B A
- * PU = 11 B A
- * PU = 00 A B
- * PU = 10 A B
- */
-static int
-do_alignment_ldmstm(unsigned long addr, unsigned long instr,
- struct pt_regs *regs)
-{
- unsigned int rd, rn, pc_correction, reg_correction, nr_regs, regbits;
- unsigned long eaddr, newaddr;
-
- if (LDM_S_BIT(instr))
- goto bad;
-
- pc_correction = 4; /* processor implementation defined */
-
- /* count the number of registers in the mask to be transferred */
- nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
-
- rn = RN_BITS(instr);
- newaddr = eaddr = regs->uregs[rn];
-
- if (!LDST_U_BIT(instr))
- nr_regs = -nr_regs;
- newaddr += nr_regs;
- if (!LDST_U_BIT(instr))
- eaddr = newaddr;
-
- if (LDST_P_EQ_U(instr)) /* U = P */
- eaddr += 4;
-
- /*
- * This is a "hint" - we already have eaddr worked out by the
- * processor for us.
- */
- if (addr != eaddr) {
- printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
- "addr = %08lx, eaddr = %08lx\n",
- instruction_pointer(regs), instr, addr, eaddr);
- show_regs(regs);
- }
-
- if (LDM_H_BIT(instr))
- reg_correction = 0x10;
- else
- reg_correction = 0x00;
-
- for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
- regbits >>= 1, rd += 1)
- if (regbits & 1) {
- if (LDST_L_BIT(instr))
- get32_unaligned_check(regs->
- uregs[rd + reg_correction], eaddr);
- else
- put32_unaligned_check(regs->
- uregs[rd + reg_correction], eaddr);
- eaddr += 4;
- }
-
- if (LDST_W_BIT(instr))
- regs->uregs[rn] = newaddr;
- return TYPE_DONE;
-
-fault:
- regs->UCreg_pc -= pc_correction;
- return TYPE_FAULT;
-
-bad:
- printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
- return TYPE_ERROR;
-}
-
-static int
-do_alignment(unsigned long addr, unsigned int error_code, struct pt_regs *regs)
-{
- union offset_union offset;
- unsigned long instr, instrptr;
- int (*handler) (unsigned long addr, unsigned long instr,
- struct pt_regs *regs);
- unsigned int type;
-
- instrptr = instruction_pointer(regs);
- if (instrptr >= PAGE_OFFSET)
- instr = *(unsigned long *)instrptr;
- else {
- __asm__ __volatile__(
- "ldw.u %0, [%1]\n"
- : "=&r"(instr)
- : "r"(instrptr));
- }
-
- regs->UCreg_pc += 4;
-
- switch (CODING_BITS(instr)) {
- case 0x40000120: /* ldrh or strh */
- if (LDSTH_I_BIT(instr))
- offset.un = (instr & 0x3e00) >> 4 | (instr & 31);
- else
- offset.un = regs->uregs[RM_BITS(instr)];
- handler = do_alignment_ldrhstrh;
- break;
-
- case 0x60000000: /* ldr or str immediate */
- case 0x60000100: /* ldr or str immediate */
- case 0x60000020: /* ldr or str immediate */
- case 0x60000120: /* ldr or str immediate */
- offset.un = OFFSET_BITS(instr);
- handler = do_alignment_ldrstr;
- break;
-
- case 0x40000000: /* ldr or str register */
- offset.un = regs->uregs[RM_BITS(instr)];
- {
- unsigned int shiftval = SHIFT_BITS(instr);
-
- switch (SHIFT_TYPE(instr)) {
- case SHIFT_LSL:
- offset.un <<= shiftval;
- break;
-
- case SHIFT_LSR:
- offset.un >>= shiftval;
- break;
-
- case SHIFT_ASR:
- offset.sn >>= shiftval;
- break;
-
- case SHIFT_RORRRX:
- if (shiftval == 0) {
- offset.un >>= 1;
- if (regs->UCreg_asr & PSR_C_BIT)
- offset.un |= 1 << 31;
- } else
- offset.un = offset.un >> shiftval |
- offset.un << (32 - shiftval);
- break;
- }
- }
- handler = do_alignment_ldrstr;
- break;
-
- case 0x80000000: /* ldm or stm */
- case 0x80000020: /* ldm or stm */
- handler = do_alignment_ldmstm;
- break;
-
- default:
- goto bad;
- }
-
- type = handler(addr, instr, regs);
-
- if (type == TYPE_ERROR || type == TYPE_FAULT)
- goto bad_or_fault;
-
- if (type == TYPE_LDST)
- do_alignment_finish_ldst(addr, instr, regs, offset);
-
- return 0;
-
-bad_or_fault:
- if (type == TYPE_ERROR)
- goto bad;
- regs->UCreg_pc -= 4;
- /*
- * We got a fault - fix it up, or die.
- */
- do_bad_area(addr, error_code, regs);
- return 0;
-
-bad:
- /*
- * Oops, we didn't handle the instruction.
- * However, we must handle fpu instr firstly.
- */
-#ifdef CONFIG_UNICORE_FPU_F64
- /* handle co.load/store */
-#define CODING_COLS 0xc0000000
-#define COLS_OFFSET_BITS(i) (i & 0x1FF)
-#define COLS_L_BITS(i) (i & (1<<24))
-#define COLS_FN_BITS(i) ((i>>14) & 31)
- if ((instr & 0xe0000000) == CODING_COLS) {
- unsigned int fn = COLS_FN_BITS(instr);
- unsigned long val = 0;
- if (COLS_L_BITS(instr)) {
- get32t_unaligned_check(val, addr);
- switch (fn) {
-#define ASM_MTF(n) case n: \
- __asm__ __volatile__("MTF %0, F" __stringify(n) \
- : : "r"(val)); \
- break;
- ASM_MTF(0); ASM_MTF(1); ASM_MTF(2); ASM_MTF(3);
- ASM_MTF(4); ASM_MTF(5); ASM_MTF(6); ASM_MTF(7);
- ASM_MTF(8); ASM_MTF(9); ASM_MTF(10); ASM_MTF(11);
- ASM_MTF(12); ASM_MTF(13); ASM_MTF(14); ASM_MTF(15);
- ASM_MTF(16); ASM_MTF(17); ASM_MTF(18); ASM_MTF(19);
- ASM_MTF(20); ASM_MTF(21); ASM_MTF(22); ASM_MTF(23);
- ASM_MTF(24); ASM_MTF(25); ASM_MTF(26); ASM_MTF(27);
- ASM_MTF(28); ASM_MTF(29); ASM_MTF(30); ASM_MTF(31);
-#undef ASM_MTF
- }
- } else {
- switch (fn) {
-#define ASM_MFF(n) case n: \
- __asm__ __volatile__("MFF %0, F" __stringify(n) \
- : : "r"(val)); \
- break;
- ASM_MFF(0); ASM_MFF(1); ASM_MFF(2); ASM_MFF(3);
- ASM_MFF(4); ASM_MFF(5); ASM_MFF(6); ASM_MFF(7);
- ASM_MFF(8); ASM_MFF(9); ASM_MFF(10); ASM_MFF(11);
- ASM_MFF(12); ASM_MFF(13); ASM_MFF(14); ASM_MFF(15);
- ASM_MFF(16); ASM_MFF(17); ASM_MFF(18); ASM_MFF(19);
- ASM_MFF(20); ASM_MFF(21); ASM_MFF(22); ASM_MFF(23);
- ASM_MFF(24); ASM_MFF(25); ASM_MFF(26); ASM_MFF(27);
- ASM_MFF(28); ASM_MFF(29); ASM_MFF(30); ASM_MFF(31);
-#undef ASM_MFF
- }
- put32t_unaligned_check(val, addr);
- }
- return TYPE_COLS;
- }
-fault:
- return TYPE_FAULT;
-#endif
- printk(KERN_ERR "Alignment trap: not handling instruction "
- "%08lx at [<%08lx>]\n", instr, instrptr);
- return 1;
-}
-
-/*
- * This needs to be done after sysctl_init, otherwise sys/ will be
- * overwritten. Actually, this shouldn't be in sys/ at all since
- * it isn't a sysctl, and it doesn't contain sysctl information.
- */
-static int __init alignment_init(void)
-{
- hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
- "alignment exception");
-
- return 0;
-}
-
-fs_initcall(alignment_init);
diff --git a/arch/unicore32/mm/cache-ucv2.S b/arch/unicore32/mm/cache-ucv2.S
deleted file mode 100644
index 2108837d6f4f..000000000000
--- a/arch/unicore32/mm/cache-ucv2.S
+++ /dev/null
@@ -1,209 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/unicore32/mm/cache-ucv2.S
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * This is the "shell" of the UniCore-v2 processor support.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/assembler.h>
-#include <asm/page.h>
-
-#include "proc-macros.S"
-
-/*
- * __cpuc_flush_icache_all()
- * __cpuc_flush_kern_all()
- * __cpuc_flush_user_all()
- *
- * Flush the entire cache.
- */
-ENTRY(__cpuc_flush_icache_all)
- /*FALLTHROUGH*/
-ENTRY(__cpuc_flush_kern_all)
- /*FALLTHROUGH*/
-ENTRY(__cpuc_flush_user_all)
- mov r0, #0
- movc p0.c5, r0, #14 @ Dcache flush all
- nop8
-
- mov r0, #0
- movc p0.c5, r0, #20 @ Icache invalidate all
- nop8
-
- mov pc, lr
-
-/*
- * __cpuc_flush_user_range(start, end, flags)
- *
- * Flush a range of TLB entries in the specified address space.
- *
- * - start - start address (may not be aligned)
- * - end - end address (exclusive, may not be aligned)
- * - flags - vm_area_struct flags describing address space
- */
-ENTRY(__cpuc_flush_user_range)
- cxor.a r2, #0
- beq __cpuc_dma_flush_range
-
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
- andn r0, r0, #CACHE_LINESIZE - 1 @ Safety check
- sub r1, r1, r0
- csub.a r1, #MAX_AREA_SIZE
- bsg 2f
-
- andn r1, r1, #CACHE_LINESIZE - 1
- add r1, r1, #CACHE_LINESIZE
-
-101: dcacheline_flush r0, r11, r12
-
- add r0, r0, #CACHE_LINESIZE
- sub.a r1, r1, #CACHE_LINESIZE
- bns 101b
- b 3f
-#endif
-2: mov ip, #0
- movc p0.c5, ip, #14 @ Dcache flush all
- nop8
-
-3: mov ip, #0
- movc p0.c5, ip, #20 @ Icache invalidate all
- nop8
-
- mov pc, lr
-
-/*
- * __cpuc_coherent_kern_range(start,end)
- * __cpuc_coherent_user_range(start,end)
- *
- * Ensure that the I and D caches are coherent within specified
- * region. This is typically used when code has been written to
- * a memory region, and will be executed.
- *
- * - start - virtual start address of region
- * - end - virtual end address of region
- */
-ENTRY(__cpuc_coherent_kern_range)
- /* FALLTHROUGH */
-ENTRY(__cpuc_coherent_user_range)
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
- andn r0, r0, #CACHE_LINESIZE - 1 @ Safety check
- sub r1, r1, r0
- csub.a r1, #MAX_AREA_SIZE
- bsg 2f
-
- andn r1, r1, #CACHE_LINESIZE - 1
- add r1, r1, #CACHE_LINESIZE
-
- @ r0 va2pa r10
- mov r9, #PAGE_SZ
- sub r9, r9, #1 @ PAGE_MASK
-101: va2pa r0, r10, r11, r12, r13, 2f @ r10 is PA
- b 103f
-102: cand.a r0, r9
- beq 101b
-
-103: movc p0.c5, r10, #11 @ Dcache clean line of R10
- nop8
-
- add r0, r0, #CACHE_LINESIZE
- add r10, r10, #CACHE_LINESIZE
- sub.a r1, r1, #CACHE_LINESIZE
- bns 102b
- b 3f
-#endif
-2: mov ip, #0
- movc p0.c5, ip, #10 @ Dcache clean all
- nop8
-
-3: mov ip, #0
- movc p0.c5, ip, #20 @ Icache invalidate all
- nop8
-
- mov pc, lr
-
-/*
- * __cpuc_flush_kern_dcache_area(void *addr, size_t size)
- *
- * - addr - kernel address
- * - size - region size
- */
-ENTRY(__cpuc_flush_kern_dcache_area)
- mov ip, #0
- movc p0.c5, ip, #14 @ Dcache flush all
- nop8
- mov pc, lr
-
-/*
- * __cpuc_dma_clean_range(start,end)
- * - start - virtual start address of region
- * - end - virtual end address of region
- */
-ENTRY(__cpuc_dma_clean_range)
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
- andn r0, r0, #CACHE_LINESIZE - 1
- sub r1, r1, r0
- andn r1, r1, #CACHE_LINESIZE - 1
- add r1, r1, #CACHE_LINESIZE
-
- csub.a r1, #MAX_AREA_SIZE
- bsg 2f
-
- @ r0 va2pa r10
- mov r9, #PAGE_SZ
- sub r9, r9, #1 @ PAGE_MASK
-101: va2pa r0, r10, r11, r12, r13, 2f @ r10 is PA
- b 1f
-102: cand.a r0, r9
- beq 101b
-
-1: movc p0.c5, r10, #11 @ Dcache clean line of R10
- nop8
- add r0, r0, #CACHE_LINESIZE
- add r10, r10, #CACHE_LINESIZE
- sub.a r1, r1, #CACHE_LINESIZE
- bns 102b
- mov pc, lr
-#endif
-2: mov ip, #0
- movc p0.c5, ip, #10 @ Dcache clean all
- nop8
-
- mov pc, lr
-
-/*
- * __cpuc_dma_inv_range(start,end)
- * __cpuc_dma_flush_range(start,end)
- * - start - virtual start address of region
- * - end - virtual end address of region
- */
-__cpuc_dma_inv_range:
- /* FALLTHROUGH */
-ENTRY(__cpuc_dma_flush_range)
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
- andn r0, r0, #CACHE_LINESIZE - 1
- sub r1, r1, r0
- andn r1, r1, #CACHE_LINESIZE - 1
- add r1, r1, #CACHE_LINESIZE
-
- csub.a r1, #MAX_AREA_SIZE
- bsg 2f
-
- @ r0 va2pa r10
-101: dcacheline_flush r0, r11, r12
-
- add r0, r0, #CACHE_LINESIZE
- sub.a r1, r1, #CACHE_LINESIZE
- bns 101b
- mov pc, lr
-#endif
-2: mov ip, #0
- movc p0.c5, ip, #14 @ Dcache flush all
- nop8
-
- mov pc, lr
-
diff --git a/arch/unicore32/mm/extable.c b/arch/unicore32/mm/extable.c
deleted file mode 100644
index e53352b41c4a..000000000000
--- a/arch/unicore32/mm/extable.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/extable.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/extable.h>
-#include <linux/uaccess.h>
-
-int fixup_exception(struct pt_regs *regs)
-{
- const struct exception_table_entry *fixup;
-
- fixup = search_exception_tables(instruction_pointer(regs));
- if (fixup)
- regs->UCreg_pc = fixup->fixup;
-
- return fixup != NULL;
-}
diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c
deleted file mode 100644
index 7654bddde133..000000000000
--- a/arch/unicore32/mm/fault.c
+++ /dev/null
@@ -1,481 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/fault.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/extable.h>
-#include <linux/signal.h>
-#include <linux/mm.h>
-#include <linux/hardirq.h>
-#include <linux/init.h>
-#include <linux/kprobes.h>
-#include <linux/uaccess.h>
-#include <linux/page-flags.h>
-#include <linux/sched/signal.h>
-#include <linux/io.h>
-
-#include <asm/tlbflush.h>
-
-/*
- * Fault status register encodings. We steal bit 31 for our own purposes.
- */
-#define FSR_LNX_PF (1 << 31)
-
-static inline int fsr_fs(unsigned int fsr)
-{
- /* xyabcde will be abcde+xy */
- return (fsr & 31) + ((fsr & (3 << 5)) >> 5);
-}
-
-/*
- * This is useful to dump out the page tables associated with
- * 'addr' in mm 'mm'.
- */
-void show_pte(struct mm_struct *mm, unsigned long addr)
-{
- pgd_t *pgd;
-
- if (!mm)
- mm = &init_mm;
-
- printk(KERN_ALERT "pgd = %p\n", mm->pgd);
- pgd = pgd_offset(mm, addr);
- printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
-
- do {
- pmd_t *pmd;
- pte_t *pte;
-
- if (pgd_none(*pgd))
- break;
-
- if (pgd_bad(*pgd)) {
- printk("(bad)");
- break;
- }
-
- pmd = pmd_offset((pud_t *) pgd, addr);
- if (PTRS_PER_PMD != 1)
- printk(", *pmd=%08lx", pmd_val(*pmd));
-
- if (pmd_none(*pmd))
- break;
-
- if (pmd_bad(*pmd)) {
- printk("(bad)");
- break;
- }
-
- /* We must not map this if we have highmem enabled */
- if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
- break;
-
- pte = pte_offset_map(pmd, addr);
- printk(", *pte=%08lx", pte_val(*pte));
- pte_unmap(pte);
- } while (0);
-
- printk("\n");
-}
-
-/*
- * Oops. The kernel tried to access some page that wasn't present.
- */
-static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
- unsigned int fsr, struct pt_regs *regs)
-{
- /*
- * Are we prepared to handle this kernel fault?
- */
- if (fixup_exception(regs))
- return;
-
- /*
- * No handler, we'll have to terminate things with extreme prejudice.
- */
- bust_spinlocks(1);
- printk(KERN_ALERT
- "Unable to handle kernel %s at virtual address %08lx\n",
- (addr < PAGE_SIZE) ? "NULL pointer dereference" :
- "paging request", addr);
-
- show_pte(mm, addr);
- die("Oops", regs, fsr);
- bust_spinlocks(0);
- do_exit(SIGKILL);
-}
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * User mode accesses just cause a SIGSEGV
- */
-static void __do_user_fault(unsigned long addr, unsigned int fsr,
- unsigned int sig, int code, struct pt_regs *regs)
-{
- struct task_struct *tsk = current;
-
- tsk->thread.address = addr;
- tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- force_sig_fault(sig, code, (void __user *)addr);
-}
-
-void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- struct task_struct *tsk = current;
- struct mm_struct *mm = tsk->active_mm;
-
- /*
- * If we are in kernel mode at this point, we
- * have no context to handle this fault with.
- */
- if (user_mode(regs))
- __do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
- else
- __do_kernel_fault(mm, addr, fsr, regs);
-}
-
-#define VM_FAULT_BADMAP 0x010000
-#define VM_FAULT_BADACCESS 0x020000
-
-/*
- * Check that the permissions on the VMA allow for the fault which occurred.
- * If we encountered a write fault, we must have write permission, otherwise
- * we allow any permission.
- */
-static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
-{
- unsigned int mask = VM_ACCESS_FLAGS;
-
- if (!(fsr ^ 0x12)) /* write? */
- mask = VM_WRITE;
- if (fsr & FSR_LNX_PF)
- mask = VM_EXEC;
-
- return vma->vm_flags & mask ? false : true;
-}
-
-static vm_fault_t __do_pf(struct mm_struct *mm, unsigned long addr,
- unsigned int fsr, unsigned int flags, struct task_struct *tsk)
-{
- struct vm_area_struct *vma;
- vm_fault_t fault;
-
- vma = find_vma(mm, addr);
- fault = VM_FAULT_BADMAP;
- if (unlikely(!vma))
- goto out;
- if (unlikely(vma->vm_start > addr))
- goto check_stack;
-
- /*
- * Ok, we have a good vm_area for this
- * memory access, so we can handle it.
- */
-good_area:
- if (access_error(fsr, vma)) {
- fault = VM_FAULT_BADACCESS;
- goto out;
- }
-
- /*
- * If for any reason at all we couldn't handle the fault, make
- * sure we exit gracefully rather than endlessly redo the fault.
- */
- fault = handle_mm_fault(vma, addr & PAGE_MASK, flags);
- return fault;
-
-check_stack:
- if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
- goto good_area;
-out:
- return fault;
-}
-
-static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- struct task_struct *tsk;
- struct mm_struct *mm;
- int sig, code;
- vm_fault_t fault;
- unsigned int flags = FAULT_FLAG_DEFAULT;
-
- tsk = current;
- mm = tsk->mm;
-
- /*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
- */
- if (faulthandler_disabled() || !mm)
- goto no_context;
-
- if (user_mode(regs))
- flags |= FAULT_FLAG_USER;
- if (!(fsr ^ 0x12))
- flags |= FAULT_FLAG_WRITE;
-
- /*
- * As per x86, we may deadlock here. However, since the kernel only
- * validly references user space from well defined areas of the code,
- * we can bug out early if this is from code which shouldn't.
- */
- if (!mmap_read_trylock(mm)) {
- if (!user_mode(regs)
- && !search_exception_tables(regs->UCreg_pc))
- goto no_context;
-retry:
- mmap_read_lock(mm);
- } else {
- /*
- * The above down_read_trylock() might have succeeded in
- * which case, we'll have missed the might_sleep() from
- * down_read()
- */
- might_sleep();
-#ifdef CONFIG_DEBUG_VM
- if (!user_mode(regs) &&
- !search_exception_tables(regs->UCreg_pc))
- goto no_context;
-#endif
- }
-
- fault = __do_pf(mm, addr, fsr, flags, tsk);
-
- /* If we need to retry but a fatal signal is pending, handle the
- * signal first. We do not need to release the mmap_lock because
- * it would already be released in __lock_page_or_retry in
- * mm/filemap.c. */
- if (fault_signal_pending(fault, regs))
- return 0;
-
- if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
- if (fault & VM_FAULT_MAJOR)
- tsk->maj_flt++;
- else
- tsk->min_flt++;
- if (fault & VM_FAULT_RETRY) {
- flags |= FAULT_FLAG_TRIED;
- goto retry;
- }
- }
-
- mmap_read_unlock(mm);
-
- /*
- * Handle the "normal" case first - VM_FAULT_MAJOR
- */
- if (likely(!(fault &
- (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
- return 0;
-
- /*
- * If we are in kernel mode at this point, we
- * have no context to handle this fault with.
- */
- if (!user_mode(regs))
- goto no_context;
-
- if (fault & VM_FAULT_OOM) {
- /*
- * We ran out of memory, call the OOM killer, and return to
- * userspace (which will retry the fault, or kill us if we
- * got oom-killed)
- */
- pagefault_out_of_memory();
- return 0;
- }
-
- if (fault & VM_FAULT_SIGBUS) {
- /*
- * We had some memory, but were unable to
- * successfully fix up this page fault.
- */
- sig = SIGBUS;
- code = BUS_ADRERR;
- } else {
- /*
- * Something tried to access memory that
- * isn't in our memory map..
- */
- sig = SIGSEGV;
- code = fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR;
- }
-
- __do_user_fault(addr, fsr, sig, code, regs);
- return 0;
-
-no_context:
- __do_kernel_fault(mm, addr, fsr, regs);
- return 0;
-}
-
-/*
- * First Level Translation Fault Handler
- *
- * We enter here because the first level page table doesn't contain
- * a valid entry for the address.
- *
- * If the address is in kernel space (>= TASK_SIZE), then we are
- * probably faulting in the vmalloc() area.
- *
- * If the init_task's first level page tables contains the relevant
- * entry, we copy the it to this task. If not, we send the process
- * a signal, fixup the exception, or oops the kernel.
- *
- * NOTE! We MUST NOT take any locks for this case. We may be in an
- * interrupt or a critical region, and should only copy the information
- * from the master page table, nothing more.
- */
-static int do_ifault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- unsigned int index;
- pgd_t *pgd, *pgd_k;
- pmd_t *pmd, *pmd_k;
-
- if (addr < TASK_SIZE)
- return do_pf(addr, fsr, regs);
-
- if (user_mode(regs))
- goto bad_area;
-
- index = pgd_index(addr);
-
- pgd = cpu_get_pgd() + index;
- pgd_k = init_mm.pgd + index;
-
- if (pgd_none(*pgd_k))
- goto bad_area;
-
- pmd_k = pmd_offset((pud_t *) pgd_k, addr);
- pmd = pmd_offset((pud_t *) pgd, addr);
-
- if (pmd_none(*pmd_k))
- goto bad_area;
-
- set_pmd(pmd, *pmd_k);
- flush_pmd_entry(pmd);
- return 0;
-
-bad_area:
- do_bad_area(addr, fsr, regs);
- return 0;
-}
-
-/*
- * This abort handler always returns "fault".
- */
-static int do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- return 1;
-}
-
-static int do_good(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- unsigned int res1, res2;
-
- printk("dabt exception but no error!\n");
-
- __asm__ __volatile__(
- "mff %0,f0\n"
- "mff %1,f1\n"
- : "=r"(res1), "=r"(res2)
- :
- : "memory");
-
- printk(KERN_EMERG "r0 :%08x r1 :%08x\n", res1, res2);
- panic("shut up\n");
- return 0;
-}
-
-static struct fsr_info {
- int (*fn) (unsigned long addr, unsigned int fsr, struct pt_regs *regs);
- int sig;
- int code;
- const char *name;
-} fsr_info[] = {
- /*
- * The following are the standard Unicore-I and UniCore-II aborts.
- */
- { do_good, SIGBUS, 0, "no error" },
- { do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
- { do_bad, SIGBUS, BUS_OBJERR, "external exception" },
- { do_bad, SIGBUS, 0, "burst operation" },
- { do_bad, SIGBUS, 0, "unknown 00100" },
- { do_ifault, SIGSEGV, SEGV_MAPERR, "2nd level pt non-exist"},
- { do_bad, SIGBUS, 0, "2nd lvl large pt non-exist" },
- { do_bad, SIGBUS, 0, "invalid pte" },
- { do_pf, SIGSEGV, SEGV_MAPERR, "page miss" },
- { do_bad, SIGBUS, 0, "middle page miss" },
- { do_bad, SIGBUS, 0, "large page miss" },
- { do_pf, SIGSEGV, SEGV_MAPERR, "super page (section) miss" },
- { do_bad, SIGBUS, 0, "unknown 01100" },
- { do_bad, SIGBUS, 0, "unknown 01101" },
- { do_bad, SIGBUS, 0, "unknown 01110" },
- { do_bad, SIGBUS, 0, "unknown 01111" },
- { do_bad, SIGBUS, 0, "addr: up 3G or IO" },
- { do_pf, SIGSEGV, SEGV_ACCERR, "read unreadable addr" },
- { do_pf, SIGSEGV, SEGV_ACCERR, "write unwriteable addr"},
- { do_pf, SIGSEGV, SEGV_ACCERR, "exec unexecutable addr"},
- { do_bad, SIGBUS, 0, "unknown 10100" },
- { do_bad, SIGBUS, 0, "unknown 10101" },
- { do_bad, SIGBUS, 0, "unknown 10110" },
- { do_bad, SIGBUS, 0, "unknown 10111" },
- { do_bad, SIGBUS, 0, "unknown 11000" },
- { do_bad, SIGBUS, 0, "unknown 11001" },
- { do_bad, SIGBUS, 0, "unknown 11010" },
- { do_bad, SIGBUS, 0, "unknown 11011" },
- { do_bad, SIGBUS, 0, "unknown 11100" },
- { do_bad, SIGBUS, 0, "unknown 11101" },
- { do_bad, SIGBUS, 0, "unknown 11110" },
- { do_bad, SIGBUS, 0, "unknown 11111" }
-};
-
-void __init hook_fault_code(int nr,
- int (*fn) (unsigned long, unsigned int, struct pt_regs *),
- int sig, int code, const char *name)
-{
- if (nr < 0 || nr >= ARRAY_SIZE(fsr_info))
- BUG();
-
- fsr_info[nr].fn = fn;
- fsr_info[nr].sig = sig;
- fsr_info[nr].code = code;
- fsr_info[nr].name = name;
-}
-
-/*
- * Dispatch a data abort to the relevant handler.
- */
-asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr,
- struct pt_regs *regs)
-{
- const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
-
- if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
- return;
-
- printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
- inf->name, fsr, addr);
-
- uc32_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
- fsr, 0);
-}
-
-asmlinkage void do_PrefetchAbort(unsigned long addr,
- unsigned int ifsr, struct pt_regs *regs)
-{
- const struct fsr_info *inf = fsr_info + fsr_fs(ifsr);
-
- if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
- return;
-
- printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
- inf->name, ifsr, addr);
-
- uc32_notify_die("", regs, inf->sig, inf->code, (void __user *)addr,
- ifsr, 0);
-}
diff --git a/arch/unicore32/mm/flush.c b/arch/unicore32/mm/flush.c
deleted file mode 100644
index 65954f8d89a2..000000000000
--- a/arch/unicore32/mm/flush.c
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/flush.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-void flush_cache_mm(struct mm_struct *mm)
-{
-}
-
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- if (vma->vm_flags & VM_EXEC)
- __flush_icache_all();
-}
-
-void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr,
- unsigned long pfn)
-{
-}
-
-static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
- unsigned long uaddr, void *kaddr, unsigned long len)
-{
- /* VIPT non-aliasing D-cache */
- if (vma->vm_flags & VM_EXEC) {
- unsigned long addr = (unsigned long)kaddr;
-
- __cpuc_coherent_kern_range(addr, addr + len);
- }
-}
-
-/*
- * Copy user data from/to a page which is mapped into a different
- * processes address space. Really, we want to allow our "user
- * space" model to handle this.
- *
- * Note that this code needs to run on the current CPU.
- */
-void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
- unsigned long uaddr, void *dst, const void *src,
- unsigned long len)
-{
- memcpy(dst, src, len);
- flush_ptrace_access(vma, page, uaddr, dst, len);
-}
-
-void __flush_dcache_page(struct address_space *mapping, struct page *page)
-{
- /*
- * Writeback any data associated with the kernel mapping of this
- * page. This ensures that data in the physical page is mutually
- * coherent with the kernels mapping.
- */
- __cpuc_flush_kern_dcache_area(page_address(page), PAGE_SIZE);
-}
-
-/*
- * Ensure cache coherency between kernel mapping and userspace mapping
- * of this page.
- */
-void flush_dcache_page(struct page *page)
-{
- struct address_space *mapping;
-
- /*
- * The zero page is never written to, so never has any dirty
- * cache lines, and therefore never needs to be flushed.
- */
- if (page == ZERO_PAGE(0))
- return;
-
- mapping = page_mapping_file(page);
-
- if (mapping && !mapping_mapped(mapping))
- clear_bit(PG_dcache_clean, &page->flags);
- else {
- __flush_dcache_page(mapping, page);
- if (mapping)
- __flush_icache_all();
- set_bit(PG_dcache_clean, &page->flags);
- }
-}
-EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c
deleted file mode 100644
index 52425d383cea..000000000000
--- a/arch/unicore32/mm/init.c
+++ /dev/null
@@ -1,261 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/init.c
- *
- * Copyright (C) 2010 GUAN Xue-tao
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/swap.h>
-#include <linux/init.h>
-#include <linux/memblock.h>
-#include <linux/mman.h>
-#include <linux/nodemask.h>
-#include <linux/initrd.h>
-#include <linux/highmem.h>
-#include <linux/gfp.h>
-#include <linux/sort.h>
-#include <linux/dma-mapping.h>
-#include <linux/export.h>
-
-#include <asm/sections.h>
-#include <asm/setup.h>
-#include <linux/sizes.h>
-#include <asm/tlb.h>
-#include <asm/memblock.h>
-#include <mach/map.h>
-
-#include "mm.h"
-
-/*
- * This keeps memory configuration data used by a couple memory
- * initialization functions, as well as show_mem() for the skipping
- * of holes in the memory map. It is populated by uc32_add_memory().
- */
-struct meminfo meminfo;
-
-static void __init find_limits(unsigned long *min, unsigned long *max_low,
- unsigned long *max_high)
-{
- struct meminfo *mi = &meminfo;
- int i;
-
- *min = -1UL;
- *max_low = *max_high = 0;
-
- for_each_bank(i, mi) {
- struct membank *bank = &mi->bank[i];
- unsigned long start, end;
-
- start = bank_pfn_start(bank);
- end = bank_pfn_end(bank);
-
- if (*min > start)
- *min = start;
- if (*max_high < end)
- *max_high = end;
- if (bank->highmem)
- continue;
- if (*max_low < end)
- *max_low = end;
- }
-}
-
-static void __init uc32_bootmem_free(unsigned long max_low)
-{
- unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
-
- max_zone_pfn[ZONE_DMA] = max_low;
- max_zone_pfn[ZONE_NORMAL] = max_low;
-
- /*
- * Adjust the sizes according to any special requirements for
- * this machine type.
- * This might lower ZONE_DMA limit.
- */
- arch_adjust_zones(max_zone_pfn);
-
- free_area_init(max_zone_pfn);
-}
-
-int pfn_valid(unsigned long pfn)
-{
- return memblock_is_memory(pfn << PAGE_SHIFT);
-}
-EXPORT_SYMBOL(pfn_valid);
-
-static void uc32_memory_present(void)
-{
-}
-
-static int __init meminfo_cmp(const void *_a, const void *_b)
-{
- const struct membank *a = _a, *b = _b;
- long cmp = bank_pfn_start(a) - bank_pfn_start(b);
- return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
-}
-
-void __init uc32_memblock_init(struct meminfo *mi)
-{
- int i;
-
- sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]),
- meminfo_cmp, NULL);
-
- for (i = 0; i < mi->nr_banks; i++)
- memblock_add(mi->bank[i].start, mi->bank[i].size);
-
- /* Register the kernel text, kernel data and initrd with memblock. */
- memblock_reserve(__pa(_text), _end - _text);
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (!phys_initrd_size) {
- phys_initrd_start = 0x01000000;
- phys_initrd_size = SZ_8M;
- }
-
- if (phys_initrd_size) {
- memblock_reserve(phys_initrd_start, phys_initrd_size);
-
- /* Now convert initrd to virtual addresses */
- initrd_start = __phys_to_virt(phys_initrd_start);
- initrd_end = initrd_start + phys_initrd_size;
- }
-#endif
-
- uc32_mm_memblock_reserve();
-
- memblock_allow_resize();
- memblock_dump_all();
-}
-
-void __init bootmem_init(void)
-{
- unsigned long min, max_low, max_high;
-
- max_low = max_high = 0;
-
- find_limits(&min, &max_low, &max_high);
-
- node_set_online(0);
-
- /*
- * Sparsemem tries to allocate bootmem in memory_present(),
- * so must be done after the fixed reservations
- */
- uc32_memory_present();
-
- /*
- * sparse_init() needs the bootmem allocator up and running.
- */
- sparse_init();
-
- /*
- * Now free the memory - free_area_init needs
- * the sparse mem_map arrays initialized by sparse_init()
- * for memmap_init_zone(), otherwise all PFNs are invalid.
- */
- uc32_bootmem_free(max_low);
-
- high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
-
- /*
- * This doesn't seem to be used by the Linux memory manager any
- * more, but is used by ll_rw_block. If we can get rid of it, we
- * also get rid of some of the stuff above as well.
- *
- * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
- * the system, not the maximum PFN.
- */
- max_low_pfn = max_low - PHYS_PFN_OFFSET;
- max_pfn = max_high - PHYS_PFN_OFFSET;
-}
-
-static inline void
-free_memmap(unsigned long start_pfn, unsigned long end_pfn)
-{
- struct page *start_pg, *end_pg;
- unsigned long pg, pgend;
-
- /*
- * Convert start_pfn/end_pfn to a struct page pointer.
- */
- start_pg = pfn_to_page(start_pfn - 1) + 1;
- end_pg = pfn_to_page(end_pfn);
-
- /*
- * Convert to physical addresses, and
- * round start upwards and end downwards.
- */
- pg = PAGE_ALIGN(__pa(start_pg));
- pgend = __pa(end_pg) & PAGE_MASK;
-
- /*
- * If there are free pages between these,
- * free the section of the memmap array.
- */
- if (pg < pgend)
- memblock_free(pg, pgend - pg);
-}
-
-/*
- * The mem_map array can get very big. Free the unused area of the memory map.
- */
-static void __init free_unused_memmap(struct meminfo *mi)
-{
- unsigned long bank_start, prev_bank_end = 0;
- unsigned int i;
-
- /*
- * This relies on each bank being in address order.
- * The banks are sorted previously in bootmem_init().
- */
- for_each_bank(i, mi) {
- struct membank *bank = &mi->bank[i];
-
- bank_start = bank_pfn_start(bank);
-
- /*
- * If we had a previous bank, and there is a space
- * between the current bank and the previous, free it.
- */
- if (prev_bank_end && prev_bank_end < bank_start)
- free_memmap(prev_bank_end, bank_start);
-
- /*
- * Align up here since the VM subsystem insists that the
- * memmap entries are valid from the bank end aligned to
- * MAX_ORDER_NR_PAGES.
- */
- prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
- }
-}
-
-/*
- * mem_init() marks the free areas in the mem_map and tells us how much
- * memory is free. This is done after various parts of the system have
- * claimed their memory after the kernel image.
- */
-void __init mem_init(void)
-{
- max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
-
- free_unused_memmap(&meminfo);
-
- /* this will put all unused low memory onto the freelists */
- memblock_free_all();
-
- mem_init_print_info(NULL);
-
- BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR);
- BUG_ON(TASK_SIZE > MODULES_VADDR);
-
- if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) {
- /*
- * On a machine this small we won't get
- * anywhere without overcommit, so turn
- * it on by default.
- */
- sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
- }
-}
diff --git a/arch/unicore32/mm/ioremap.c b/arch/unicore32/mm/ioremap.c
deleted file mode 100644
index 46a64bd6156a..000000000000
--- a/arch/unicore32/mm/ioremap.c
+++ /dev/null
@@ -1,242 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/ioremap.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * Re-map IO memory to kernel address space so that we can access it.
- *
- * This allows a driver to remap an arbitrary region of bus memory into
- * virtual space. One should *only* use readl, writel, memcpy_toio and
- * so on with such remapped areas.
- *
- * Because UniCore only has a 32-bit address space we can't address the
- * whole of the (physical) PCI space at once. PCI huge-mode addressing
- * allows us to circumvent this restriction by splitting PCI space into
- * two 2GB chunks and mapping only one at a time into processor memory.
- * We use MMU protection domains to trap any attempt to access the bank
- * that is not currently mapped. (This isn't fully implemented yet.)
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/io.h>
-
-#include <asm/cputype.h>
-#include <asm/cacheflush.h>
-#include <asm/mmu_context.h>
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <linux/sizes.h>
-
-#include <mach/map.h>
-#include "mm.h"
-
-/*
- * Used by ioremap() and iounmap() code to mark (super)section-mapped
- * I/O regions in vm_struct->flags field.
- */
-#define VM_UNICORE_SECTION_MAPPING 0x80000000
-
-int ioremap_page(unsigned long virt, unsigned long phys,
- const struct mem_type *mtype)
-{
- return ioremap_page_range(virt, virt + PAGE_SIZE, phys,
- __pgprot(mtype->prot_pte));
-}
-EXPORT_SYMBOL(ioremap_page);
-
-/*
- * Section support is unsafe on SMP - If you iounmap and ioremap a region,
- * the other CPUs will not see this change until their next context switch.
- * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs
- * which requires the new ioremap'd region to be referenced, the CPU will
- * reference the _old_ region.
- *
- * Note that get_vm_area_caller() allocates a guard 4K page, so we need to
- * mask the size back to 4MB aligned or we will overflow in the loop below.
- */
-static void unmap_area_sections(unsigned long virt, unsigned long size)
-{
- unsigned long addr = virt, end = virt + (size & ~(SZ_4M - 1));
- pgd_t *pgd;
-
- flush_cache_vunmap(addr, end);
- pgd = pgd_offset_k(addr);
- do {
- pmd_t pmd, *pmdp = pmd_offset((pud_t *)pgd, addr);
-
- pmd = *pmdp;
- if (!pmd_none(pmd)) {
- /*
- * Clear the PMD from the page table, and
- * increment the kvm sequence so others
- * notice this change.
- *
- * Note: this is still racy on SMP machines.
- */
- pmd_clear(pmdp);
-
- /*
- * Free the page table, if there was one.
- */
- if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
- pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
- }
-
- addr += PGDIR_SIZE;
- pgd++;
- } while (addr < end);
-
- flush_tlb_kernel_range(virt, end);
-}
-
-static int
-remap_area_sections(unsigned long virt, unsigned long pfn,
- size_t size, const struct mem_type *type)
-{
- unsigned long addr = virt, end = virt + size;
- pgd_t *pgd;
-
- /*
- * Remove and free any PTE-based mapping, and
- * sync the current kernel mapping.
- */
- unmap_area_sections(virt, size);
-
- pgd = pgd_offset_k(addr);
- do {
- pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
-
- set_pmd(pmd, __pmd(__pfn_to_phys(pfn) | type->prot_sect));
- pfn += SZ_4M >> PAGE_SHIFT;
- flush_pmd_entry(pmd);
-
- addr += PGDIR_SIZE;
- pgd++;
- } while (addr < end);
-
- return 0;
-}
-
-void __iomem *__uc32_ioremap_pfn_caller(unsigned long pfn,
- unsigned long offset, size_t size, unsigned int mtype, void *caller)
-{
- const struct mem_type *type;
- int err;
- unsigned long addr;
- struct vm_struct *area;
-
- /*
- * High mappings must be section aligned
- */
- if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SECTION_MASK))
- return NULL;
-
- /*
- * Don't allow RAM to be mapped
- */
- if (pfn_valid(pfn)) {
- WARN(1, "BUG: Your driver calls ioremap() on\n"
- "system memory. This leads to architecturally\n"
- "unpredictable behaviour, and ioremap() will fail in\n"
- "the next kernel release. Please fix your driver.\n");
- return NULL;
- }
-
- type = get_mem_type(mtype);
- if (!type)
- return NULL;
-
- /*
- * Page align the mapping size, taking account of any offset.
- */
- size = PAGE_ALIGN(offset + size);
-
- area = get_vm_area_caller(size, VM_IOREMAP, caller);
- if (!area)
- return NULL;
- addr = (unsigned long)area->addr;
-
- if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
- area->flags |= VM_UNICORE_SECTION_MAPPING;
- err = remap_area_sections(addr, pfn, size, type);
- } else
- err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn),
- __pgprot(type->prot_pte));
-
- if (err) {
- vunmap((void *)addr);
- return NULL;
- }
-
- flush_cache_vmap(addr, addr + size);
- return (void __iomem *) (offset + addr);
-}
-
-void __iomem *__uc32_ioremap_caller(unsigned long phys_addr, size_t size,
- unsigned int mtype, void *caller)
-{
- unsigned long last_addr;
- unsigned long offset = phys_addr & ~PAGE_MASK;
- unsigned long pfn = __phys_to_pfn(phys_addr);
-
- /*
- * Don't allow wraparound or zero size
- */
- last_addr = phys_addr + size - 1;
- if (!size || last_addr < phys_addr)
- return NULL;
-
- return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, caller);
-}
-
-/*
- * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
- *
- * NOTE! We need to allow non-page-aligned mappings too: we will obviously
- * have to convert them into an offset in a page-aligned mapping, but the
- * caller shouldn't need to know that small detail.
- */
-void __iomem *
-__uc32_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
- unsigned int mtype)
-{
- return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype,
- __builtin_return_address(0));
-}
-EXPORT_SYMBOL(__uc32_ioremap_pfn);
-
-void __iomem *
-__uc32_ioremap(unsigned long phys_addr, size_t size)
-{
- return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE,
- __builtin_return_address(0));
-}
-EXPORT_SYMBOL(__uc32_ioremap);
-
-void __uc32_iounmap(volatile void __iomem *io_addr)
-{
- void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
- struct vm_struct *vm;
-
- /*
- * If this is a section based mapping we need to handle it
- * specially as the VM subsystem does not know how to handle
- * such a beast. We need the lock here b/c we need to clear
- * all the mappings before the area can be reclaimed
- * by someone else.
- */
- vm = find_vm_area(addr);
- if (vm && (vm->flags & VM_IOREMAP) &&
- (vm->flags & VM_UNICORE_SECTION_MAPPING))
- unmap_area_sections((unsigned long)vm->addr, vm->size);
-
- vunmap(addr);
-}
-EXPORT_SYMBOL(__uc32_iounmap);
diff --git a/arch/unicore32/mm/mm.h b/arch/unicore32/mm/mm.h
deleted file mode 100644
index f157f5d249ab..000000000000
--- a/arch/unicore32/mm/mm.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/unicore32/mm/mm.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <asm/hwdef-copro.h>
-
-/* the upper-most page table pointer */
-extern pmd_t *top_pmd;
-extern int sysctl_overcommit_memory;
-
-#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
-
-struct mem_type {
- unsigned int prot_pte;
- unsigned int prot_l1;
- unsigned int prot_sect;
-};
-
-const struct mem_type *get_mem_type(unsigned int type);
-
-extern void __flush_dcache_page(struct address_space *, struct page *);
-extern void hook_fault_code(int nr, int (*fn)
- (unsigned long, unsigned int, struct pt_regs *),
- int sig, int code, const char *name);
-
-void __init bootmem_init(void);
-void uc32_mm_memblock_reserve(void);
diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c
deleted file mode 100644
index 183d5b056814..000000000000
--- a/arch/unicore32/mm/mmu.c
+++ /dev/null
@@ -1,513 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/mmu.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/mman.h>
-#include <linux/nodemask.h>
-#include <linux/memblock.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-
-#include <asm/cputype.h>
-#include <asm/sections.h>
-#include <asm/setup.h>
-#include <linux/sizes.h>
-#include <asm/tlb.h>
-#include <asm/memblock.h>
-
-#include <mach/map.h>
-
-#include "mm.h"
-
-/*
- * empty_zero_page is a special page that is used for
- * zero-initialized data and COW.
- */
-struct page *empty_zero_page;
-EXPORT_SYMBOL(empty_zero_page);
-
-/*
- * The pmd table for the upper-most set of pages.
- */
-pmd_t *top_pmd;
-
-pgprot_t pgprot_user;
-EXPORT_SYMBOL(pgprot_user);
-
-pgprot_t pgprot_kernel;
-EXPORT_SYMBOL(pgprot_kernel);
-
-static int __init noalign_setup(char *__unused)
-{
- cr_alignment &= ~CR_A;
- cr_no_alignment &= ~CR_A;
- set_cr(cr_alignment);
- return 1;
-}
-__setup("noalign", noalign_setup);
-
-void adjust_cr(unsigned long mask, unsigned long set)
-{
- unsigned long flags;
-
- mask &= ~CR_A;
-
- set &= mask;
-
- local_irq_save(flags);
-
- cr_no_alignment = (cr_no_alignment & ~mask) | set;
- cr_alignment = (cr_alignment & ~mask) | set;
-
- set_cr((get_cr() & ~mask) | set);
-
- local_irq_restore(flags);
-}
-
-struct map_desc {
- unsigned long virtual;
- unsigned long pfn;
- unsigned long length;
- unsigned int type;
-};
-
-#define PROT_PTE_DEVICE (PTE_PRESENT | PTE_YOUNG | \
- PTE_DIRTY | PTE_READ | PTE_WRITE)
-#define PROT_SECT_DEVICE (PMD_TYPE_SECT | PMD_PRESENT | \
- PMD_SECT_READ | PMD_SECT_WRITE)
-
-static struct mem_type mem_types[] = {
- [MT_DEVICE] = { /* Strongly ordered */
- .prot_pte = PROT_PTE_DEVICE,
- .prot_l1 = PMD_TYPE_TABLE | PMD_PRESENT,
- .prot_sect = PROT_SECT_DEVICE,
- },
- /*
- * MT_KUSER: pte for vecpage -- cacheable,
- * and sect for unigfx mmap -- noncacheable
- */
- [MT_KUSER] = {
- .prot_pte = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
- PTE_CACHEABLE | PTE_READ | PTE_EXEC,
- .prot_l1 = PMD_TYPE_TABLE | PMD_PRESENT,
- .prot_sect = PROT_SECT_DEVICE,
- },
- [MT_HIGH_VECTORS] = {
- .prot_pte = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
- PTE_CACHEABLE | PTE_READ | PTE_WRITE |
- PTE_EXEC,
- .prot_l1 = PMD_TYPE_TABLE | PMD_PRESENT,
- },
- [MT_MEMORY] = {
- .prot_pte = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
- PTE_WRITE | PTE_EXEC,
- .prot_l1 = PMD_TYPE_TABLE | PMD_PRESENT,
- .prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
- PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC,
- },
- [MT_ROM] = {
- .prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
- PMD_SECT_READ,
- },
-};
-
-const struct mem_type *get_mem_type(unsigned int type)
-{
- return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL;
-}
-EXPORT_SYMBOL(get_mem_type);
-
-/*
- * Adjust the PMD section entries according to the CPU in use.
- */
-static void __init build_mem_type_table(void)
-{
- pgprot_user = __pgprot(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE);
- pgprot_kernel = __pgprot(PTE_PRESENT | PTE_YOUNG |
- PTE_DIRTY | PTE_READ | PTE_WRITE |
- PTE_EXEC | PTE_CACHEABLE);
-}
-
-#define vectors_base() (vectors_high() ? 0xffff0000 : 0)
-
-static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
- unsigned long prot)
-{
- if (pmd_none(*pmd)) {
- size_t size = PTRS_PER_PTE * sizeof(pte_t);
- pte_t *pte = memblock_alloc(size, size);
-
- if (!pte)
- panic("%s: Failed to allocate %zu bytes align=%zx\n",
- __func__, size, size);
-
- __pmd_populate(pmd, __pa(pte) | prot);
- }
- BUG_ON(pmd_bad(*pmd));
- return pte_offset_kernel(pmd, addr);
-}
-
-static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
- unsigned long end, unsigned long pfn,
- const struct mem_type *type)
-{
- pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
- do {
- set_pte(pte, pfn_pte(pfn, __pgprot(type->prot_pte)));
- pfn++;
- } while (pte++, addr += PAGE_SIZE, addr != end);
-}
-
-static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
- unsigned long end, unsigned long phys,
- const struct mem_type *type)
-{
- pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
-
- /*
- * Try a section mapping - end, addr and phys must all be aligned
- * to a section boundary.
- */
- if (((addr | end | phys) & ~SECTION_MASK) == 0) {
- pmd_t *p = pmd;
-
- do {
- set_pmd(pmd, __pmd(phys | type->prot_sect));
- phys += SECTION_SIZE;
- } while (pmd++, addr += SECTION_SIZE, addr != end);
-
- flush_pmd_entry(p);
- } else {
- /*
- * No need to loop; pte's aren't interested in the
- * individual L1 entries.
- */
- alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
- }
-}
-
-/*
- * Create the page directory entries and any necessary
- * page tables for the mapping specified by `md'. We
- * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections.
- */
-static void __init create_mapping(struct map_desc *md)
-{
- unsigned long phys, addr, length, end;
- const struct mem_type *type;
- pgd_t *pgd;
-
- if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
- printk(KERN_WARNING "BUG: not creating mapping for "
- "0x%08llx at 0x%08lx in user region\n",
- __pfn_to_phys((u64)md->pfn), md->virtual);
- return;
- }
-
- if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
- md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
- printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
- "overlaps vmalloc space\n",
- __pfn_to_phys((u64)md->pfn), md->virtual);
- }
-
- type = &mem_types[md->type];
-
- addr = md->virtual & PAGE_MASK;
- phys = (unsigned long)__pfn_to_phys(md->pfn);
- length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
-
- if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
- printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
- "be mapped using pages, ignoring.\n",
- __pfn_to_phys(md->pfn), addr);
- return;
- }
-
- pgd = pgd_offset_k(addr);
- end = addr + length;
- do {
- unsigned long next = pgd_addr_end(addr, end);
-
- alloc_init_section(pgd, addr, next, phys, type);
-
- phys += next - addr;
- addr = next;
- } while (pgd++, addr != end);
-}
-
-static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
-
-/*
- * vmalloc=size forces the vmalloc area to be exactly 'size'
- * bytes. This can be used to increase (or decrease) the vmalloc
- * area - the default is 128m.
- */
-static int __init early_vmalloc(char *arg)
-{
- unsigned long vmalloc_reserve = memparse(arg, NULL);
-
- if (vmalloc_reserve < SZ_16M) {
- vmalloc_reserve = SZ_16M;
- printk(KERN_WARNING
- "vmalloc area too small, limiting to %luMB\n",
- vmalloc_reserve >> 20);
- }
-
- if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) {
- vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M);
- printk(KERN_WARNING
- "vmalloc area is too big, limiting to %luMB\n",
- vmalloc_reserve >> 20);
- }
-
- vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve);
- return 0;
-}
-early_param("vmalloc", early_vmalloc);
-
-static phys_addr_t lowmem_limit __initdata = SZ_1G;
-
-static void __init sanity_check_meminfo(void)
-{
- int i, j;
-
- lowmem_limit = __pa(vmalloc_min - 1) + 1;
- memblock_set_current_limit(lowmem_limit);
-
- for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
- struct membank *bank = &meminfo.bank[j];
- *bank = meminfo.bank[i];
- j++;
- }
- meminfo.nr_banks = j;
-}
-
-static inline void prepare_page_table(void)
-{
- unsigned long addr;
- phys_addr_t end;
-
- /*
- * Clear out all the mappings below the kernel image.
- */
- for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
- pmd_clear(pmd_off_k(addr));
-
- for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
- pmd_clear(pmd_off_k(addr));
-
- /*
- * Find the end of the first block of lowmem.
- */
- end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
- if (end >= lowmem_limit)
- end = lowmem_limit;
-
- /*
- * Clear out all the kernel space mappings, except for the first
- * memory bank, up to the end of the vmalloc region.
- */
- for (addr = __phys_to_virt(end);
- addr < VMALLOC_END; addr += PGDIR_SIZE)
- pmd_clear(pmd_off_k(addr));
-}
-
-/*
- * Reserve the special regions of memory
- */
-void __init uc32_mm_memblock_reserve(void)
-{
- /*
- * Reserve the page tables. These are already in use,
- * and can only be in node 0.
- */
- memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
-}
-
-/*
- * Set up device the mappings. Since we clear out the page tables for all
- * mappings above VMALLOC_END, we will remove any debug device mappings.
- * This means you have to be careful how you debug this function, or any
- * called function. This means you can't use any function or debugging
- * method which may touch any device, otherwise the kernel _will_ crash.
- */
-static void __init devicemaps_init(void)
-{
- struct map_desc map;
- unsigned long addr;
- void *vectors;
-
- /*
- * Allocate the vector page early.
- */
- vectors = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
- if (!vectors)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, PAGE_SIZE, PAGE_SIZE);
-
- for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
- pmd_clear(pmd_off_k(addr));
-
- /*
- * Create a mapping for the machine vectors at the high-vectors
- * location (0xffff0000). If we aren't using high-vectors, also
- * create a mapping at the low-vectors virtual address.
- */
- map.pfn = __phys_to_pfn(virt_to_phys(vectors));
- map.virtual = VECTORS_BASE;
- map.length = PAGE_SIZE;
- map.type = MT_HIGH_VECTORS;
- create_mapping(&map);
-
- /*
- * Create a mapping for the kuser page at the special
- * location (0xbfff0000) to the same vectors location.
- */
- map.pfn = __phys_to_pfn(virt_to_phys(vectors));
- map.virtual = KUSER_VECPAGE_BASE;
- map.length = PAGE_SIZE;
- map.type = MT_KUSER;
- create_mapping(&map);
-
- /*
- * Finally flush the caches and tlb to ensure that we're in a
- * consistent state wrt the writebuffer. This also ensures that
- * any write-allocated cache lines in the vector page are written
- * back. After this point, we can start to touch devices again.
- */
- local_flush_tlb_all();
- flush_cache_all();
-}
-
-static void __init map_lowmem(void)
-{
- struct memblock_region *reg;
-
- /* Map all the lowmem memory banks. */
- for_each_memblock(memory, reg) {
- phys_addr_t start = reg->base;
- phys_addr_t end = start + reg->size;
- struct map_desc map;
-
- if (end > lowmem_limit)
- end = lowmem_limit;
- if (start >= end)
- break;
-
- map.pfn = __phys_to_pfn(start);
- map.virtual = __phys_to_virt(start);
- map.length = end - start;
- map.type = MT_MEMORY;
-
- create_mapping(&map);
- }
-}
-
-/*
- * paging_init() sets up the page tables, initialises the zone memory
- * maps, and sets up the zero page, bad page and bad page tables.
- */
-void __init paging_init(void)
-{
- void *zero_page;
-
- build_mem_type_table();
- sanity_check_meminfo();
- prepare_page_table();
- map_lowmem();
- devicemaps_init();
-
- top_pmd = pmd_off_k(0xffff0000);
-
- /* allocate the zero page. */
- zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
- if (!zero_page)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, PAGE_SIZE, PAGE_SIZE);
-
- bootmem_init();
-
- empty_zero_page = virt_to_page(zero_page);
- __flush_dcache_page(NULL, empty_zero_page);
-}
-
-/*
- * In order to soft-boot, we need to insert a 1:1 mapping in place of
- * the user-mode pages. This will then ensure that we have predictable
- * results when turning the mmu off
- */
-void setup_mm_for_reboot(void)
-{
- unsigned long base_pmdval;
- pgd_t *pgd;
- int i;
-
- /*
- * We need to access to user-mode page tables here. For kernel threads
- * we don't have any user-mode mappings so we use the context that we
- * "borrowed".
- */
- pgd = current->active_mm->pgd;
-
- base_pmdval = PMD_SECT_WRITE | PMD_SECT_READ | PMD_TYPE_SECT;
-
- for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
- unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
- pmd_t *pmd;
-
- pmd = pmd_off(pgd, i << PGDIR_SHIFT);
- set_pmd(pmd, __pmd(pmdval));
- flush_pmd_entry(pmd);
- }
-
- local_flush_tlb_all();
-}
-
-/*
- * Take care of architecture specific things when placing a new PTE into
- * a page table, or changing an existing PTE. Basically, there are two
- * things that we need to take care of:
- *
- * 1. If PG_dcache_clean is not set for the page, we need to ensure
- * that any cache entries for the kernels virtual memory
- * range are written back to the page.
- * 2. If we have multiple shared mappings of the same space in
- * an object, we need to deal with the cache aliasing issues.
- *
- * Note that the pte lock will be held.
- */
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
- pte_t *ptep)
-{
- unsigned long pfn = pte_pfn(*ptep);
- struct address_space *mapping;
- struct page *page;
-
- if (!pfn_valid(pfn))
- return;
-
- /*
- * The zero page is never written to, so never has any dirty
- * cache lines, and therefore never needs to be flushed.
- */
- page = pfn_to_page(pfn);
- if (page == ZERO_PAGE(0))
- return;
-
- mapping = page_mapping_file(page);
- if (!test_and_set_bit(PG_dcache_clean, &page->flags))
- __flush_dcache_page(mapping, page);
- if (mapping)
- if (vma->vm_flags & VM_EXEC)
- __flush_icache_all();
-}
diff --git a/arch/unicore32/mm/pgd.c b/arch/unicore32/mm/pgd.c
deleted file mode 100644
index f01c73e04836..000000000000
--- a/arch/unicore32/mm/pgd.c
+++ /dev/null
@@ -1,102 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/pgd.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/mm.h>
-#include <linux/gfp.h>
-#include <linux/highmem.h>
-
-#include <asm/pgalloc.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-
-#include "mm.h"
-
-#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-
-/*
- * need to get a 4k page for level 1
- */
-pgd_t *get_pgd_slow(struct mm_struct *mm)
-{
- pgd_t *new_pgd, *init_pgd;
- pmd_t *new_pmd, *init_pmd;
- pte_t *new_pte, *init_pte;
-
- new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 0);
- if (!new_pgd)
- goto no_pgd;
-
- memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
-
- /*
- * Copy over the kernel and IO PGD entries
- */
- init_pgd = pgd_offset_k(0);
- memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
- (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
-
- clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
-
- if (!vectors_high()) {
- /*
- * On UniCore, first page must always be allocated since it
- * contains the machine vectors.
- */
- new_pmd = pmd_alloc(mm, (pud_t *)new_pgd, 0);
- if (!new_pmd)
- goto no_pmd;
-
- new_pte = pte_alloc_map(mm, new_pmd, 0);
- if (!new_pte)
- goto no_pte;
-
- init_pmd = pmd_offset((pud_t *)init_pgd, 0);
- init_pte = pte_offset_map(init_pmd, 0);
- set_pte(new_pte, *init_pte);
- pte_unmap(init_pte);
- pte_unmap(new_pte);
- }
-
- return new_pgd;
-
-no_pte:
- pmd_free(mm, new_pmd);
- mm_dec_nr_pmds(mm);
-no_pmd:
- free_pages((unsigned long)new_pgd, 0);
-no_pgd:
- return NULL;
-}
-
-void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
-{
- pmd_t *pmd;
- pgtable_t pte;
-
- if (!pgd)
- return;
-
- /* pgd is always present and good */
- pmd = pmd_off(pgd, 0);
- if (pmd_none(*pmd))
- goto free;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- goto free;
- }
-
- pte = pmd_pgtable(*pmd);
- pmd_clear(pmd);
- pte_free(mm, pte);
- mm_dec_nr_ptes(mm);
- pmd_free(mm, pmd);
- mm_dec_nr_pmds(mm);
-free:
- free_pages((unsigned long) pgd, 0);
-}
diff --git a/arch/unicore32/mm/proc-macros.S b/arch/unicore32/mm/proc-macros.S
deleted file mode 100644
index 3b0ae7d5bd80..000000000000
--- a/arch/unicore32/mm/proc-macros.S
+++ /dev/null
@@ -1,142 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/unicore32/mm/proc-macros.S
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * We need constants.h for:
- * VMA_VM_MM
- * VMA_VM_FLAGS
- * VM_EXEC
- */
-#include <generated/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/memory.h>
-
-/*
- * the cache line sizes of the I and D cache are the same
- */
-#define CACHE_LINESIZE 32
-
-/*
- * This is the maximum size of an area which will be invalidated
- * using the single invalidate entry instructions. Anything larger
- * than this, and we go for the whole cache.
- *
- * This value should be chosen such that we choose the cheapest
- * alternative.
- */
-#ifdef CONFIG_CPU_UCV2
-#define MAX_AREA_SIZE 0x800 /* 64 cache line */
-#endif
-
-/*
- * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
- */
- .macro vma_vm_mm, rd, rn
- ldw \rd, [\rn+], #VMA_VM_MM
- .endm
-
-/*
- * vma_vm_flags - get vma->vm_flags
- */
- .macro vma_vm_flags, rd, rn
- ldw \rd, [\rn+], #VMA_VM_FLAGS
- .endm
-
- .macro tsk_mm, rd, rn
- ldw \rd, [\rn+], #TI_TASK
- ldw \rd, [\rd+], #TSK_ACTIVE_MM
- .endm
-
-/*
- * act_mm - get current->active_mm
- */
- .macro act_mm, rd
- andn \rd, sp, #8128
- andn \rd, \rd, #63
- ldw \rd, [\rd+], #TI_TASK
- ldw \rd, [\rd+], #TSK_ACTIVE_MM
- .endm
-
-/*
- * mmid - get context id from mm pointer (mm->context.id)
- */
- .macro mmid, rd, rn
- ldw \rd, [\rn+], #MM_CONTEXT_ID
- .endm
-
-/*
- * mask_asid - mask the ASID from the context ID
- */
- .macro asid, rd, rn
- and \rd, \rn, #255
- .endm
-
- .macro crval, clear, mmuset, ucset
- .word \clear
- .word \mmuset
- .endm
-
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
-/*
- * va2pa va, pa, tbl, msk, off, err
- * This macro is used to translate virtual address to its physical address.
- *
- * va: virtual address
- * pa: physical address, result is stored in this register
- * tbl, msk, off: temp registers, will be destroyed
- * err: jump to error label if the physical address not exist
- * NOTE: all regs must be different
- */
- .macro va2pa, va, pa, tbl, msk, off, err=990f
- movc \pa, p0.c2, #0
- mov \off, \va >> #22 @ off <- index of 1st page table
- adr \tbl, 910f @ tbl <- table of 1st page table
-900: @ ---- handle 1, 2 page table
- add \pa, \pa, #PAGE_OFFSET @ pa <- virt addr of page table
- ldw \pa, [\pa+], \off << #2 @ pa <- the content of pt
- cand.a \pa, #4 @ test exist bit
- beq \err @ if not exist
- and \off, \pa, #3 @ off <- the last 2 bits
- add \tbl, \tbl, \off << #3 @ cmove table pointer
- ldw \msk, [\tbl+], #0 @ get the mask
- ldw pc, [\tbl+], #4
-930: @ ---- handle 2nd page table
- and \pa, \pa, \msk @ pa <- phys addr of 2nd pt
- mov \off, \va << #10
- cntlo \tbl, \msk @ use tbl as temp reg
- mov \off, \off >> \tbl
- mov \off, \off >> #2 @ off <- index of 2nd pt
- adr \tbl, 920f @ tbl <- table of 2nd pt
- b 900b
-910: @ 1st level page table
- .word 0xfffff000, 930b @ second level page table
- .word 0xfffffc00, 930b @ second level large page table
- .word 0x00000000, \err @ invalid
- .word 0xffc00000, 980f @ super page
-
-920: @ 2nd level page table
- .word 0xfffff000, 980f @ page
- .word 0xffffc000, 980f @ middle page
- .word 0xffff0000, 980f @ large page
- .word 0x00000000, \err @ invalid
-980:
- andn \tbl, \va, \msk
- and \pa, \pa, \msk
- or \pa, \pa, \tbl
-990:
- .endm
-#endif
-
- .macro dcacheline_flush, addr, t1, t2
- mov \t1, \addr << #20
- ldw \t2, =_stext @ _stext must ALIGN(4096)
- add \t2, \t2, \t1 >> #20
- ldw \t1, [\t2+], #0x0000
- ldw \t1, [\t2+], #0x1000
- ldw \t1, [\t2+], #0x2000
- ldw \t1, [\t2+], #0x3000
- .endm
diff --git a/arch/unicore32/mm/proc-syms.c b/arch/unicore32/mm/proc-syms.c
deleted file mode 100644
index 6c081616fc3c..000000000000
--- a/arch/unicore32/mm/proc-syms.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/arch/unicore32/mm/proc-syms.c
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/module.h>
-#include <linux/mm.h>
-
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <asm/page.h>
-
-EXPORT_SYMBOL(cpu_dcache_clean_area);
-EXPORT_SYMBOL(cpu_set_pte);
-
-EXPORT_SYMBOL(__cpuc_coherent_kern_range);
diff --git a/arch/unicore32/mm/proc-ucv2.S b/arch/unicore32/mm/proc-ucv2.S
deleted file mode 100644
index 18f8c4fb21a0..000000000000
--- a/arch/unicore32/mm/proc-ucv2.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/unicore32/mm/proc-ucv2.S
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/init.h>
-#include <linux/linkage.h>
-#include <linux/pgtable.h>
-#include <asm/assembler.h>
-#include <asm/hwcap.h>
-#include <asm/pgtable-hwdef.h>
-
-#include "proc-macros.S"
-
-ENTRY(cpu_proc_fin)
- stm.w (lr), [sp-]
- mov ip, #PSR_R_BIT | PSR_I_BIT | PRIV_MODE
- mov.a asr, ip
- b.l __cpuc_flush_kern_all
- ldm.w (pc), [sp]+
-
-/*
- * cpu_reset(loc)
- *
- * Perform a soft reset of the system. Put the CPU into the
- * same state as it would be if it had been reset, and branch
- * to what would be the reset vector.
- *
- * - loc - location to jump to for soft reset
- */
- .align 5
-ENTRY(cpu_reset)
- mov ip, #0
- movc p0.c5, ip, #28 @ Cache invalidate all
- nop8
-
- movc p0.c6, ip, #6 @ TLB invalidate all
- nop8
-
- movc ip, p0.c1, #0 @ ctrl register
- or ip, ip, #0x2000 @ vector base address
- andn ip, ip, #0x000f @ ............idam
- movc p0.c1, ip, #0 @ disable caches and mmu
- nop
- mov pc, r0 @ jump to loc
- nop8
-
-/*
- * cpu_do_idle()
- *
- * Idle the processor (eg, wait for interrupt).
- *
- * IRQs are already disabled.
- */
-ENTRY(cpu_do_idle)
- mov r0, #0 @ PCI address
- .rept 8
- ldw r1, [r0]
- .endr
- mov pc, lr
-
-ENTRY(cpu_dcache_clean_area)
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
- csub.a r1, #MAX_AREA_SIZE
- bsg 101f
- mov r9, #PAGE_SZ
- sub r9, r9, #1 @ PAGE_MASK
-1: va2pa r0, r10, r11, r12, r13 @ r10 is PA
- b 3f
-2: cand.a r0, r9
- beq 1b
-3: movc p0.c5, r10, #11 @ clean D entry
- nop8
- add r0, r0, #CACHE_LINESIZE
- add r10, r10, #CACHE_LINESIZE
- sub.a r1, r1, #CACHE_LINESIZE
- bua 2b
- mov pc, lr
-#endif
-101: mov ip, #0
- movc p0.c5, ip, #10 @ Dcache clean all
- nop8
-
- mov pc, lr
-
-/*
- * cpu_do_switch_mm(pgd_phys)
- *
- * Set the translation table base pointer to be pgd_phys
- *
- * - pgd_phys - physical address of new pgd
- *
- * It is assumed that:
- * - we are not using split page tables
- */
- .align 5
-ENTRY(cpu_do_switch_mm)
- movc p0.c2, r0, #0 @ update page table ptr
- nop8
-
- movc p0.c6, ip, #6 @ TLB invalidate all
- nop8
-
- mov pc, lr
-
-/*
- * cpu_set_pte(ptep, pte)
- *
- * Set a level 2 translation table entry.
- *
- * - ptep - pointer to level 2 translation table entry
- * - pte - PTE value to store
- */
- .align 5
-ENTRY(cpu_set_pte)
- stw r1, [r0]
-#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
- sub r2, r0, #PAGE_OFFSET
- movc p0.c5, r2, #11 @ Dcache clean line
- nop8
-#else
- mov ip, #0
- movc p0.c5, ip, #10 @ Dcache clean all
- nop8
- @dcacheline_flush r0, r2, ip
-#endif
- mov pc, lr
-
diff --git a/arch/unicore32/mm/tlb-ucv2.S b/arch/unicore32/mm/tlb-ucv2.S
deleted file mode 100644
index 0ce9c6b6f1db..000000000000
--- a/arch/unicore32/mm/tlb-ucv2.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/arch/unicore32/mm/tlb-ucv2.S
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- */
-#include <linux/init.h>
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-#include "proc-macros.S"
-
-/*
- * __cpu_flush_user_tlb_range(start, end, vma)
- *
- * Invalidate a range of TLB entries in the specified address space.
- *
- * - start - start address (may not be aligned)
- * - end - end address (exclusive, may not be aligned)
- * - vma - vma_struct describing address range
- */
-ENTRY(__cpu_flush_user_tlb_range)
-#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
- mov r0, r0 >> #PAGE_SHIFT @ align address
- mov r0, r0 << #PAGE_SHIFT
- vma_vm_flags r2, r2 @ get vma->vm_flags
-1:
- movc p0.c6, r0, #3
- nop8
-
- cand.a r2, #VM_EXEC @ Executable area ?
- beq 2f
-
- movc p0.c6, r0, #5
- nop8
-2:
- add r0, r0, #PAGE_SZ
- csub.a r0, r1
- beb 1b
-#else
- movc p0.c6, r0, #2
- nop8
-
- cand.a r2, #VM_EXEC @ Executable area ?
- beq 2f
-
- movc p0.c6, r0, #4
- nop8
-2:
-#endif
- mov pc, lr
-
-/*
- * __cpu_flush_kern_tlb_range(start,end)
- *
- * Invalidate a range of kernel TLB entries
- *
- * - start - start address (may not be aligned)
- * - end - end address (exclusive, may not be aligned)
- */
-ENTRY(__cpu_flush_kern_tlb_range)
-#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
- mov r0, r0 >> #PAGE_SHIFT @ align address
- mov r0, r0 << #PAGE_SHIFT
-1:
- movc p0.c6, r0, #3
- nop8
-
- movc p0.c6, r0, #5
- nop8
-
- add r0, r0, #PAGE_SZ
- csub.a r0, r1
- beb 1b
-#else
- movc p0.c6, r0, #2
- nop8
-
- movc p0.c6, r0, #4
- nop8
-#endif
- mov pc, lr
-