Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/hexagon/mm/cache.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Cache management functions for Hexagon
4
*
5
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
6
*/
7
8
#include <linux/mm.h>
9
#include <asm/cacheflush.h>
10
#include <asm/hexagon_vm.h>
11
12
#define spanlines(start, end) \
13
(((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
14
15
void flush_dcache_range(unsigned long start, unsigned long end)
16
{
17
unsigned long lines = spanlines(start, end-1);
18
unsigned long i, flags;
19
20
start &= ~(LINESIZE - 1);
21
22
local_irq_save(flags);
23
24
for (i = 0; i < lines; i++) {
25
__asm__ __volatile__ (
26
" dccleaninva(%0); "
27
:
28
: "r" (start)
29
);
30
start += LINESIZE;
31
}
32
local_irq_restore(flags);
33
}
34
35
void flush_icache_range(unsigned long start, unsigned long end)
36
{
37
unsigned long lines = spanlines(start, end-1);
38
unsigned long i, flags;
39
40
start &= ~(LINESIZE - 1);
41
42
local_irq_save(flags);
43
44
for (i = 0; i < lines; i++) {
45
__asm__ __volatile__ (
46
" dccleana(%0); "
47
" icinva(%0); "
48
:
49
: "r" (start)
50
);
51
start += LINESIZE;
52
}
53
__asm__ __volatile__ (
54
"isync"
55
);
56
local_irq_restore(flags);
57
}
58
EXPORT_SYMBOL(flush_icache_range);
59
60
void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
61
{
62
unsigned long lines = spanlines(start, end-1);
63
unsigned long i, flags;
64
65
start &= ~(LINESIZE - 1);
66
67
local_irq_save(flags);
68
69
for (i = 0; i < lines; i++) {
70
__asm__ __volatile__ (
71
" dccleana(%0); "
72
:
73
: "r" (start)
74
);
75
start += LINESIZE;
76
}
77
local_irq_restore(flags);
78
}
79
80
void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
81
{
82
unsigned long lines = spanlines(start, end-1);
83
unsigned long i, flags;
84
85
start &= ~(LINESIZE - 1);
86
87
local_irq_save(flags);
88
89
for (i = 0; i < lines; i++) {
90
__asm__ __volatile__ (
91
" dcinva(%0); "
92
:
93
: "r" (start)
94
);
95
start += LINESIZE;
96
}
97
local_irq_restore(flags);
98
}
99
100
101
102
103
/*
104
* This is just really brutal and shouldn't be used anyways,
105
* especially on V2. Left here just in case.
106
*/
107
void flush_cache_all_hexagon(void)
108
{
109
unsigned long flags;
110
local_irq_save(flags);
111
__vmcache_ickill();
112
__vmcache_dckill();
113
__vmcache_l2kill();
114
local_irq_restore(flags);
115
mb();
116
}
117
118
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
119
unsigned long vaddr, void *dst, void *src, int len)
120
{
121
memcpy(dst, src, len);
122
if (vma->vm_flags & VM_EXEC) {
123
flush_icache_range((unsigned long) dst,
124
(unsigned long) dst + len);
125
}
126
}
127
128