xref: /openbmc/linux/arch/arm64/mm/cache.S (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
2f1a0c4aaSCatalin Marinas/*
3f1a0c4aaSCatalin Marinas * Cache maintenance
4f1a0c4aaSCatalin Marinas *
5f1a0c4aaSCatalin Marinas * Copyright (C) 2001 Deep Blue Solutions Ltd.
6f1a0c4aaSCatalin Marinas * Copyright (C) 2012 ARM Ltd.
7f1a0c4aaSCatalin Marinas */
8f1a0c4aaSCatalin Marinas
9a2d25a53SVladimir Murzin#include <linux/errno.h>
10f1a0c4aaSCatalin Marinas#include <linux/linkage.h>
11f1a0c4aaSCatalin Marinas#include <linux/init.h>
12f1a0c4aaSCatalin Marinas#include <asm/assembler.h>
13301bcfacSAndre Przywara#include <asm/cpufeature.h>
148d883b23SMarc Zyngier#include <asm/alternative.h>
15b4b8664dSAl Viro#include <asm/asm-uaccess.h>
16f1a0c4aaSCatalin Marinas
17f1a0c4aaSCatalin Marinas/*
18fade9c2cSFuad Tabba *	caches_clean_inval_pou_macro(start,end) [fixup]
19116b7f55SFuad Tabba *
20116b7f55SFuad Tabba *	Ensure that the I and D caches are coherent within specified region.
21116b7f55SFuad Tabba *	This is typically used when code has been written to a memory region,
22116b7f55SFuad Tabba *	and will be executed.
23116b7f55SFuad Tabba *
24116b7f55SFuad Tabba *	- start   - virtual start address of region
25116b7f55SFuad Tabba *	- end     - virtual end address of region
26116b7f55SFuad Tabba *	- fixup   - optional label to branch to on user fault
27116b7f55SFuad Tabba */
28fade9c2cSFuad Tabba.macro	caches_clean_inval_pou_macro, fixup
29116b7f55SFuad Tabbaalternative_if ARM64_HAS_CACHE_IDC
30116b7f55SFuad Tabba	dsb     ishst
31116b7f55SFuad Tabba	b       .Ldc_skip_\@
32116b7f55SFuad Tabbaalternative_else_nop_endif
33116b7f55SFuad Tabba	mov     x2, x0
34163d3f80SFuad Tabba	mov     x3, x1
35116b7f55SFuad Tabba	dcache_by_line_op cvau, ish, x2, x3, x4, x5, \fixup
36116b7f55SFuad Tabba.Ldc_skip_\@:
37116b7f55SFuad Tabbaalternative_if ARM64_HAS_CACHE_DIC
38116b7f55SFuad Tabba	isb
39116b7f55SFuad Tabba	b	.Lic_skip_\@
40116b7f55SFuad Tabbaalternative_else_nop_endif
41116b7f55SFuad Tabba	invalidate_icache_by_line x0, x1, x2, x3, \fixup
42116b7f55SFuad Tabba.Lic_skip_\@:
43116b7f55SFuad Tabba.endm
44116b7f55SFuad Tabba
45116b7f55SFuad Tabba/*
46fade9c2cSFuad Tabba *	caches_clean_inval_pou(start,end)
47f1a0c4aaSCatalin Marinas *
48f1a0c4aaSCatalin Marinas *	Ensure that the I and D caches are coherent within specified region.
49f1a0c4aaSCatalin Marinas *	This is typically used when code has been written to a memory region,
50f1a0c4aaSCatalin Marinas *	and will be executed.
51f1a0c4aaSCatalin Marinas *
52f1a0c4aaSCatalin Marinas *	- start   - virtual start address of region
53f1a0c4aaSCatalin Marinas *	- end     - virtual end address of region
54f1a0c4aaSCatalin Marinas */
55fade9c2cSFuad TabbaSYM_FUNC_START(caches_clean_inval_pou)
56fade9c2cSFuad Tabba	caches_clean_inval_pou_macro
57116b7f55SFuad Tabba	ret
58fade9c2cSFuad TabbaSYM_FUNC_END(caches_clean_inval_pou)
59*61786170SArd BiesheuvelSYM_FUNC_ALIAS(__pi_caches_clean_inval_pou, caches_clean_inval_pou)
60f1a0c4aaSCatalin Marinas
61f1a0c4aaSCatalin Marinas/*
62fade9c2cSFuad Tabba *	caches_clean_inval_user_pou(start,end)
63f1a0c4aaSCatalin Marinas *
64f1a0c4aaSCatalin Marinas *	Ensure that the I and D caches are coherent within specified region.
65f1a0c4aaSCatalin Marinas *	This is typically used when code has been written to a memory region,
66f1a0c4aaSCatalin Marinas *	and will be executed.
67f1a0c4aaSCatalin Marinas *
68f1a0c4aaSCatalin Marinas *	- start   - virtual start address of region
69f1a0c4aaSCatalin Marinas *	- end     - virtual end address of region
70f1a0c4aaSCatalin Marinas */
71fade9c2cSFuad TabbaSYM_FUNC_START(caches_clean_inval_user_pou)
72448fadc8SChristoffer Dall	uaccess_ttbr0_enable x2, x3, x4
73f1a0c4aaSCatalin Marinas
74fade9c2cSFuad Tabba	caches_clean_inval_pou_macro 2f
75116b7f55SFuad Tabba	mov	x0, xzr
7639bc88e5SCatalin Marinas1:
770482b505SChristoffer Dall	uaccess_ttbr0_disable x1, x2
78a2d25a53SVladimir Murzin	ret
79116b7f55SFuad Tabba2:
80a2d25a53SVladimir Murzin	mov	x0, #-EFAULT
8139bc88e5SCatalin Marinas	b	1b
82fade9c2cSFuad TabbaSYM_FUNC_END(caches_clean_inval_user_pou)
83f1a0c4aaSCatalin Marinas
84f1a0c4aaSCatalin Marinas/*
85fade9c2cSFuad Tabba *	icache_inval_pou(start,end)
864fee9473SMarc Zyngier *
874fee9473SMarc Zyngier *	Ensure that the I cache is invalid within specified region.
884fee9473SMarc Zyngier *
894fee9473SMarc Zyngier *	- start   - virtual start address of region
904fee9473SMarc Zyngier *	- end     - virtual end address of region
914fee9473SMarc Zyngier */
92fade9c2cSFuad TabbaSYM_FUNC_START(icache_inval_pou)
936ae4b6e0SShanker Donthinenialternative_if ARM64_HAS_CACHE_DIC
946ae4b6e0SShanker Donthineni	isb
956ae4b6e0SShanker Donthineni	ret
966ae4b6e0SShanker Donthinenialternative_else_nop_endif
976ae4b6e0SShanker Donthineni
987908072dSFuad Tabba	invalidate_icache_by_line x0, x1, x2, x3
994fee9473SMarc Zyngier	ret
100fade9c2cSFuad TabbaSYM_FUNC_END(icache_inval_pou)
1014fee9473SMarc Zyngier
1024fee9473SMarc Zyngier/*
103fade9c2cSFuad Tabba *	dcache_clean_inval_poc(start, end)
104f1a0c4aaSCatalin Marinas *
105814b1860SFuad Tabba *	Ensure that any D-cache lines for the interval [start, end)
1060a28714cSAshok Kumar *	are cleaned and invalidated to the PoC.
107f1a0c4aaSCatalin Marinas *
108814b1860SFuad Tabba *	- start   - virtual start address of region
109814b1860SFuad Tabba *	- end     - virtual end address of region
110f1a0c4aaSCatalin Marinas */
1110f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_clean_inval_poc)
1120a28714cSAshok Kumar	dcache_by_line_op civac, sy, x0, x1, x2, x3
113f1a0c4aaSCatalin Marinas	ret
1140f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_clean_inval_poc)
1150f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_clean_inval_poc, __pi_dcache_clean_inval_poc)
1167363590dSCatalin Marinas
1177363590dSCatalin Marinas/*
118fade9c2cSFuad Tabba *	dcache_clean_pou(start, end)
1190a28714cSAshok Kumar *
120406d7d4eSFuad Tabba * 	Ensure that any D-cache lines for the interval [start, end)
1210a28714cSAshok Kumar * 	are cleaned to the PoU.
1220a28714cSAshok Kumar *
123406d7d4eSFuad Tabba *	- start   - virtual start address of region
124406d7d4eSFuad Tabba *	- end     - virtual end address of region
1250a28714cSAshok Kumar */
126fade9c2cSFuad TabbaSYM_FUNC_START(dcache_clean_pou)
1276ae4b6e0SShanker Donthinenialternative_if ARM64_HAS_CACHE_IDC
1286ae4b6e0SShanker Donthineni	dsb	ishst
1296ae4b6e0SShanker Donthineni	ret
1306ae4b6e0SShanker Donthinenialternative_else_nop_endif
1310a28714cSAshok Kumar	dcache_by_line_op cvau, ish, x0, x1, x2, x3
1320a28714cSAshok Kumar	ret
133fade9c2cSFuad TabbaSYM_FUNC_END(dcache_clean_pou)
1340a28714cSAshok Kumar
1350a28714cSAshok Kumar/*
136fade9c2cSFuad Tabba *	dcache_inval_poc(start, end)
137d46befefSRobin Murphy *
138e3974adbSFuad Tabba * 	Ensure that any D-cache lines for the interval [start, end)
139d46befefSRobin Murphy * 	are invalidated. Any partial lines at the ends of the interval are
140d46befefSRobin Murphy *	also cleaned to PoC to prevent data loss.
141d46befefSRobin Murphy *
142e3974adbSFuad Tabba *	- start   - kernel start address of region
143e3974adbSFuad Tabba *	- end     - kernel end address of region
144d46befefSRobin Murphy */
1450f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_inval_poc)
1467363590dSCatalin Marinas	dcache_line_size x2, x3
1477363590dSCatalin Marinas	sub	x3, x2, #1
148ebf81a93SCatalin Marinas	tst	x1, x3				// end cache line aligned?
1497363590dSCatalin Marinas	bic	x1, x1, x3
150ebf81a93SCatalin Marinas	b.eq	1f
151ebf81a93SCatalin Marinas	dc	civac, x1			// clean & invalidate D / U line
152ebf81a93SCatalin Marinas1:	tst	x0, x3				// start cache line aligned?
153ebf81a93SCatalin Marinas	bic	x0, x0, x3
154ebf81a93SCatalin Marinas	b.eq	2f
155ebf81a93SCatalin Marinas	dc	civac, x0			// clean & invalidate D / U line
156ebf81a93SCatalin Marinas	b	3f
157ebf81a93SCatalin Marinas2:	dc	ivac, x0			// invalidate D / U line
158ebf81a93SCatalin Marinas3:	add	x0, x0, x2
1597363590dSCatalin Marinas	cmp	x0, x1
160ebf81a93SCatalin Marinas	b.lo	2b
1617363590dSCatalin Marinas	dsb	sy
1627363590dSCatalin Marinas	ret
1630f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_inval_poc)
1640f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_inval_poc, __pi_dcache_inval_poc)
1657363590dSCatalin Marinas
1667363590dSCatalin Marinas/*
167fade9c2cSFuad Tabba *	dcache_clean_poc(start, end)
168d34fdb70SKwangwoo Lee *
1691f42faf1SFuad Tabba * 	Ensure that any D-cache lines for the interval [start, end)
170d34fdb70SKwangwoo Lee * 	are cleaned to the PoC.
171d34fdb70SKwangwoo Lee *
1721f42faf1SFuad Tabba *	- start   - virtual start address of region
1731f42faf1SFuad Tabba *	- end     - virtual end address of region
1747363590dSCatalin Marinas */
1750f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_clean_poc)
176d34fdb70SKwangwoo Lee	dcache_by_line_op cvac, sy, x0, x1, x2, x3
1777363590dSCatalin Marinas	ret
1780f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_clean_poc)
1790f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_clean_poc, __pi_dcache_clean_poc)
180d34fdb70SKwangwoo Lee
181d34fdb70SKwangwoo Lee/*
182fade9c2cSFuad Tabba *	dcache_clean_pop(start, end)
183d50e071fSRobin Murphy *
184f749448eSFuad Tabba * 	Ensure that any D-cache lines for the interval [start, end)
185d50e071fSRobin Murphy * 	are cleaned to the PoP.
186d50e071fSRobin Murphy *
187f749448eSFuad Tabba *	- start   - virtual start address of region
188f749448eSFuad Tabba *	- end     - virtual end address of region
189d50e071fSRobin Murphy */
1900f61f6beSMark RutlandSYM_FUNC_START(__pi_dcache_clean_pop)
19133309ecdSWill Deacon	alternative_if_not ARM64_HAS_DCPOP
192fade9c2cSFuad Tabba	b	dcache_clean_poc
19333309ecdSWill Deacon	alternative_else_nop_endif
194d50e071fSRobin Murphy	dcache_by_line_op cvap, sy, x0, x1, x2, x3
195d50e071fSRobin Murphy	ret
1960f61f6beSMark RutlandSYM_FUNC_END(__pi_dcache_clean_pop)
1970f61f6beSMark RutlandSYM_FUNC_ALIAS(dcache_clean_pop, __pi_dcache_clean_pop)
198