Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 013de2d6 authored by Guo Ren's avatar Guo Ren
Browse files

csky: MMU and page table management

This patch adds files related to memory management and here is our
memory-layout:

   Fixmap       : 0xffc02000 – 0xfffff000       (4 MB - 12KB)
   Pkmap        : 0xff800000 – 0xffc00000       (4 MB)
   Vmalloc      : 0xf0200000 – 0xff000000       (238 MB)
   Lowmem       : 0x80000000 – 0xc0000000       (1GB)

abiv1 CPU (CK610) is VIPT cache and it doesn't support highmem.
abiv2 CPUs are all PIPT cache and they could support highmem.

Lowmem is directly mapped by msa0 & msa1 reg, and we needn't setup
memory page table for it.

Link:https://lore.kernel.org/lkml/20180518215548.GH17671@n2100.armlinux.org.uk/


Signed-off-by: default avatarGuo Ren <ren_guo@c-sky.com>
Cc: Christoph Hellwig <hch@infradead.org>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 00a9730e
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#ifndef __ASM_CSKY_CKMMUV1_H
#define __ASM_CSKY_CKMMUV1_H
#include <abi/reg_ops.h>

static inline int read_mmu_index(void)
{
	return cprcr("cpcr0");
}

static inline void write_mmu_index(int value)
{
	cpwcr("cpcr0", value);
}

static inline int read_mmu_entrylo0(void)
{
	return cprcr("cpcr2") << 6;
}

static inline int read_mmu_entrylo1(void)
{
	return cprcr("cpcr3") << 6;
}

static inline void write_mmu_pagemask(int value)
{
	cpwcr("cpcr6", value);
}

static inline int read_mmu_entryhi(void)
{
	return cprcr("cpcr4");
}

static inline void write_mmu_entryhi(int value)
{
	cpwcr("cpcr4", value);
}

/*
 * TLB operations.
 */
static inline void tlb_probe(void)
{
	cpwcr("cpcr8", 0x80000000);
}

static inline void tlb_read(void)
{
	cpwcr("cpcr8", 0x40000000);
}

static inline void tlb_invalid_all(void)
{
	cpwcr("cpcr8", 0x04000000);
}

static inline void tlb_invalid_indexed(void)
{
	cpwcr("cpcr8", 0x02000000);
}

static inline void setup_pgd(unsigned long pgd, bool kernel)
{
	cpwcr("cpcr29", pgd);
}

static inline unsigned long get_pgd(void)
{
	return cprcr("cpcr29");
}
#endif /* __ASM_CSKY_CKMMUV1_H */
+27 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

extern unsigned long shm_align_mask;
extern void flush_dcache_page(struct page *page);

static inline unsigned long pages_do_alias(unsigned long addr1,
					   unsigned long addr2)
{
	return (addr1 ^ addr2) & shm_align_mask;
}

static inline void clear_user_page(void *addr, unsigned long vaddr,
				   struct page *page)
{
	clear_page(addr);
	if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
		flush_dcache_page(page);
}

static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
				  struct page *page)
{
	copy_page(to, from);
	if (pages_do_alias((unsigned long) to, vaddr & PAGE_MASK))
		flush_dcache_page(page);
}
+37 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#ifndef __ASM_CSKY_PGTABLE_BITS_H
#define __ASM_CSKY_PGTABLE_BITS_H

/* implemented in software */
#define _PAGE_ACCESSED		(1<<3)
#define PAGE_ACCESSED_BIT	(3)

#define _PAGE_READ		(1<<1)
#define _PAGE_WRITE		(1<<2)
#define _PAGE_PRESENT		(1<<0)

#define _PAGE_MODIFIED		(1<<4)
#define PAGE_MODIFIED_BIT	(4)

/* implemented in hardware */
#define _PAGE_GLOBAL		(1<<6)

#define _PAGE_VALID		(1<<7)
#define PAGE_VALID_BIT		(7)

#define _PAGE_DIRTY		(1<<8)
#define PAGE_DIRTY_BIT		(8)

#define _PAGE_CACHE		(3<<9)
#define _PAGE_UNCACHE		(2<<9)

#define _CACHE_MASK		(7<<9)

