nds32: Cache and TLB routines

This patch contains cache and TLB maintenance functions.

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Greentime Hu
2017-10-24 15:40:25 +08:00
vanhempi 664eec400b
commit 7de9cf4740
12 muutettua tiedostoa jossa 1224 lisäystä ja 0 poistoa

Näytä tiedosto

@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __NDS32_CACHE_H__
#define __NDS32_CACHE_H__
#define L1_CACHE_BYTES 32
#define L1_CACHE_SHIFT 5
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
#endif /* __NDS32_CACHE_H__ */

Näytä tiedosto

@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
struct cache_info {
unsigned char ways;
unsigned char line_size;
unsigned short sets;
unsigned short size;
#if defined(CONFIG_CPU_CACHE_ALIASING)
unsigned short aliasing_num;
unsigned int aliasing_mask;
#endif
};

Näytä tiedosto

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __NDS32_CACHEFLUSH_H__
#define __NDS32_CACHEFLUSH_H__
#include <linux/mm.h>
#define PG_dcache_dirty PG_arch_1
#ifdef CONFIG_CPU_CACHE_ALIASING
void flush_cache_mm(struct mm_struct *mm);
void flush_cache_dup_mm(struct mm_struct *mm);
void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
void flush_cache_page(struct vm_area_struct *vma,
unsigned long addr, unsigned long pfn);
void flush_cache_kmaps(void);
void flush_cache_vmap(unsigned long start, unsigned long end);
void flush_cache_vunmap(unsigned long start, unsigned long end);
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
void flush_dcache_page(struct page *page);
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, void *src, int len);
void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, void *src, int len);
#define ARCH_HAS_FLUSH_ANON_PAGE
void flush_anon_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr);
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
void flush_kernel_dcache_page(struct page *page);
void flush_icache_range(unsigned long start, unsigned long end);
void flush_icache_page(struct vm_area_struct *vma, struct page *page);
#define flush_dcache_mmap_lock(mapping) spin_lock_irq(&(mapping)->tree_lock)
#define flush_dcache_mmap_unlock(mapping) spin_unlock_irq(&(mapping)->tree_lock)
#else
#include <asm-generic/cacheflush.h>
#endif
#endif /* __NDS32_CACHEFLUSH_H__ */

Näytä tiedosto

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __ASM_NDS32_MMU_CONTEXT_H
#define __ASM_NDS32_MMU_CONTEXT_H
#include <linux/spinlock.h>
#include <asm/tlbflush.h>
#include <asm/proc-fns.h>
#include <asm-generic/mm_hooks.h>
static inline int
init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
mm->context.id = 0;
return 0;
}
#define destroy_context(mm) do { } while(0)
#define CID_BITS 9
extern spinlock_t cid_lock;
extern unsigned int cpu_last_cid;
static inline void __new_context(struct mm_struct *mm)
{
unsigned int cid;
unsigned long flags;
spin_lock_irqsave(&cid_lock, flags);
cid = cpu_last_cid;
cpu_last_cid += 1 << TLB_MISC_offCID;
if (cpu_last_cid == 0)
cpu_last_cid = 1 << TLB_MISC_offCID << CID_BITS;
if ((cid & TLB_MISC_mskCID) == 0)
flush_tlb_all();
spin_unlock_irqrestore(&cid_lock, flags);
mm->context.id = cid;
}
static inline void check_context(struct mm_struct *mm)
{
if (unlikely
((mm->context.id ^ cpu_last_cid) >> TLB_MISC_offCID >> CID_BITS))
__new_context(mm);
}
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
unsigned int cpu = smp_processor_id();
if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
check_context(next);
cpu_switch_mm(next);
}
}
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) switch_mm(prev, next, NULL)
#endif

Näytä tiedosto

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __NDS32_PROCFNS_H__
#define __NDS32_PROCFNS_H__
#ifdef __KERNEL__
#include <asm/page.h>
struct mm_struct;
struct vm_area_struct;
extern void cpu_proc_init(void);
extern void cpu_proc_fin(void);
extern void cpu_do_idle(void);
extern void cpu_reset(unsigned long reset);
extern void cpu_switch_mm(struct mm_struct *mm);
extern void cpu_dcache_inval_all(void);
extern void cpu_dcache_wbinval_all(void);
extern void cpu_dcache_inval_page(unsigned long page);
extern void cpu_dcache_wb_page(unsigned long page);
extern void cpu_dcache_wbinval_page(unsigned long page);
extern void cpu_dcache_inval_range(unsigned long start, unsigned long end);
extern void cpu_dcache_wb_range(unsigned long start, unsigned long end);
extern void cpu_dcache_wbinval_range(unsigned long start, unsigned long end);
extern void cpu_icache_inval_all(void);
extern void cpu_icache_inval_page(unsigned long page);
extern void cpu_icache_inval_range(unsigned long start, unsigned long end);
extern void cpu_cache_wbinval_page(unsigned long page, int flushi);
extern void cpu_cache_wbinval_range(unsigned long start,
unsigned long end, int flushi);
extern void cpu_cache_wbinval_range_check(struct vm_area_struct *vma,
unsigned long start,
unsigned long end, bool flushi,
bool wbd);
extern void cpu_dma_wb_range(unsigned long start, unsigned long end);
extern void cpu_dma_inval_range(unsigned long start, unsigned long end);
extern void cpu_dma_wbinval_range(unsigned long start, unsigned long end);
#endif /* __KERNEL__ */
#endif /* __NDS32_PROCFNS_H__ */

Näytä tiedosto

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef __ASMNDS32_TLB_H
#define __ASMNDS32_TLB_H
#define tlb_start_vma(tlb,vma) \
do { \
if (!tlb->fullmm) \
flush_cache_range(vma, vma->vm_start, vma->vm_end); \
} while (0)
#define tlb_end_vma(tlb,vma) \
do { \
if(!tlb->fullmm) \
flush_tlb_range(vma, vma->vm_start, vma->vm_end); \
} while (0)
#define __tlb_remove_tlb_entry(tlb, pte, addr) do { } while (0)
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
#include <asm-generic/tlb.h>
#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tln)->mm, pmd)
#endif

Näytä tiedosto

@@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2017 Andes Technology Corporation
#ifndef _ASMNDS32_TLBFLUSH_H
#define _ASMNDS32_TLBFLUSH_H
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <nds32_intrinsic.h>
static inline void local_flush_tlb_all(void)
{
__nds32__tlbop_flua();
__nds32__isb();
}
static inline void local_flush_tlb_mm(struct mm_struct *mm)
{
__nds32__tlbop_flua();
__nds32__isb();
}
static inline void local_flush_tlb_kernel_range(unsigned long start,
unsigned long end)
{
while (start < end) {
__nds32__tlbop_inv(start);
__nds32__isb();
start += PAGE_SIZE;
}
}
void local_flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
#define flush_tlb_all local_flush_tlb_all
#define flush_tlb_mm local_flush_tlb_mm
#define flush_tlb_range local_flush_tlb_range
#define flush_tlb_page local_flush_tlb_page
#define flush_tlb_kernel_range local_flush_tlb_kernel_range
void update_mmu_cache(struct vm_area_struct *vma,
unsigned long address, pte_t * pte);
void tlb_migrate_finish(struct mm_struct *mm);
#endif