You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[XTENSA] Add support for cache-aliasing
Add support for processors that have cache-aliasing issues, such as the Stretch S5000 processor. Cache-aliasing means that the size of the cache (for one way) is larger than the page size, thus, a page can end up in several places in cache depending on the virtual to physical translation. The method used here is to map a user page temporarily through the auto-refill way 0 and of of the DTLB. We probably will want to revisit this issue and use a better approach with kmap/kunmap. Signed-off-by: Chris Zankel <chris@zankel.net>
This commit is contained in:
@@ -19,6 +19,15 @@
|
||||
|
||||
#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE/XCHAL_DCACHE_WAYS)
|
||||
#define ICACHE_WAY_SIZE (XCHAL_ICACHE_SIZE/XCHAL_ICACHE_WAYS)
|
||||
#define DCACHE_WAY_SHIFT (XCHAL_DCACHE_SETWIDTH + XCHAL_DCACHE_LINEWIDTH)
|
||||
#define ICACHE_WAY_SHIFT (XCHAL_ICACHE_SETWIDTH + XCHAL_ICACHE_LINEWIDTH)
|
||||
|
||||
/* Maximum cache size per way. */
|
||||
#if DCACHE_WAY_SIZE >= ICACHE_WAY_SIZE
|
||||
# define CACHE_WAY_SIZE DCACHE_WAY_SIZE
|
||||
#else
|
||||
# define CACHE_WAY_SIZE ICACHE_WAY_SIZE
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _XTENSA_CACHE_H */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* (C) 2001 - 2006 Tensilica Inc.
|
||||
* (C) 2001 - 2007 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_CACHEFLUSH_H
|
||||
@@ -18,10 +18,7 @@
|
||||
#include <asm/page.h>
|
||||
|
||||
/*
|
||||
* flush and invalidate data cache, invalidate instruction cache:
|
||||
*
|
||||
* __flush_invalidate_cache_all()
|
||||
* __flush_invalidate_cache_range(from,sze)
|
||||
* Lo-level routines for cache flushing.
|
||||
*
|
||||
* invalidate data or instruction cache:
|
||||
*
|
||||
@@ -40,26 +37,39 @@
|
||||
* __flush_invalidate_dcache_all()
|
||||
* __flush_invalidate_dcache_page(adr)
|
||||
* __flush_invalidate_dcache_range(from,size)
|
||||
*
|
||||
* specials for cache aliasing:
|
||||
*
|
||||
* __flush_invalidate_dcache_page_alias(vaddr,paddr)
|
||||
* __invalidate_icache_page_alias(vaddr,paddr)
|
||||
*/
|
||||
|
||||
extern void __flush_invalidate_cache_all(void);
|
||||
extern void __flush_invalidate_cache_range(unsigned long, unsigned long);
|
||||
extern void __flush_invalidate_dcache_all(void);
|
||||
extern void __invalidate_dcache_all(void);
|
||||
extern void __invalidate_icache_all(void);
|
||||
|
||||
extern void __invalidate_dcache_page(unsigned long);
|
||||
extern void __invalidate_icache_page(unsigned long);
|
||||
extern void __invalidate_icache_range(unsigned long, unsigned long);
|
||||
extern void __invalidate_dcache_range(unsigned long, unsigned long);
|
||||
|
||||
|
||||
#if XCHAL_DCACHE_IS_WRITEBACK
|
||||
extern void __flush_invalidate_dcache_all(void);
|
||||
extern void __flush_dcache_page(unsigned long);
|
||||
extern void __flush_dcache_range(unsigned long, unsigned long);
|
||||
extern void __flush_invalidate_dcache_page(unsigned long);
|
||||
extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
|
||||
#else
|
||||
# define __flush_dcache_page(p) do { } while(0)
|
||||
# define __flush_invalidate_dcache_page(p) do { } while(0)
|
||||
# define __flush_invalidate_dcache_range(p,s) do { } while(0)
|
||||
# define __flush_dcache_range(p,s) do { } while(0)
|
||||
# define __flush_dcache_page(p) do { } while(0)
|
||||
# define __flush_invalidate_dcache_page(p) __invalidate_dcache_page(p)
|
||||
# define __flush_invalidate_dcache_range(p,s) __invalidate_dcache_range(p,s)
|
||||
#endif
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long);
|
||||
#endif
|
||||
#if (ICACHE_WAY_SIZE > PAGE_SIZE)
|
||||
extern void __invalidate_icache_page_alias(unsigned long, unsigned long);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -71,17 +81,21 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
|
||||
* (see also Documentation/cachetlb.txt)
|
||||
*/
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
|
||||
#define flush_cache_all() __flush_invalidate_cache_all();
|
||||
#define flush_cache_mm(mm) __flush_invalidate_cache_all();
|
||||
#define flush_cache_dup_mm(mm) __flush_invalidate_cache_all();
|
||||
#define flush_cache_all() \
|
||||
do { \
|
||||
__flush_invalidate_dcache_all(); \
|
||||
__invalidate_icache_all(); \
|
||||
} while (0)
|
||||
|
||||
#define flush_cache_vmap(start,end) __flush_invalidate_cache_all();
|
||||
#define flush_cache_vunmap(start,end) __flush_invalidate_cache_all();
|
||||
#define flush_cache_mm(mm) flush_cache_all()
|
||||
#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
|
||||
|
||||
#define flush_cache_vmap(start,end) flush_cache_all()
|
||||
#define flush_cache_vunmap(start,end) flush_cache_all()
|
||||
|
||||
extern void flush_dcache_page(struct page*);
|
||||
|
||||
extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
|
||||
extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long);
|
||||
|
||||
@@ -101,24 +115,39 @@ extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned lon
|
||||
|
||||
#endif
|
||||
|
||||
/* Ensure consistency between data and instruction cache. */
|
||||
#define flush_icache_range(start,end) \
|
||||
__invalidate_icache_range(start,(end)-(start))
|
||||
do { \
|
||||
__flush_dcache_range(start, (end) - (start)); \
|
||||
__invalidate_icache_range(start,(end) - (start)); \
|
||||
} while (0)
|
||||
|
||||
/* This is not required, see Documentation/cachetlb.txt */
|
||||
|
||||
#define flush_icache_page(vma,page) do { } while(0)
|
||||
#define flush_icache_page(vma,page) do { } while (0)
|
||||
|
||||
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
|
||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||
memcpy(dst, src, len)
|
||||
extern void copy_to_user_page(struct vm_area_struct*, struct page*,
|
||||
unsigned long, void*, const void*, unsigned long);
|
||||
extern void copy_from_user_page(struct vm_area_struct*, struct page*,
|
||||
unsigned long, void*, const void*, unsigned long);
|
||||
|
||||
#else
|
||||
|
||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||
do { \
|
||||
memcpy(dst, src, len); \
|
||||
__flush_dcache_range((unsigned long) dst, len); \
|
||||
__invalidate_icache_range((unsigned long) dst, len); \
|
||||
} while (0)
|
||||
|
||||
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
||||
memcpy(dst, src, len)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _XTENSA_CACHEFLUSH_H */
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#ifdef __KERNEL__
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/page.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
/*
|
||||
* Fixed TLB translations in the processor.
|
||||
@@ -39,6 +40,53 @@
|
||||
#define MAX_MEM_PFN XCHAL_KSEG_SIZE
|
||||
#define PGTABLE_START 0x80000000
|
||||
|
||||
/*
|
||||
* Cache aliasing:
|
||||
*
|
||||
* If the cache size for one way is greater than the page size, we have to
|
||||
* deal with cache aliasing. The cache index is wider than the page size:
|
||||
*
|
||||
* | |cache| cache index
|
||||
* | pfn |off| virtual address
|
||||
* |xxxx:X|zzz|
|
||||
* | : | |
|
||||
* | \ / | |
|
||||
* |trans.| |
|
||||
* | / \ | |
|
||||
* |yyyy:Y|zzz| physical address
|
||||
*
|
||||
* When the page number is translated to the physical page address, the lowest
|
||||
* bit(s) (X) that are part of the cache index are also translated (Y).
|
||||
* If this translation changes bit(s) (X), the cache index is also afected,
|
||||
* thus resulting in a different cache line than before.
|
||||
* The kernel does not provide a mechanism to ensure that the page color
|
||||
* (represented by this bit) remains the same when allocated or when pages
|
||||
* are remapped. When user pages are mapped into kernel space, the color of
|
||||
* the page might also change.
|
||||
*
|
||||
* We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
|
||||
* to temporarily map a patch so we can match the color.
|
||||
*/
|
||||
|
||||
#if DCACHE_WAY_SIZE > PAGE_SIZE
|
||||
# define DCACHE_ALIAS_ORDER (DCACHE_WAY_SHIFT - PAGE_SHIFT)
|
||||
# define DCACHE_ALIAS_MASK (PAGE_MASK & (DCACHE_WAY_SIZE - 1))
|
||||
# define DCACHE_ALIAS(a) (((a) & DCACHE_ALIAS_MASK) >> PAGE_SHIFT)
|
||||
# define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0)
|
||||
#else
|
||||
# define DCACHE_ALIAS_ORDER 0
|
||||
#endif
|
||||
|
||||
#if ICACHE_WAY_SIZE > PAGE_SIZE
|
||||
# define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT)
|
||||
# define ICACHE_ALIAS_MASK (PAGE_MASK & (ICACHE_WAY_SIZE - 1))
|
||||
# define ICACHE_ALIAS(a) (((a) & ICACHE_ALIAS_MASK) >> PAGE_SHIFT)
|
||||
# define ICACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & ICACHE_ALIAS_MASK) == 0)
|
||||
#else
|
||||
# define ICACHE_ALIAS_ORDER 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#define __pgprot(x) (x)
|
||||
@@ -90,11 +138,11 @@ extern void copy_page(void *to, void *from);
|
||||
* some extra work
|
||||
*/
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
|
||||
void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
|
||||
#if DCACHE_WAY_SIZE > PAGE_SIZE
|
||||
extern void clear_user_page(void*, unsigned long, struct page*);
|
||||
extern void copy_user_page(void*, void*, unsigned long, struct page*);
|
||||
#else
|
||||
# define clear_user_page(page,vaddr,pg) clear_page(page)
|
||||
# define clear_user_page(page, vaddr, pg) clear_page(page)
|
||||
# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* linux/include/asm-xtensa/pgalloc.h
|
||||
* include/asm-xtensa/pgalloc.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Copyright (C) 2001-2005 Tensilica Inc.
|
||||
* Copyright (C) 2001-2007 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_PGALLOC_H
|
||||
@@ -13,103 +13,54 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/threads.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
|
||||
/* Cache aliasing:
|
||||
*
|
||||
* If the cache size for one way is greater than the page size, we have to
|
||||
* deal with cache aliasing. The cache index is wider than the page size:
|
||||
*
|
||||
* |cache |
|
||||
* |pgnum |page| virtual address
|
||||
* |xxxxxX|zzzz|
|
||||
* | | |
|
||||
* \ / | |
|
||||
* trans.| |
|
||||
* / \ | |
|
||||
* |yyyyyY|zzzz| physical address
|
||||
*
|
||||
* When the page number is translated to the physical page address, the lowest
|
||||
* bit(s) (X) that are also part of the cache index are also translated (Y).
|
||||
* If this translation changes this bit (X), the cache index is also afected,
|
||||
* thus resulting in a different cache line than before.
|
||||
* The kernel does not provide a mechanism to ensure that the page color
|
||||
* (represented by this bit) remains the same when allocated or when pages
|
||||
* are remapped. When user pages are mapped into kernel space, the color of
|
||||
* the page might also change.
|
||||
*
|
||||
* We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
|
||||
* to temporarily map a patch so we can match the color.
|
||||
*/
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
# define PAGE_COLOR_MASK (PAGE_MASK & (DCACHE_WAY_SIZE-1))
|
||||
# define PAGE_COLOR(a) \
|
||||
(((unsigned long)(a)&PAGE_COLOR_MASK) >> PAGE_SHIFT)
|
||||
# define PAGE_COLOR_EQ(a,b) \
|
||||
((((unsigned long)(a) ^ (unsigned long)(b)) & PAGE_COLOR_MASK) == 0)
|
||||
# define PAGE_COLOR_MAP0(v) \
|
||||
(VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK))
|
||||
# define PAGE_COLOR_MAP1(v) \
|
||||
(VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK) + DCACHE_WAY_SIZE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocating and freeing a pmd is trivial: the 1-entry pmd is
|
||||
* inside the pgd, so has no extra memory associated with it.
|
||||
*/
|
||||
|
||||
#define pgd_free(pgd) free_page((unsigned long)(pgd))
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
|
||||
|
||||
static inline void
|
||||
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *pte)
|
||||
{
|
||||
pmd_val(*(pmdp)) = (unsigned long)(pte);
|
||||
__asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *page)
|
||||
{
|
||||
pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page);
|
||||
__asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
# define pmd_populate_kernel(mm, pmdp, pte) \
|
||||
(pmd_val(*(pmdp)) = (unsigned long)(pte))
|
||||
# define pmd_populate(mm, pmdp, page) \
|
||||
(pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page))
|
||||
|
||||
#endif
|
||||
#define pmd_populate_kernel(mm, pmdp, ptep) \
|
||||
(pmd_val(*(pmdp)) = ((unsigned long)ptep))
|
||||
#define pmd_populate(mm, pmdp, page) \
|
||||
(pmd_val(*(pmdp)) = ((unsigned long)page_to_virt(page)))
|
||||
|
||||
static inline pgd_t*
|
||||
pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
pgd_t *pgd;
|
||||
|
||||
pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGD_ORDER);
|
||||
|
||||
if (likely(pgd != NULL))
|
||||
__flush_dcache_page((unsigned long)pgd);
|
||||
|
||||
return pgd;
|
||||
return (pgd_t*) __get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
|
||||
}
|
||||
|
||||
extern pte_t* pte_alloc_one_kernel(struct mm_struct* mm, unsigned long addr);
|
||||
extern struct page* pte_alloc_one(struct mm_struct* mm, unsigned long addr);
|
||||
static inline void pgd_free(pgd_t *pgd)
|
||||
{
|
||||
free_page((unsigned long)pgd);
|
||||
}
|
||||
|
||||
#define pte_free_kernel(pte) free_page((unsigned long)pte)
|
||||
#define pte_free(pte) __free_page(pte)
|
||||
/* Use a slab cache for the pte pages (see also sparc64 implementation) */
|
||||
|
||||
extern struct kmem_cache *pgtable_cache;
|
||||
|
||||
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
||||
unsigned long address)
|
||||
{
|
||||
return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT);
|
||||
}
|
||||
|
||||
static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
||||
unsigned long addr)
|
||||
{
|
||||
return virt_to_page(pte_alloc_one_kernel(mm, addr));
|
||||
}
|
||||
|
||||
static inline void pte_free_kernel(pte_t *pte)
|
||||
{
|
||||
kmem_cache_free(pgtable_cache, pte);
|
||||
}
|
||||
|
||||
static inline void pte_free(struct page *page)
|
||||
{
|
||||
kmem_cache_free(pgtable_cache, page_address(page));
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _XTENSA_PGALLOC_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* linux/include/asm-xtensa/pgtable.h
|
||||
* include/asm-xtensa/pgtable.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -60,16 +60,20 @@
|
||||
#define FIRST_USER_ADDRESS 0
|
||||
#define FIRST_USER_PGD_NR (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
|
||||
|
||||
/* virtual memory area. We keep a distance to other memory regions to be
|
||||
/*
|
||||
* Virtual memory area. We keep a distance to other memory regions to be
|
||||
* on the safe side. We also use this area for cache aliasing.
|
||||
*/
|
||||
|
||||
// FIXME: virtual memory area must be configuration-dependent
|
||||
|
||||
#define VMALLOC_START 0xC0000000
|
||||
#define VMALLOC_END 0xC7FF0000
|
||||
#define VMALLOC_END 0xC6FEFFFF
|
||||
#define TLBTEMP_BASE_1 0xC6FF0000
|
||||
#define TLBTEMP_BASE_2 0xC6FF8000
|
||||
#define MODULE_START 0xC7000000
|
||||
#define MODULE_END 0xC7FFFFFF
|
||||
|
||||
/* Xtensa Linux config PTE layout (when present):
|
||||
/*
|
||||
* Xtensa Linux config PTE layout (when present):
|
||||
* 31-12: PPN
|
||||
* 11-6: Software
|
||||
* 5-4: RING
|
||||
@@ -126,12 +130,13 @@
|
||||
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_WRITABLE)
|
||||
#define PAGE_SHARED_EXEC \
|
||||
__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_WRITABLE | _PAGE_HW_EXEC)
|
||||
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT)
|
||||
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_HW_WRITE)
|
||||
#define PAGE_KERNEL_EXEC __pgprot(_PAGE_PRESENT|_PAGE_HW_WRITE|_PAGE_HW_EXEC)
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED | _PAGE_HW_WRITE)
|
||||
# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED)
|
||||
#else
|
||||
# define _PAGE_DIRECTORY (_PAGE_VALID|_PAGE_ACCESSED|_PAGE_HW_WRITE|_PAGE_CA_WB)
|
||||
# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED | _PAGE_CA_WB)
|
||||
#endif
|
||||
|
||||
#else /* no mmu */
|
||||
@@ -244,6 +249,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
static inline void update_pte(pte_t *ptep, pte_t pteval)
|
||||
{
|
||||
*ptep = pteval;
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
|
||||
__asm__ __volatile__ ("dhwb %0, 0" :: "a" (ptep));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
struct mm_struct;
|
||||
@@ -383,13 +392,12 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
|
||||
* remap a physical page `pfn' of size `size' with page protection `prot'
|
||||
* into virtual address `from'
|
||||
*/
|
||||
|
||||
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
|
||||
remap_pfn_range(vma, from, pfn, size, prot)
|
||||
|
||||
|
||||
/* No page table caches to init */
|
||||
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
extern void pgtable_cache_init(void);
|
||||
|
||||
typedef pte_t *pte_addr_t;
|
||||
|
||||
|
||||
@@ -11,14 +11,36 @@
|
||||
#ifndef _XTENSA_TLB_H
|
||||
#define _XTENSA_TLB_H
|
||||
|
||||
#define tlb_start_vma(tlb,vma) do { } while (0)
|
||||
#define tlb_end_vma(tlb,vma) do { } while (0)
|
||||
#define __tlb_remove_tlb_entry(tlb,pte,addr) do { } while (0)
|
||||
#include <asm/cache.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#if (DCACHE_WAY_SIZE <= PAGE_SIZE)
|
||||
|
||||
/* Note, read http://lkml.org/lkml/2004/1/15/6 */
|
||||
|
||||
# define tlb_start_vma(tlb,vma) do { } while (0)
|
||||
# define tlb_end_vma(tlb,vma) do { } while (0)
|
||||
|
||||
#else
|
||||
|
||||
# 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)
|
||||
|
||||
#endif
|
||||
|
||||
#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>
|
||||
#include <asm/page.h>
|
||||
|
||||
#define __pte_free_tlb(tlb,pte) pte_free(pte)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user