#define _CACHE_CACHED		(_PAGE_VALID | _PAGE_CACHE)
#define _CACHE_UNCACHED		(_PAGE_VALID | _PAGE_UNCACHE)

#define HAVE_ARCH_UNMAPPED_AREA

#endif /* __ASM_CSKY_PGTABLE_BITS_H */

arch/csky/abiv1/mmap.c

0 → 100644
+66 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/shm.h>
#include <linux/sched.h>
#include <linux/random.h>
#include <linux/io.h>

unsigned long shm_align_mask = (0x4000 >> 1) - 1;   /* Sane caches */

#define COLOUR_ALIGN(addr, pgoff) \
	((((addr) + shm_align_mask) & ~shm_align_mask) + \
	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))

unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
		unsigned long len, unsigned long pgoff, unsigned long flags)
{
	struct vm_area_struct *vmm;
	int do_color_align;

	if (flags & MAP_FIXED) {
		/*
		 * We do not accept a shared mapping if it would violate
		 * cache aliasing constraints.
		 */
		if ((flags & MAP_SHARED) &&
			((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
			return -EINVAL;
		return addr;
	}

	if (len > TASK_SIZE)
		return -ENOMEM;
	do_color_align = 0;
	if (filp || (flags & MAP_SHARED))
		do_color_align = 1;
	if (addr) {
		if (do_color_align)
			addr = COLOUR_ALIGN(addr, pgoff);
		else
			addr = PAGE_ALIGN(addr);
		vmm = find_vma(current->mm, addr);
		if (TASK_SIZE - len >= addr &&
				(!vmm || addr + len <= vmm->vm_start))
			return addr;
	}
	addr = TASK_UNMAPPED_BASE;
	if (do_color_align)
		addr = COLOUR_ALIGN(addr, pgoff);
	else
		addr = PAGE_ALIGN(addr);

	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
		/* At this point: (!vmm || addr < vmm->vm_end). */
		if (TASK_SIZE - len < addr)
			return -ENOMEM;
		if (!vmm || addr + len <= vmm->vm_start)
			return addr;
		addr = vmm->vm_end;
		if (do_color_align)
			addr = COLOUR_ALIGN(addr, pgoff);
	}
}
+87 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#ifndef __ASM_CSKY_CKMMUV2_H
#define __ASM_CSKY_CKMMUV2_H

#include <abi/reg_ops.h>
#include <asm/barrier.h>

static inline int read_mmu_index(void)
{
	return mfcr("cr<0, 15>");
}

static inline void write_mmu_index(int value)
{
	mtcr("cr<0, 15>", value);
}

static inline int read_mmu_entrylo0(void)
{
	return mfcr("cr<2, 15>");
}

static inline int read_mmu_entrylo1(void)
{
	return mfcr("cr<3, 15>");
}

static inline void write_mmu_pagemask(int value)
{
	mtcr("cr<6, 15>", value);
}

static inline int read_mmu_entryhi(void)
{
	return mfcr("cr<4, 15>");
}

static inline void write_mmu_entryhi(int value)
{
	mtcr("cr<4, 15>", value);
}

/*
 * TLB operations.
 */
static inline void tlb_probe(void)
{
	mtcr("cr<8, 15>", 0x80000000);
}

static inline void tlb_read(void)
{
	mtcr("cr<8, 15>", 0x40000000);
}

static inline void tlb_invalid_all(void)
{
#ifdef CONFIG_CPU_HAS_TLBI
	asm volatile("tlbi.alls\n":::"memory");
	sync_is();
#else
	mtcr("cr<8, 15>", 0x04000000);
#endif
}

static inline void tlb_invalid_indexed(void)
{
	mtcr("cr<8, 15>", 0x02000000);
}

/* setup hardrefil pgd */
static inline unsigned long get_pgd(void)
{
	return mfcr("cr<29, 15>");
}

static inline void setup_pgd(unsigned long pgd, bool kernel)
{
	if (kernel)
		mtcr("cr<28, 15>", pgd);
	else
		mtcr("cr<29, 15>", pgd);
}

#endif /* __ASM_CSKY_CKMMUV2_H */
Loading