Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Hexagon: Implement basic cache-flush support

Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Richard Kuo and committed by
Linus Torvalds
2d3cbc78 013bf24c

+261
+34
arch/hexagon/include/asm/cache.h
··· 1 + /* 2 + * Cache definitions for the Hexagon architecture 3 + * 4 + * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 and 8 + * only version 2 as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the Free Software 17 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 + * 02110-1301, USA. 19 + */ 20 + 21 + #ifndef __ASM_CACHE_H 22 + #define __ASM_CACHE_H 23 + 24 + /* Bytes per L1 cache line */ 25 + #define L1_CACHE_SHIFT (5) 26 + #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) 27 + 28 + #define __cacheline_aligned __aligned(L1_CACHE_BYTES) 29 + #define ____cacheline_aligned __aligned(L1_CACHE_BYTES) 30 + 31 + /* See http://kerneltrap.org/node/15100 */ 32 + #define __read_mostly 33 + 34 + #endif
+99
arch/hexagon/include/asm/cacheflush.h
··· 1 + /* 2 + * Cache flush operations for the Hexagon architecture 3 + * 4 + * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 and 8 + * only version 2 as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the Free Software 17 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 + * 02110-1301, USA. 19 + */ 20 + 21 + #ifndef _ASM_CACHEFLUSH_H 22 + #define _ASM_CACHEFLUSH_H 23 + 24 + #include <linux/cache.h> 25 + #include <linux/mm.h> 26 + #include <asm/string.h> 27 + #include <asm-generic/cacheflush.h> 28 + 29 + /* Cache flushing: 30 + * 31 + * - flush_cache_all() flushes entire cache 32 + * - flush_cache_mm(mm) flushes the specified mm context's cache lines 33 + * - flush_cache_page(mm, vmaddr, pfn) flushes a single page 34 + * - flush_cache_range(vma, start, end) flushes a range of pages 35 + * - flush_icache_range(start, end) flush a range of instructions 36 + * - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache 37 + * - flush_icache_page(vma, pg) flushes(invalidates) a page for icache 38 + * 39 + * Need to doublecheck which one is really needed for ptrace stuff to work. 40 + */ 41 + #define LINESIZE 32 42 + #define LINEBITS 5 43 + 44 + /* 45 + * Flush Dcache range through current map. 46 + */ 47 + extern void flush_dcache_range(unsigned long start, unsigned long end); 48 + 49 + /* 50 + * Flush Icache range through current map. 51 + */ 52 + #undef flush_icache_range 53 + extern void flush_icache_range(unsigned long start, unsigned long end); 54 + 55 + /* 56 + * Memory-management related flushes are there to ensure in non-physically 57 + * indexed cache schemes that stale lines belonging to a given ASID aren't 58 + * in the cache to confuse things. The prototype Hexagon Virtual Machine 59 + * only uses a single ASID for all user-mode maps, which should 60 + * mean that they aren't necessary. A brute-force, flush-everything 61 + * implementation, with the name xxxxx_hexagon() is present in 62 + * arch/hexagon/mm/cache.c, but let's not wire it up until we know 63 + * it is needed. 64 + */ 65 + extern void flush_cache_all_hexagon(void); 66 + 67 + /* 68 + * This may or may not ever have to be non-null, depending on the 69 + * virtual machine MMU. For a native kernel, it's definitiely a no-op 70 + * 71 + * This is also the place where deferred cache coherency stuff seems 72 + * to happen, classically... but instead we do it like ia64 and 73 + * clean the cache when the PTE is set. 74 + * 75 + */ 76 + static inline void update_mmu_cache(struct vm_area_struct *vma, 77 + unsigned long address, pte_t *ptep) 78 + { 79 + /* generic_ptrace_pokedata doesn't wind up here, does it? */ 80 + } 81 + 82 + #undef copy_to_user_page 83 + static inline void copy_to_user_page(struct vm_area_struct *vma, 84 + struct page *page, 85 + unsigned long vaddr, 86 + void *dst, void *src, int len) 87 + { 88 + memcpy(dst, src, len); 89 + if (vma->vm_flags & VM_EXEC) { 90 + flush_icache_range((unsigned long) dst, 91 + (unsigned long) dst + len); 92 + } 93 + } 94 + 95 + 96 + extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end); 97 + extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end); 98 + 99 + #endif
+128
arch/hexagon/mm/cache.c
··· 1 + /* 2 + * Cache management functions for Hexagon 3 + * 4 + * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 and 8 + * only version 2 as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the Free Software 17 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 + * 02110-1301, USA. 19 + */ 20 + 21 + #include <linux/mm.h> 22 + #include <asm/cacheflush.h> 23 + #include <asm/hexagon_vm.h> 24 + 25 + #define spanlines(start, end) \ 26 + (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1) 27 + 28 + void flush_dcache_range(unsigned long start, unsigned long end) 29 + { 30 + unsigned long lines = spanlines(start, end-1); 31 + unsigned long i, flags; 32 + 33 + start &= ~(LINESIZE - 1); 34 + 35 + local_irq_save(flags); 36 + 37 + for (i = 0; i < lines; i++) { 38 + __asm__ __volatile__ ( 39 + " dccleaninva(%0); " 40 + : 41 + : "r" (start) 42 + ); 43 + start += LINESIZE; 44 + } 45 + local_irq_restore(flags); 46 + } 47 + 48 + void flush_icache_range(unsigned long start, unsigned long end) 49 + { 50 + unsigned long lines = spanlines(start, end-1); 51 + unsigned long i, flags; 52 + 53 + start &= ~(LINESIZE - 1); 54 + 55 + local_irq_save(flags); 56 + 57 + for (i = 0; i < lines; i++) { 58 + __asm__ __volatile__ ( 59 + " dccleana(%0); " 60 + " icinva(%0); " 61 + : 62 + : "r" (start) 63 + ); 64 + start += LINESIZE; 65 + } 66 + __asm__ __volatile__ ( 67 + "isync" 68 + ); 69 + local_irq_restore(flags); 70 + } 71 + 72 + void hexagon_clean_dcache_range(unsigned long start, unsigned long end) 73 + { 74 + unsigned long lines = spanlines(start, end-1); 75 + unsigned long i, flags; 76 + 77 + start &= ~(LINESIZE - 1); 78 + 79 + local_irq_save(flags); 80 + 81 + for (i = 0; i < lines; i++) { 82 + __asm__ __volatile__ ( 83 + " dccleana(%0); " 84 + : 85 + : "r" (start) 86 + ); 87 + start += LINESIZE; 88 + } 89 + local_irq_restore(flags); 90 + } 91 + 92 + void hexagon_inv_dcache_range(unsigned long start, unsigned long end) 93 + { 94 + unsigned long lines = spanlines(start, end-1); 95 + unsigned long i, flags; 96 + 97 + start &= ~(LINESIZE - 1); 98 + 99 + local_irq_save(flags); 100 + 101 + for (i = 0; i < lines; i++) { 102 + __asm__ __volatile__ ( 103 + " dcinva(%0); " 104 + : 105 + : "r" (start) 106 + ); 107 + start += LINESIZE; 108 + } 109 + local_irq_restore(flags); 110 + } 111 + 112 + 113 + 114 + 115 + /* 116 + * This is just really brutal and shouldn't be used anyways, 117 + * especially on V2. Left here just in case. 118 + */ 119 + void flush_cache_all_hexagon(void) 120 + { 121 + unsigned long flags; 122 + local_irq_save(flags); 123 + __vmcache_ickill(); 124 + __vmcache_dckill(); 125 + __vmcache_l2kill(); 126 + local_irq_restore(flags); 127 + mb(); 128 + }