csky-for-linus-5.4-rc1: arch/csky patches for 5.4-rc1
This round of csky subsystem just some fixups. Fixup: - Fixup mb() synchronization problem - Fixup dma_alloc_coherent with PAGE_SO attribute - Fixup cache_op failed when cross memory ZONEs - Optimize arch_sync_dma_for_cpu/device with dma_inv_range - Fixup ioremap function losing - Fixup arch_get_unmapped_area() implementation - Fixup defer cache flush for 610 - Support kernel non-aligned access - Fixup 610 vipt cache flush mechanism - Fixup add zero_fp fixup perf backtrace panic - Move static keyword to the front of declaration - Fixup csky_pmu.max_period assignment - Use generic free_initrd_mem() - entry: Remove unneeded need_resched() loop CI-Tested: https://gitlab.com/c-sky/buildroot/pipelines/77689888 -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE2KAv+isbWR/viAKHAXH1GYaIxXsFAl2Rfc0SHHJlbl9ndW9A Yy1za3kuY29tAAoJEAFx9RmGiMV7eEUQAIuuO1ym/o7zMWZsIRbISJYi6xuq752W RVhnPv957ktFYlqrtelDuZwkCPnK03YDTv8lPzcIhes+xYtuspN6NMum7SUWPt4c IbfQe4GmMwPGNrJ76NO9YcWQig8flT75wWE2CzOjhGpBfEkEHmtbOvOiZujcq4yN vhj8TKF9CjOSaDJNCOXinC6DeGoftRYTSRq6NMPfFfHIWqFcZIyb1Fz8tE/vFP4Y qEoG/ys/eu114DIZVnxr5ihmrJ4gjxmlXlnYA8WMRnRt6/oHEmmbtHLTT2eHbI2T u4TCssqrLoNADV7g7zyAyBnrgf4dXnJivGjc2NzVLAkgNbEJn+oGNYn+kdiRGd5X 1CNVbzbZN0gHwLayDjJ4BWNxtpxxqmOjlDffjLVRW7dleTdfHvcxJwfhlvbQOPuq nMj4t1qJswn44f/bsj+F13hgXV0tWctYui/HS78xscE7t4yMNduf3JAm7TIxT0XN ej3102ffm4ycKZtfdwKwcACmMBJc+2QvGYmQo2L9pVLYIQe3QUWYs881V50PJXxV jdz4kmhpfKLie+yxmsdN1/8nTlcHF5wDiYwW9UColzfz1fCRkoPRx5tu/YI9zLoi K41CFEv4Z+aVzcp4HZNmOvVhGWgdmuwICMdY16wawhN6SAkvKJBFaP4g24h0J95M QyAPQl/VUMED =FLYg -----END PGP SIGNATURE----- Merge tag 'csky-for-linus-5.4-rc1' of git://github.com/c-sky/csky-linux Pull csky updates from Guo Ren: "This round of csky subsystem just some fixups: - Fix mb() synchronization problem - Fix dma_alloc_coherent with PAGE_SO attribute - Fix cache_op failed when cross memory ZONEs - Optimize arch_sync_dma_for_cpu/device with dma_inv_range - Fix ioremap function losing - Fix arch_get_unmapped_area() implementation - Fix defer cache flush for 610 - Support kernel non-aligned access - Fix 610 vipt cache flush mechanism - Fix add zero_fp fixup perf backtrace panic - Move static keyword to the front of declaration - Fix csky_pmu.max_period assignment - Use generic free_initrd_mem() - entry: Remove unneeded need_resched() loop" * tag 'csky-for-linus-5.4-rc1' of git://github.com/c-sky/csky-linux: csky: Move static keyword to the front of declaration csky: entry: Remove unneeded need_resched() loop csky: Fixup csky_pmu.max_period assignment csky: Fixup add zero_fp fixup perf backtrace panic csky: Use generic free_initrd_mem() csky: Fixup 610 vipt cache flush mechanism csky: Support kernel non-aligned access csky: Fixup defer cache flush for 610 csky: Fixup arch_get_unmapped_area() implementation csky: Fixup ioremap function losing csky: Optimize arch_sync_dma_for_cpu/device with dma_inv_range csky/dma: Fixup cache_op failed when cross memory ZONEs csky: Fixup dma_alloc_coherent with PAGE_SO attribute csky: Fixup mb() synchronization problem
This commit is contained in:
commit
80b29b6b8c
|
@ -5,8 +5,10 @@
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
|
||||||
static int align_enable = 1;
|
static int align_kern_enable = 1;
|
||||||
static int align_count;
|
static int align_usr_enable = 1;
|
||||||
|
static int align_kern_count = 0;
|
||||||
|
static int align_usr_count = 0;
|
||||||
|
|
||||||
static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx)
|
static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx)
|
||||||
{
|
{
|
||||||
|
@ -32,9 +34,6 @@ static int ldb_asm(uint32_t addr, uint32_t *valp)
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!access_ok((void *)addr, 1))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movi %0, 0\n"
|
"movi %0, 0\n"
|
||||||
"1:\n"
|
"1:\n"
|
||||||
|
@ -67,9 +66,6 @@ static int stb_asm(uint32_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!access_ok((void *)addr, 1))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movi %0, 0\n"
|
"movi %0, 0\n"
|
||||||
"1:\n"
|
"1:\n"
|
||||||
|
@ -203,8 +199,6 @@ static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
|
||||||
if (stb_asm(addr, byte3))
|
if (stb_asm(addr, byte3))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
align_count++;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +220,14 @@ void csky_alignment(struct pt_regs *regs)
|
||||||
uint32_t addr = 0;
|
uint32_t addr = 0;
|
||||||
|
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
|
goto kernel_area;
|
||||||
|
|
||||||
|
if (!align_usr_enable) {
|
||||||
|
pr_err("%s user disabled.\n", __func__);
|
||||||
goto bad_area;
|
goto bad_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
align_usr_count++;
|
||||||
|
|
||||||
ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
|
ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -234,6 +235,19 @@ void csky_alignment(struct pt_regs *regs)
|
||||||
goto bad_area;
|
goto bad_area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goto good_area;
|
||||||
|
|
||||||
|
kernel_area:
|
||||||
|
if (!align_kern_enable) {
|
||||||
|
pr_err("%s kernel disabled.\n", __func__);
|
||||||
|
goto bad_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
align_kern_count++;
|
||||||
|
|
||||||
|
tmp = *(uint16_t *)instruction_pointer(regs);
|
||||||
|
|
||||||
|
good_area:
|
||||||
opcode = (uint32_t)tmp;
|
opcode = (uint32_t)tmp;
|
||||||
|
|
||||||
rx = opcode & 0xf;
|
rx = opcode & 0xf;
|
||||||
|
@ -286,18 +300,32 @@ void csky_alignment(struct pt_regs *regs)
|
||||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
|
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ctl_table alignment_tbl[4] = {
|
static struct ctl_table alignment_tbl[5] = {
|
||||||
{
|
{
|
||||||
.procname = "enable",
|
.procname = "kernel_enable",
|
||||||
.data = &align_enable,
|
.data = &align_kern_enable,
|
||||||
.maxlen = sizeof(align_enable),
|
.maxlen = sizeof(align_kern_enable),
|
||||||
.mode = 0666,
|
.mode = 0666,
|
||||||
.proc_handler = &proc_dointvec
|
.proc_handler = &proc_dointvec
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.procname = "count",
|
.procname = "user_enable",
|
||||||
.data = &align_count,
|
.data = &align_usr_enable,
|
||||||
.maxlen = sizeof(align_count),
|
.maxlen = sizeof(align_usr_enable),
|
||||||
|
.mode = 0666,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.procname = "kernel_count",
|
||||||
|
.data = &align_kern_count,
|
||||||
|
.maxlen = sizeof(align_kern_count),
|
||||||
|
.mode = 0666,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.procname = "user_count",
|
||||||
|
.data = &align_usr_count,
|
||||||
|
.maxlen = sizeof(align_usr_count),
|
||||||
.mode = 0666,
|
.mode = 0666,
|
||||||
.proc_handler = &proc_dointvec
|
.proc_handler = &proc_dointvec
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,42 +11,66 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cachectl.h>
|
#include <asm/cachectl.h>
|
||||||
|
|
||||||
|
#define PG_dcache_clean PG_arch_1
|
||||||
|
|
||||||
void flush_dcache_page(struct page *page)
|
void flush_dcache_page(struct page *page)
|
||||||
{
|
{
|
||||||
struct address_space *mapping = page_mapping(page);
|
struct address_space *mapping;
|
||||||
unsigned long addr;
|
|
||||||
|
|
||||||
if (mapping && !mapping_mapped(mapping)) {
|
if (page == ZERO_PAGE(0))
|
||||||
set_bit(PG_arch_1, &(page)->flags);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
mapping = page_mapping_file(page);
|
||||||
|
|
||||||
|
if (mapping && !page_mapcount(page))
|
||||||
|
clear_bit(PG_dcache_clean, &page->flags);
|
||||||
|
else {
|
||||||
|
dcache_wbinv_all();
|
||||||
|
if (mapping)
|
||||||
|
icache_inv_all();
|
||||||
|
set_bit(PG_dcache_clean, &page->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We could delay the flush for the !page_mapping case too. But that
|
|
||||||
* case is for exec env/arg pages and those are %99 certainly going to
|
|
||||||
* get faulted into the tlb (and thus flushed) anyways.
|
|
||||||
*/
|
|
||||||
addr = (unsigned long) page_address(page);
|
|
||||||
dcache_wb_range(addr, addr + PAGE_SIZE);
|
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(flush_dcache_page);
|
||||||
|
|
||||||
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
|
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
|
||||||
pte_t *pte)
|
pte_t *ptep)
|
||||||
{
|
{
|
||||||
unsigned long addr;
|
unsigned long pfn = pte_pfn(*ptep);
|
||||||
struct page *page;
|
struct page *page;
|
||||||
unsigned long pfn;
|
|
||||||
|
|
||||||
pfn = pte_pfn(*pte);
|
if (!pfn_valid(pfn))
|
||||||
if (unlikely(!pfn_valid(pfn)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
page = pfn_to_page(pfn);
|
page = pfn_to_page(pfn);
|
||||||
addr = (unsigned long) page_address(page);
|
if (page == ZERO_PAGE(0))
|
||||||
|
return;
|
||||||
|
|
||||||
if (vma->vm_flags & VM_EXEC ||
|
if (!test_and_set_bit(PG_dcache_clean, &page->flags))
|
||||||
pages_do_alias(addr, address & PAGE_MASK))
|
dcache_wbinv_all();
|
||||||
cache_wbinv_all();
|
|
||||||
|
|
||||||
clear_bit(PG_arch_1, &(page)->flags);
|
if (page_mapping_file(page)) {
|
||||||
|
if (vma->vm_flags & VM_EXEC)
|
||||||
|
icache_inv_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_kernel_dcache_page(struct page *page)
|
||||||
|
{
|
||||||
|
struct address_space *mapping;
|
||||||
|
|
||||||
|
mapping = page_mapping_file(page);
|
||||||
|
|
||||||
|
if (!mapping || mapping_mapped(mapping))
|
||||||
|
dcache_wbinv_all();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(flush_kernel_dcache_page);
|
||||||
|
|
||||||
|
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
|
||||||
|
unsigned long end)
|
||||||
|
{
|
||||||
|
dcache_wbinv_all();
|
||||||
|
|
||||||
|
if (vma->vm_flags & VM_EXEC)
|
||||||
|
icache_inv_all();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,46 +4,63 @@
|
||||||
#ifndef __ABI_CSKY_CACHEFLUSH_H
|
#ifndef __ABI_CSKY_CACHEFLUSH_H
|
||||||
#define __ABI_CSKY_CACHEFLUSH_H
|
#define __ABI_CSKY_CACHEFLUSH_H
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/mm.h>
|
||||||
#include <asm/string.h>
|
#include <asm/string.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
|
||||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
||||||
extern void flush_dcache_page(struct page *);
|
extern void flush_dcache_page(struct page *);
|
||||||
|
|
||||||
#define flush_cache_mm(mm) cache_wbinv_all()
|
#define flush_cache_mm(mm) dcache_wbinv_all()
|
||||||
#define flush_cache_page(vma, page, pfn) cache_wbinv_all()
|
#define flush_cache_page(vma, page, pfn) cache_wbinv_all()
|
||||||
#define flush_cache_dup_mm(mm) cache_wbinv_all()
|
#define flush_cache_dup_mm(mm) cache_wbinv_all()
|
||||||
|
|
||||||
|
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
|
||||||
|
extern void flush_kernel_dcache_page(struct page *);
|
||||||
|
|
||||||
|
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages)
|
||||||
|
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
|
||||||
|
|
||||||
|
static inline void flush_kernel_vmap_range(void *addr, int size)
|
||||||
|
{
|
||||||
|
dcache_wbinv_all();
|
||||||
|
}
|
||||||
|
static inline void invalidate_kernel_vmap_range(void *addr, int size)
|
||||||
|
{
|
||||||
|
dcache_wbinv_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ARCH_HAS_FLUSH_ANON_PAGE
|
||||||
|
static inline void flush_anon_page(struct vm_area_struct *vma,
|
||||||
|
struct page *page, unsigned long vmaddr)
|
||||||
|
{
|
||||||
|
if (PageAnon(page))
|
||||||
|
cache_wbinv_all();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if (current_mm != vma->mm) cache_wbinv_range(start, end) will be broken.
|
* if (current_mm != vma->mm) cache_wbinv_range(start, end) will be broken.
|
||||||
* Use cache_wbinv_all() here and need to be improved in future.
|
* Use cache_wbinv_all() here and need to be improved in future.
|
||||||
*/
|
*/
|
||||||
#define flush_cache_range(vma, start, end) cache_wbinv_all()
|
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
|
||||||
#define flush_cache_vmap(start, end) cache_wbinv_range(start, end)
|
#define flush_cache_vmap(start, end) cache_wbinv_all()
|
||||||
#define flush_cache_vunmap(start, end) cache_wbinv_range(start, end)
|
#define flush_cache_vunmap(start, end) cache_wbinv_all()
|
||||||
|
|
||||||
#define flush_icache_page(vma, page) cache_wbinv_all()
|
#define flush_icache_page(vma, page) do {} while (0);
|
||||||
#define flush_icache_range(start, end) cache_wbinv_range(start, end)
|
#define flush_icache_range(start, end) cache_wbinv_range(start, end)
|
||||||
|
|
||||||
#define flush_icache_user_range(vma, pg, adr, len) \
|
#define flush_icache_user_range(vma,page,addr,len) \
|
||||||
cache_wbinv_range(adr, adr + len)
|
flush_dcache_page(page)
|
||||||
|
|
||||||
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
||||||
do { \
|
do { \
|
||||||
cache_wbinv_all(); \
|
|
||||||
memcpy(dst, src, len); \
|
memcpy(dst, src, len); \
|
||||||
cache_wbinv_all(); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||||
do { \
|
do { \
|
||||||
cache_wbinv_all(); \
|
|
||||||
memcpy(dst, src, len); \
|
memcpy(dst, src, len); \
|
||||||
cache_wbinv_all(); \
|
cache_wbinv_all(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define flush_dcache_mmap_lock(mapping) do {} while (0)
|
|
||||||
#define flush_dcache_mmap_unlock(mapping) do {} while (0)
|
|
||||||
|
|
||||||
#endif /* __ABI_CSKY_CACHEFLUSH_H */
|
#endif /* __ABI_CSKY_CACHEFLUSH_H */
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
|
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
|
||||||
|
|
||||||
extern unsigned long shm_align_mask;
|
#include <asm/shmparam.h>
|
||||||
|
|
||||||
extern void flush_dcache_page(struct page *page);
|
extern void flush_dcache_page(struct page *page);
|
||||||
|
|
||||||
static inline unsigned long pages_do_alias(unsigned long addr1,
|
static inline unsigned long pages_do_alias(unsigned long addr1,
|
||||||
unsigned long addr2)
|
unsigned long addr2)
|
||||||
{
|
{
|
||||||
return (addr1 ^ addr2) & shm_align_mask;
|
return (addr1 ^ addr2) & (SHMLBA-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void clear_user_page(void *addr, unsigned long vaddr,
|
static inline void clear_user_page(void *addr, unsigned long vaddr,
|
||||||
|
|
|
@ -9,58 +9,63 @@
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
unsigned long shm_align_mask = (0x4000 >> 1) - 1; /* Sane caches */
|
#define COLOUR_ALIGN(addr,pgoff) \
|
||||||
|
((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \
|
||||||
|
(((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
|
||||||
|
|
||||||
#define COLOUR_ALIGN(addr, pgoff) \
|
/*
|
||||||
((((addr) + shm_align_mask) & ~shm_align_mask) + \
|
* We need to ensure that shared mappings are correctly aligned to
|
||||||
(((pgoff) << PAGE_SHIFT) & shm_align_mask))
|
* avoid aliasing issues with VIPT caches. We need to ensure that
|
||||||
|
* a specific page of an object is always mapped at a multiple of
|
||||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
* SHMLBA bytes.
|
||||||
|
*
|
||||||
|
* We unconditionally provide this function for all cases.
|
||||||
|
*/
|
||||||
|
unsigned long
|
||||||
|
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||||
{
|
{
|
||||||
struct vm_area_struct *vmm;
|
struct mm_struct *mm = current->mm;
|
||||||
int do_color_align;
|
struct vm_area_struct *vma;
|
||||||
|
int do_align = 0;
|
||||||
|
struct vm_unmapped_area_info info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only need to do colour alignment if either the I or D
|
||||||
|
* caches alias.
|
||||||
|
*/
|
||||||
|
do_align = filp || (flags & MAP_SHARED);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We enforce the MAP_FIXED case.
|
||||||
|
*/
|
||||||
if (flags & MAP_FIXED) {
|
if (flags & MAP_FIXED) {
|
||||||
/*
|
if (flags & MAP_SHARED &&
|
||||||
* We do not accept a shared mapping if it would violate
|
(addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
|
||||||
* cache aliasing constraints.
|
|
||||||
*/
|
|
||||||
if ((flags & MAP_SHARED) &&
|
|
||||||
((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > TASK_SIZE)
|
if (len > TASK_SIZE)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
do_color_align = 0;
|
|
||||||
if (filp || (flags & MAP_SHARED))
|
|
||||||
do_color_align = 1;
|
|
||||||
if (addr) {
|
if (addr) {
|
||||||
if (do_color_align)
|
if (do_align)
|
||||||
addr = COLOUR_ALIGN(addr, pgoff);
|
addr = COLOUR_ALIGN(addr, pgoff);
|
||||||
else
|
else
|
||||||
addr = PAGE_ALIGN(addr);
|
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) {
|
vma = find_vma(mm, addr);
|
||||||
/* At this point: (!vmm || addr < vmm->vm_end). */
|
if (TASK_SIZE - len >= addr &&
|
||||||
if (TASK_SIZE - len < addr)
|
(!vma || addr + len <= vm_start_gap(vma)))
|
||||||
return -ENOMEM;
|
|
||||||
if (!vmm || addr + len <= vmm->vm_start)
|
|
||||||
return addr;
|
return addr;
|
||||||
addr = vmm->vm_end;
|
|
||||||
if (do_color_align)
|
|
||||||
addr = COLOUR_ALIGN(addr, pgoff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.flags = 0;
|
||||||
|
info.length = len;
|
||||||
|
info.low_limit = mm->mmap_base;
|
||||||
|
info.high_limit = TASK_SIZE;
|
||||||
|
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||||
|
info.align_offset = pgoff << PAGE_SHIFT;
|
||||||
|
return vm_unmapped_area(&info);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,12 @@
|
||||||
#define nop() asm volatile ("nop\n":::"memory")
|
#define nop() asm volatile ("nop\n":::"memory")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sync: completion barrier
|
* sync: completion barrier, all sync.xx instructions
|
||||||
* sync.s: completion barrier and shareable to other cores
|
* guarantee the last response recieved by bus transaction
|
||||||
* sync.i: completion barrier with flush cpu pipeline
|
* made by ld/st instructions before sync.s
|
||||||
* sync.is: completion barrier with flush cpu pipeline and shareable to
|
* sync.s: inherit from sync, but also shareable to other cores
|
||||||
* other cores
|
* sync.i: inherit from sync, but also flush cpu pipeline
|
||||||
|
* sync.is: the same with sync.i + sync.s
|
||||||
*
|
*
|
||||||
* bar.brwarw: ordering barrier for all load/store instructions before it
|
* bar.brwarw: ordering barrier for all load/store instructions before it
|
||||||
* bar.brwarws: ordering barrier for all load/store instructions before it
|
* bar.brwarws: ordering barrier for all load/store instructions before it
|
||||||
|
@ -27,9 +28,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_HAS_CACHEV2
|
#ifdef CONFIG_CPU_HAS_CACHEV2
|
||||||
#define mb() asm volatile ("bar.brwarw\n":::"memory")
|
#define mb() asm volatile ("sync.s\n":::"memory")
|
||||||
#define rmb() asm volatile ("bar.brar\n":::"memory")
|
|
||||||
#define wmb() asm volatile ("bar.bwaw\n":::"memory")
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#define __smp_mb() asm volatile ("bar.brwarws\n":::"memory")
|
#define __smp_mb() asm volatile ("bar.brwarws\n":::"memory")
|
||||||
|
|
|
@ -24,6 +24,7 @@ void cache_wbinv_range(unsigned long start, unsigned long end);
|
||||||
void cache_wbinv_all(void);
|
void cache_wbinv_all(void);
|
||||||
|
|
||||||
void dma_wbinv_range(unsigned long start, unsigned long end);
|
void dma_wbinv_range(unsigned long start, unsigned long end);
|
||||||
|
void dma_inv_range(unsigned long start, unsigned long end);
|
||||||
void dma_wb_range(unsigned long start, unsigned long end);
|
void dma_wb_range(unsigned long start, unsigned long end);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,17 +4,10 @@
|
||||||
#ifndef __ASM_CSKY_IO_H
|
#ifndef __ASM_CSKY_IO_H
|
||||||
#define __ASM_CSKY_IO_H
|
#define __ASM_CSKY_IO_H
|
||||||
|
|
||||||
#include <abi/pgtable-bits.h>
|
#include <asm/pgtable.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
extern void __iomem *ioremap(phys_addr_t offset, size_t size);
|
|
||||||
|
|
||||||
extern void iounmap(void *addr);
|
|
||||||
|
|
||||||
extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
|
|
||||||
size_t size, unsigned long flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I/O memory access primitives. Reads are ordered relative to any
|
* I/O memory access primitives. Reads are ordered relative to any
|
||||||
* following Normal memory access. Writes are ordered relative to any prior
|
* following Normal memory access. Writes are ordered relative to any prior
|
||||||
|
@ -40,9 +33,17 @@ extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
|
||||||
#define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); })
|
#define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); })
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ioremap_nocache(phy, sz) ioremap(phy, sz)
|
/*
|
||||||
#define ioremap_wc ioremap_nocache
|
* I/O memory mapping functions.
|
||||||
#define ioremap_wt ioremap_nocache
|
*/
|
||||||
|
extern void __iomem *ioremap_cache(phys_addr_t addr, size_t size);
|
||||||
|
extern void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot);
|
||||||
|
extern void iounmap(void *addr);
|
||||||
|
|
||||||
|
#define ioremap(addr, size) __ioremap((addr), (size), pgprot_noncached(PAGE_KERNEL))
|
||||||
|
#define ioremap_wc(addr, size) __ioremap((addr), (size), pgprot_writecombine(PAGE_KERNEL))
|
||||||
|
#define ioremap_nocache(addr, size) ioremap((addr), (size))
|
||||||
|
#define ioremap_cache ioremap_cache
|
||||||
|
|
||||||
#include <asm-generic/io.h>
|
#include <asm-generic/io.h>
|
||||||
|
|
||||||
|
|
|
@ -258,6 +258,16 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
|
||||||
{
|
{
|
||||||
unsigned long prot = pgprot_val(_prot);
|
unsigned long prot = pgprot_val(_prot);
|
||||||
|
|
||||||
|
prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED | _PAGE_SO;
|
||||||
|
|
||||||
|
return __pgprot(prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define pgprot_writecombine pgprot_writecombine
|
||||||
|
static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
|
||||||
|
{
|
||||||
|
unsigned long prot = pgprot_val(_prot);
|
||||||
|
|
||||||
prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
|
prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
|
||||||
|
|
||||||
return __pgprot(prot);
|
return __pgprot(prot);
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
#define PTE_INDX_SHIFT 10
|
#define PTE_INDX_SHIFT 10
|
||||||
#define _PGDIR_SHIFT 22
|
#define _PGDIR_SHIFT 22
|
||||||
|
|
||||||
|
.macro zero_fp
|
||||||
|
#ifdef CONFIG_STACKTRACE
|
||||||
|
movi r8, 0
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
.macro tlbop_begin name, val0, val1, val2
|
.macro tlbop_begin name, val0, val1, val2
|
||||||
ENTRY(csky_\name)
|
ENTRY(csky_\name)
|
||||||
mtcr a3, ss2
|
mtcr a3, ss2
|
||||||
|
@ -96,6 +102,7 @@ ENTRY(csky_\name)
|
||||||
SAVE_ALL 0
|
SAVE_ALL 0
|
||||||
.endm
|
.endm
|
||||||
.macro tlbop_end is_write
|
.macro tlbop_end is_write
|
||||||
|
zero_fp
|
||||||
RD_MEH a2
|
RD_MEH a2
|
||||||
psrset ee, ie
|
psrset ee, ie
|
||||||
mov a0, sp
|
mov a0, sp
|
||||||
|
@ -120,6 +127,7 @@ tlbop_end 1
|
||||||
|
|
||||||
ENTRY(csky_systemcall)
|
ENTRY(csky_systemcall)
|
||||||
SAVE_ALL TRAP0_SIZE
|
SAVE_ALL TRAP0_SIZE
|
||||||
|
zero_fp
|
||||||
|
|
||||||
psrset ee, ie
|
psrset ee, ie
|
||||||
|
|
||||||
|
@ -136,9 +144,9 @@ ENTRY(csky_systemcall)
|
||||||
mov r9, sp
|
mov r9, sp
|
||||||
bmaski r10, THREAD_SHIFT
|
bmaski r10, THREAD_SHIFT
|
||||||
andn r9, r10
|
andn r9, r10
|
||||||
ldw r8, (r9, TINFO_FLAGS)
|
ldw r12, (r9, TINFO_FLAGS)
|
||||||
ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
|
ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
|
||||||
cmpnei r8, 0
|
cmpnei r12, 0
|
||||||
bt csky_syscall_trace
|
bt csky_syscall_trace
|
||||||
#if defined(__CSKYABIV2__)
|
#if defined(__CSKYABIV2__)
|
||||||
subi sp, 8
|
subi sp, 8
|
||||||
|
@ -180,7 +188,7 @@ csky_syscall_trace:
|
||||||
|
|
||||||
ENTRY(ret_from_kernel_thread)
|
ENTRY(ret_from_kernel_thread)
|
||||||
jbsr schedule_tail
|
jbsr schedule_tail
|
||||||
mov a0, r8
|
mov a0, r10
|
||||||
jsr r9
|
jsr r9
|
||||||
jbsr ret_from_exception
|
jbsr ret_from_exception
|
||||||
|
|
||||||
|
@ -189,9 +197,9 @@ ENTRY(ret_from_fork)
|
||||||
mov r9, sp
|
mov r9, sp
|
||||||
bmaski r10, THREAD_SHIFT
|
bmaski r10, THREAD_SHIFT
|
||||||
andn r9, r10
|
andn r9, r10
|
||||||
ldw r8, (r9, TINFO_FLAGS)
|
ldw r12, (r9, TINFO_FLAGS)
|
||||||
ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
|
ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
|
||||||
cmpnei r8, 0
|
cmpnei r12, 0
|
||||||
bf ret_from_exception
|
bf ret_from_exception
|
||||||
mov a0, sp /* sp = pt_regs pointer */
|
mov a0, sp /* sp = pt_regs pointer */
|
||||||
jbsr syscall_trace_exit
|
jbsr syscall_trace_exit
|
||||||
|
@ -209,9 +217,9 @@ ret_from_exception:
|
||||||
bmaski r10, THREAD_SHIFT
|
bmaski r10, THREAD_SHIFT
|
||||||
andn r9, r10
|
andn r9, r10
|
||||||
|
|
||||||
ldw r8, (r9, TINFO_FLAGS)
|
ldw r12, (r9, TINFO_FLAGS)
|
||||||
andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
|
andi r12, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
|
||||||
cmpnei r8, 0
|
cmpnei r12, 0
|
||||||
bt exit_work
|
bt exit_work
|
||||||
1:
|
1:
|
||||||
RESTORE_ALL
|
RESTORE_ALL
|
||||||
|
@ -220,11 +228,11 @@ exit_work:
|
||||||
lrw syscallid, ret_from_exception
|
lrw syscallid, ret_from_exception
|
||||||
mov lr, syscallid
|
mov lr, syscallid
|
||||||
|
|
||||||
btsti r8, TIF_NEED_RESCHED
|
btsti r12, TIF_NEED_RESCHED
|
||||||
bt work_resched
|
bt work_resched
|
||||||
|
|
||||||
mov a0, sp
|
mov a0, sp
|
||||||
mov a1, r8
|
mov a1, r12
|
||||||
jmpi do_notify_resume
|
jmpi do_notify_resume
|
||||||
|
|
||||||
work_resched:
|
work_resched:
|
||||||
|
@ -232,6 +240,7 @@ work_resched:
|
||||||
|
|
||||||
ENTRY(csky_trap)
|
ENTRY(csky_trap)
|
||||||
SAVE_ALL 0
|
SAVE_ALL 0
|
||||||
|
zero_fp
|
||||||
psrset ee
|
psrset ee
|
||||||
mov a0, sp /* Push Stack pointer arg */
|
mov a0, sp /* Push Stack pointer arg */
|
||||||
jbsr trap_c /* Call C-level trap handler */
|
jbsr trap_c /* Call C-level trap handler */
|
||||||
|
@ -265,6 +274,7 @@ ENTRY(csky_get_tls)
|
||||||
|
|
||||||
ENTRY(csky_irq)
|
ENTRY(csky_irq)
|
||||||
SAVE_ALL 0
|
SAVE_ALL 0
|
||||||
|
zero_fp
|
||||||
psrset ee
|
psrset ee
|
||||||
|
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
|
@ -276,27 +286,23 @@ ENTRY(csky_irq)
|
||||||
* Get task_struct->stack.preempt_count for current,
|
* Get task_struct->stack.preempt_count for current,
|
||||||
* and increase 1.
|
* and increase 1.
|
||||||
*/
|
*/
|
||||||
ldw r8, (r9, TINFO_PREEMPT)
|
ldw r12, (r9, TINFO_PREEMPT)
|
||||||
addi r8, 1
|
addi r12, 1
|
||||||
stw r8, (r9, TINFO_PREEMPT)
|
stw r12, (r9, TINFO_PREEMPT)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mov a0, sp
|
mov a0, sp
|
||||||
jbsr csky_do_IRQ
|
jbsr csky_do_IRQ
|
||||||
|
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
subi r8, 1
|
subi r12, 1
|
||||||
stw r8, (r9, TINFO_PREEMPT)
|
stw r12, (r9, TINFO_PREEMPT)
|
||||||
cmpnei r8, 0
|
cmpnei r12, 0
|
||||||
bt 2f
|
bt 2f
|
||||||
ldw r8, (r9, TINFO_FLAGS)
|
ldw r12, (r9, TINFO_FLAGS)
|
||||||
btsti r8, TIF_NEED_RESCHED
|
btsti r12, TIF_NEED_RESCHED
|
||||||
bf 2f
|
bf 2f
|
||||||
1:
|
|
||||||
jbsr preempt_schedule_irq /* irq en/disable is done inside */
|
jbsr preempt_schedule_irq /* irq en/disable is done inside */
|
||||||
ldw r7, (r9, TINFO_FLAGS) /* get new tasks TI_FLAGS */
|
|
||||||
btsti r7, TIF_NEED_RESCHED
|
|
||||||
bt 1b /* go again */
|
|
||||||
#endif
|
#endif
|
||||||
2:
|
2:
|
||||||
jmpi ret_from_exception
|
jmpi ret_from_exception
|
||||||
|
|
|
@ -1306,7 +1306,7 @@ int csky_pmu_device_probe(struct platform_device *pdev,
|
||||||
&csky_pmu.count_width)) {
|
&csky_pmu.count_width)) {
|
||||||
csky_pmu.count_width = DEFAULT_COUNT_WIDTH;
|
csky_pmu.count_width = DEFAULT_COUNT_WIDTH;
|
||||||
}
|
}
|
||||||
csky_pmu.max_period = BIT(csky_pmu.count_width) - 1;
|
csky_pmu.max_period = BIT_ULL(csky_pmu.count_width) - 1;
|
||||||
|
|
||||||
csky_pmu.plat_device = pdev;
|
csky_pmu.plat_device = pdev;
|
||||||
|
|
||||||
|
@ -1337,7 +1337,7 @@ int csky_pmu_device_probe(struct platform_device *pdev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct of_device_id csky_pmu_of_device_ids[] = {
|
static const struct of_device_id csky_pmu_of_device_ids[] = {
|
||||||
{.compatible = "csky,csky-pmu"},
|
{.compatible = "csky,csky-pmu"},
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ int copy_thread(unsigned long clone_flags,
|
||||||
if (unlikely(p->flags & PF_KTHREAD)) {
|
if (unlikely(p->flags & PF_KTHREAD)) {
|
||||||
memset(childregs, 0, sizeof(struct pt_regs));
|
memset(childregs, 0, sizeof(struct pt_regs));
|
||||||
childstack->r15 = (unsigned long) ret_from_kernel_thread;
|
childstack->r15 = (unsigned long) ret_from_kernel_thread;
|
||||||
childstack->r8 = kthread_arg;
|
childstack->r10 = kthread_arg;
|
||||||
childstack->r9 = usp;
|
childstack->r9 = usp;
|
||||||
childregs->sr = mfcr("psr");
|
childregs->sr = mfcr("psr");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -120,7 +120,12 @@ void dma_wbinv_range(unsigned long start, unsigned long end)
|
||||||
cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
|
cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dma_inv_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void dma_wb_range(unsigned long start, unsigned long end)
|
void dma_wb_range(unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
cache_op_range(start, end, DATA_CACHE|CACHE_INV, 1);
|
cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,11 +69,20 @@ void dma_wbinv_range(unsigned long start, unsigned long end)
|
||||||
sync_is();
|
sync_is();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dma_inv_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
unsigned long i = start & ~(L1_CACHE_BYTES - 1);
|
||||||
|
|
||||||
|
for (; i < end; i += L1_CACHE_BYTES)
|
||||||
|
asm volatile("dcache.iva %0\n"::"r"(i):"memory");
|
||||||
|
sync_is();
|
||||||
|
}
|
||||||
|
|
||||||
void dma_wb_range(unsigned long start, unsigned long end)
|
void dma_wb_range(unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
unsigned long i = start & ~(L1_CACHE_BYTES - 1);
|
unsigned long i = start & ~(L1_CACHE_BYTES - 1);
|
||||||
|
|
||||||
for (; i < end; i += L1_CACHE_BYTES)
|
for (; i < end; i += L1_CACHE_BYTES)
|
||||||
asm volatile("dcache.civa %0\n"::"r"(i):"memory");
|
asm volatile("dcache.cva %0\n"::"r"(i):"memory");
|
||||||
sync_is();
|
sync_is();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,69 +14,50 @@
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
|
||||||
void arch_dma_prep_coherent(struct page *page, size_t size)
|
|
||||||
{
|
|
||||||
if (PageHighMem(page)) {
|
|
||||||
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
|
|
||||||
|
|
||||||
do {
|
|
||||||
void *ptr = kmap_atomic(page);
|
|
||||||
size_t _size = (size < PAGE_SIZE) ? size : PAGE_SIZE;
|
|
||||||
|
|
||||||
memset(ptr, 0, _size);
|
|
||||||
dma_wbinv_range((unsigned long)ptr,
|
|
||||||
(unsigned long)ptr + _size);
|
|
||||||
|
|
||||||
kunmap_atomic(ptr);
|
|
||||||
|
|
||||||
page++;
|
|
||||||
size -= PAGE_SIZE;
|
|
||||||
count--;
|
|
||||||
} while (count);
|
|
||||||
} else {
|
|
||||||
void *ptr = page_address(page);
|
|
||||||
|
|
||||||
memset(ptr, 0, size);
|
|
||||||
dma_wbinv_range((unsigned long)ptr, (unsigned long)ptr + size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cache_op(phys_addr_t paddr, size_t size,
|
static inline void cache_op(phys_addr_t paddr, size_t size,
|
||||||
void (*fn)(unsigned long start, unsigned long end))
|
void (*fn)(unsigned long start, unsigned long end))
|
||||||
{
|
{
|
||||||
struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
|
struct page *page = phys_to_page(paddr);
|
||||||
unsigned int offset = paddr & ~PAGE_MASK;
|
void *start = __va(page_to_phys(page));
|
||||||
size_t left = size;
|
unsigned long offset = offset_in_page(paddr);
|
||||||
unsigned long start;
|
size_t left = size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
size_t len = left;
|
size_t len = left;
|
||||||
|
|
||||||
|
if (offset + len > PAGE_SIZE)
|
||||||
|
len = PAGE_SIZE - offset;
|
||||||
|
|
||||||
if (PageHighMem(page)) {
|
if (PageHighMem(page)) {
|
||||||
void *addr;
|
start = kmap_atomic(page);
|
||||||
|
|
||||||
if (offset + len > PAGE_SIZE) {
|
fn((unsigned long)start + offset,
|
||||||
if (offset >= PAGE_SIZE) {
|
(unsigned long)start + offset + len);
|
||||||
page += offset >> PAGE_SHIFT;
|
|
||||||
offset &= ~PAGE_MASK;
|
|
||||||
}
|
|
||||||
len = PAGE_SIZE - offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = kmap_atomic(page);
|
kunmap_atomic(start);
|
||||||
start = (unsigned long)(addr + offset);
|
|
||||||
fn(start, start + len);
|
|
||||||
kunmap_atomic(addr);
|
|
||||||
} else {
|
} else {
|
||||||
start = (unsigned long)phys_to_virt(paddr);
|
fn((unsigned long)start + offset,
|
||||||
fn(start, start + size);
|
(unsigned long)start + offset + len);
|
||||||
}
|
}
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
page++;
|
page++;
|
||||||
|
start += PAGE_SIZE;
|
||||||
left -= len;
|
left -= len;
|
||||||
} while (left);
|
} while (left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dma_wbinv_set_zero_range(unsigned long start, unsigned long end)
|
||||||
|
{
|
||||||
|
memset((void *)start, 0, end - start);
|
||||||
|
dma_wbinv_range(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_dma_prep_coherent(struct page *page, size_t size)
|
||||||
|
{
|
||||||
|
cache_op(page_to_phys(page), size, dma_wbinv_set_zero_range);
|
||||||
|
}
|
||||||
|
|
||||||
void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
|
void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
|
||||||
size_t size, enum dma_data_direction dir)
|
size_t size, enum dma_data_direction dir)
|
||||||
{
|
{
|
||||||
|
@ -98,11 +79,10 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
|
||||||
{
|
{
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case DMA_TO_DEVICE:
|
case DMA_TO_DEVICE:
|
||||||
cache_op(paddr, size, dma_wb_range);
|
return;
|
||||||
break;
|
|
||||||
case DMA_FROM_DEVICE:
|
case DMA_FROM_DEVICE:
|
||||||
case DMA_BIDIRECTIONAL:
|
case DMA_BIDIRECTIONAL:
|
||||||
cache_op(paddr, size, dma_wbinv_range);
|
cache_op(paddr, size, dma_inv_range);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
|
|
|
@ -60,22 +60,6 @@ void __init mem_init(void)
|
||||||
mem_init_print_info(NULL);
|
mem_init_print_info(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
|
||||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
|
||||||
{
|
|
||||||
if (start < end)
|
|
||||||
pr_info("Freeing initrd memory: %ldk freed\n",
|
|
||||||
(end - start) >> 10);
|
|
||||||
|
|
||||||
for (; start < end; start += PAGE_SIZE) {
|
|
||||||
ClearPageReserved(virt_to_page(start));
|
|
||||||
init_page_count(virt_to_page(start));
|
|
||||||
free_page(start);
|
|
||||||
totalram_pages_inc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern char __init_begin[], __init_end[];
|
extern char __init_begin[], __init_end[];
|
||||||
|
|
||||||
void free_initmem(void)
|
void free_initmem(void)
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
|
|
||||||
void __iomem *ioremap(phys_addr_t addr, size_t size)
|
static void __iomem *__ioremap_caller(phys_addr_t addr, size_t size,
|
||||||
|
pgprot_t prot, void *caller)
|
||||||
{
|
{
|
||||||
phys_addr_t last_addr;
|
phys_addr_t last_addr;
|
||||||
unsigned long offset, vaddr;
|
unsigned long offset, vaddr;
|
||||||
struct vm_struct *area;
|
struct vm_struct *area;
|
||||||
pgprot_t prot;
|
|
||||||
|
|
||||||
last_addr = addr + size - 1;
|
last_addr = addr + size - 1;
|
||||||
if (!size || last_addr < addr)
|
if (!size || last_addr < addr)
|
||||||
|
@ -23,15 +23,12 @@ void __iomem *ioremap(phys_addr_t addr, size_t size)
|
||||||
addr &= PAGE_MASK;
|
addr &= PAGE_MASK;
|
||||||
size = PAGE_ALIGN(size + offset);
|
size = PAGE_ALIGN(size + offset);
|
||||||
|
|
||||||
area = get_vm_area_caller(size, VM_ALLOC, __builtin_return_address(0));
|
area = get_vm_area_caller(size, VM_IOREMAP, caller);
|
||||||
if (!area)
|
if (!area)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
vaddr = (unsigned long)area->addr;
|
vaddr = (unsigned long)area->addr;
|
||||||
|
|
||||||
prot = __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE |
|
|
||||||
_PAGE_GLOBAL | _CACHE_UNCACHED | _PAGE_SO);
|
|
||||||
|
|
||||||
if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
|
if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
|
||||||
free_vm_area(area);
|
free_vm_area(area);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -39,7 +36,20 @@ void __iomem *ioremap(phys_addr_t addr, size_t size)
|
||||||
|
|
||||||
return (void __iomem *)(vaddr + offset);
|
return (void __iomem *)(vaddr + offset);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ioremap);
|
|
||||||
|
void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot)
|
||||||
|
{
|
||||||
|
return __ioremap_caller(phys_addr, size, prot,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__ioremap);
|
||||||
|
|
||||||
|
void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
|
||||||
|
{
|
||||||
|
return __ioremap_caller(phys_addr, size, PAGE_KERNEL,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ioremap_cache);
|
||||||
|
|
||||||
void iounmap(void __iomem *addr)
|
void iounmap(void __iomem *addr)
|
||||||
{
|
{
|
||||||
|
@ -51,10 +61,9 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
||||||
unsigned long size, pgprot_t vma_prot)
|
unsigned long size, pgprot_t vma_prot)
|
||||||
{
|
{
|
||||||
if (!pfn_valid(pfn)) {
|
if (!pfn_valid(pfn)) {
|
||||||
vma_prot.pgprot |= _PAGE_SO;
|
|
||||||
return pgprot_noncached(vma_prot);
|
return pgprot_noncached(vma_prot);
|
||||||
} else if (file->f_flags & O_SYNC) {
|
} else if (file->f_flags & O_SYNC) {
|
||||||
return pgprot_noncached(vma_prot);
|
return pgprot_writecombine(vma_prot);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vma_prot;
|
return vma_prot;
|
||||||
|
|
Loading…
Reference in New Issue