Blame SOURCES/kexec-tools-2.0.8-arm64-Add-enable-disable-d-cache-support-for-purgato.patch

a6d77e
From 8b40614f4c1925fe94f274dfc69d1a63537fe399 Mon Sep 17 00:00:00 2001
a6d77e
Message-Id: <8b40614f4c1925fe94f274dfc69d1a63537fe399.1430751022.git.panand@redhat.com>
a6d77e
From: Pratyush Anand <panand@redhat.com>
a6d77e
Date: Mon, 4 May 2015 17:43:25 +0530
a6d77e
Subject: [PATCH 1/3] arm64: Add enable/disable d-cache support for purgatory
a6d77e
a6d77e
This patch adds support to enable/disable d-cache, which can be used for
a6d77e
faster purgatory sha256 verification.
a6d77e
a6d77e
Signed-off-by: Pratyush Anand <panand@redhat.com>
a6d77e
---
a6d77e
 purgatory/arch/arm64/Makefile |   1 +
a6d77e
 purgatory/arch/arm64/cache.S  | 222 ++++++++++++++++++++++++++++++++++++++++++
a6d77e
 purgatory/arch/arm64/cache.h  |  42 ++++++++
a6d77e
 3 files changed, 265 insertions(+)
a6d77e
 create mode 100644 purgatory/arch/arm64/cache.S
a6d77e
 create mode 100644 purgatory/arch/arm64/cache.h
a6d77e
a6d77e
diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile
a6d77e
index 5d35161fc5f4..04fef16476fb 100644
a6d77e
--- a/purgatory/arch/arm64/Makefile
a6d77e
+++ b/purgatory/arch/arm64/Makefile
a6d77e
@@ -12,6 +12,7 @@ arm64_PURGATORY_EXTRA_CFLAGS = \
a6d77e
 
a6d77e
 arm64_PURGATORY_SRCS += \
a6d77e
 	purgatory/arch/arm64/entry.S \
a6d77e
+	purgatory/arch/arm64/cache.S \
a6d77e
 	purgatory/arch/arm64/purgatory-arm64.c
a6d77e
 
a6d77e
 dist += \
a6d77e
diff --git a/purgatory/arch/arm64/cache.S b/purgatory/arch/arm64/cache.S
a6d77e
new file mode 100644
a6d77e
index 000000000000..6bbdeacdab47
a6d77e
--- /dev/null
a6d77e
+++ b/purgatory/arch/arm64/cache.S
a6d77e
@@ -0,0 +1,222 @@
a6d77e
+/*
a6d77e
+ * Cache maintenance
a6d77e
+ * Some of the routine has been copied from Linux Kernel, therefore
a6d77e
+ * copying the license as well.
a6d77e
+ *
a6d77e
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
a6d77e
+ * Copyright (C) 2012 ARM Ltd.
a6d77e
+ * Copyright (C) 2015 Pratyush Anand <panand@redhat.com>
a6d77e
+ *
a6d77e
+ * This program is free software; you can redistribute it and/or modify
a6d77e
+ * it under the terms of the GNU General Public License version 2 as
a6d77e
+ * published by the Free Software Foundation.
a6d77e
+ *
a6d77e
+ * This program is distributed in the hope that it will be useful,
a6d77e
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
a6d77e
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a6d77e
+ * GNU General Public License for more details.
a6d77e
+ *
a6d77e
+ * You should have received a copy of the GNU General Public License
a6d77e
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
a6d77e
+ */
a6d77e
+
a6d77e
+#include "cache.h"
a6d77e
+
a6d77e
+/*
a6d77e
+ * dcache_line_size - get the minimum D-cache line size from the CTR register.
a6d77e
+ */
a6d77e
+	.macro	dcache_line_size, reg, tmp
a6d77e
+	mrs	\tmp, ctr_el0			// read CTR
a6d77e
+	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
a6d77e
+	mov	\reg, #4			// bytes per word
a6d77e
+	lsl	\reg, \reg, \tmp		// actual cache line size
a6d77e
+	.endm
a6d77e
+
a6d77e
+/*
a6d77e
+ *	__inval_cache_range(start, end)
a6d77e
+ *	- start	- start address of region
a6d77e
+ *	- end	- end address of region
a6d77e
+ */
a6d77e
+__inval_cache_range:
a6d77e
+	dcache_line_size x2, x3
a6d77e
+	sub	x3, x2, #1
a6d77e
+	tst	x1, x3				// end cache line aligned?
a6d77e
+	bic	x1, x1, x3
a6d77e
+	b.eq	1f
a6d77e
+	dc	civac, x1			// clean & invalidate D / U line
a6d77e
+1:	tst	x0, x3				// start cache line aligned?
a6d77e
+	bic	x0, x0, x3
a6d77e
+	b.eq	2f
a6d77e
+	dc	civac, x0			// clean & invalidate D / U line
a6d77e
+	b	3f
a6d77e
+2:	dc	ivac, x0			// invalidate D / U line
a6d77e
+3:	add	x0, x0, x2
a6d77e
+	cmp	x0, x1
a6d77e
+	b.lo	2b
a6d77e
+	dsb	sy
a6d77e
+	ret
a6d77e
+/*
a6d77e
+ *	__flush_dcache_range(start, end)
a6d77e
+ *	- start	- start address of region
a6d77e
+ *	- end	- end address of region
a6d77e
+ *
a6d77e
+ */
a6d77e
+__flush_dcache_range:
a6d77e
+	dcache_line_size x2, x3
a6d77e
+	sub	x3, x2, #1
a6d77e
+	bic	x0, x0, x3
a6d77e
+1:	dc	civac, x0			// clean & invalidate D line / unified line
a6d77e
+	add	x0, x0, x2
a6d77e
+	cmp	x0, x1
a6d77e
+	b.lo	1b
a6d77e
+	dsb	sy
a6d77e
+	ret
a6d77e
+
a6d77e
+/*
a6d77e
+ *	enable_dcache(start, end, page_table)
a6d77e
+ *	- start	- start address of ram
a6d77e
+ *	- end	- end address of ram
a6d77e
+ *	- page_table - base of page table
a6d77e
+ */
a6d77e
+.globl enable_dcache
a6d77e
+enable_dcache:
a6d77e
+	stp	x6, x7, [sp,#-16]!
a6d77e
+	stp	x16, x17, [sp,#-16]!
a6d77e
+	stp	x18, x19, [sp,#-16]!
a6d77e
+
a6d77e
+	/* save args */
a6d77e
+	mov x16, x0	/* first segment start */
a6d77e
+	mov x17, x1	/* last segment end */
a6d77e
+	mov x18, x2 	/* page table */
a6d77e
+	mov x19, x30	/* save ret addr */
a6d77e
+
a6d77e
+	/*
a6d77e
+	 * Invalidate the page tables to avoid potential
a6d77e
+	 * dirty cache lines being evicted.
a6d77e
+	 */
a6d77e
+	mov x0, x18
a6d77e
+	add x1, x0, #PAGE_TABLE_SIZE
a6d77e
+	bl __inval_cache_range
a6d77e
+
a6d77e
+	/*
a6d77e
+	 * Clear the page tables.
a6d77e
+	 */
a6d77e
+	mov x0, x18
a6d77e
+	add x1, x0, #PAGE_TABLE_SIZE
a6d77e
+1:	stp	xzr, xzr, [x0], #16
a6d77e
+	stp	xzr, xzr, [x0], #16
a6d77e
+	stp	xzr, xzr, [x0], #16
a6d77e
+	stp	xzr, xzr, [x0], #16
a6d77e
+	cmp	x0, x1
a6d77e
+	b.lo	1b
a6d77e
+
a6d77e
+	/*
a6d77e
+	 * Create the identity mapping.
a6d77e
+	 */
a6d77e
+	ldr	x6, =SECTION_SHIFT
a6d77e
+	ldr	x7, =MM_MMUFLAGS
a6d77e
+	lsr	x0, x16, x6	//first index
a6d77e
+	lsr	x1, x17, x6	//last index
a6d77e
+
a6d77e
+next_sect:
a6d77e
+	lsl	x2, x0, x6	//section
a6d77e
+	orr	x2, x2, x7
a6d77e
+	str	x2, [x18, x0, lsl #3]
a6d77e
+	add	x0, x0, #1
a6d77e
+	cmp	x0, x1
a6d77e
+	b.ls	next_sect
a6d77e
+
a6d77e
+	/*
a6d77e
+	 * Since the page tables have been populated with non-cacheable
a6d77e
+	 * accesses (MMU disabled), invalidate the idmap page
a6d77e
+	 * tables again to remove any speculatively loaded cache lines.
a6d77e
+	 */
a6d77e
+	mov x0, x18
a6d77e
+	add x1, x0, #PAGE_TABLE_SIZE
a6d77e
+	bl __inval_cache_range
a6d77e
+
a6d77e
+	mrs 	x0, CurrentEL
a6d77e
+	cmp	x0, #12	//EL3
a6d77e
+	b.eq	set_el3
a6d77e
+	cmp	x0, #8	//EL2
a6d77e
+	b.eq	set_el2
a6d77e
+	cmp	x0, #4	//EL1
a6d77e
+	b.eq	set_el1
a6d77e
+	b	done_enable
a6d77e
+
a6d77e
+set_el1:
a6d77e
+	msr	ttbr0_el1, x18
a6d77e
+	ldr	x0, =TCR_FLAGS
a6d77e
+	orr	x0, x0, #TCR_EL1_IPS_BITS
a6d77e
+	msr	tcr_el1, x0
a6d77e
+	ldr	x0, =MEMORY_ATTRIBUTES
a6d77e
+	msr	mair_el1, x0
a6d77e
+	mrs	x0, sctlr_el1
a6d77e
+	orr	x0, x0, #CR_M
a6d77e
+	orr	x0, x0, #CR_C
a6d77e
+	msr	sctlr_el1, x0
a6d77e
+	b	done_enable
a6d77e
+set_el2:
a6d77e
+	msr	ttbr0_el2, x18
a6d77e
+	ldr	x0, =TCR_FLAGS
a6d77e
+	orr	x0, x0, #TCR_EL2_IPS_BITS
a6d77e
+	msr	tcr_el2, x0
a6d77e
+	ldr	x0, =MEMORY_ATTRIBUTES
a6d77e
+	msr	mair_el2, x0
a6d77e
+	mrs	x0, sctlr_el2
a6d77e
+	orr	x0, x0, #CR_M
a6d77e
+	orr	x0, x0, #CR_C
a6d77e
+	msr	sctlr_el2, x0
a6d77e
+	b	done_enable
a6d77e
+set_el3:
a6d77e
+	msr	ttbr0_el3, x18
a6d77e
+	ldr	x0, =TCR_FLAGS
a6d77e
+	orr	x0, x0, #TCR_EL3_IPS_BITS
a6d77e
+	msr	tcr_el3, x0
a6d77e
+	ldr	x0, =MEMORY_ATTRIBUTES
a6d77e
+	msr	mair_el3, x0
a6d77e
+	mrs	x0, sctlr_el3
a6d77e
+	orr	x0, x0, #CR_M
a6d77e
+	orr	x0, x0, #CR_C
a6d77e
+	msr	sctlr_el3, x0
a6d77e
+done_enable:
a6d77e
+
a6d77e
+	mov	x30, x19
a6d77e
+	ldp	x18, x19, [sp],#16
a6d77e
+	ldp	x16, x17, [sp],#16
a6d77e
+	ldp	x6, x7, [sp],#16
a6d77e
+
a6d77e
+	ret
a6d77e
+
a6d77e
+.globl disable_dcache
a6d77e
+disable_dcache:
a6d77e
+	stp	x5, x30, [sp,#-16]!
a6d77e
+	mrs 	x5, CurrentEL
a6d77e
+	cmp	x5, #12	//EL3
a6d77e
+	b.eq	disable_el3
a6d77e
+	cmp	x5, #8	//EL2
a6d77e
+	b.eq	disable_el2
a6d77e
+	cmp	x5, #4	//EL1
a6d77e
+	b.eq	disable_el1
a6d77e
+	b	done_disable
a6d77e
+disable_el3:
a6d77e
+	mrs	x5, sctlr_el3
a6d77e
+	bic	x5, x2, #CR_M
a6d77e
+	bic	x5, x2, #CR_C
a6d77e
+	msr	sctlr_el3, x5
a6d77e
+	b	done_disable
a6d77e
+disable_el2:
a6d77e
+	mrs	x5, sctlr_el2
a6d77e
+	bic	x5, x2, #CR_M
a6d77e
+	bic	x5, x2, #CR_C
a6d77e
+	msr	sctlr_el2, x5
a6d77e
+	b	done_disable
a6d77e
+disable_el1:
a6d77e
+	mrs	x5, sctlr_el1
a6d77e
+	bic	x5, x2, #CR_M
a6d77e
+	bic	x5, x2, #CR_C
a6d77e
+	msr	sctlr_el1, x5
a6d77e
+done_disable:
a6d77e
+	bl __flush_dcache_range
a6d77e
+	ldp	x5, x30, [sp],#16
a6d77e
+	ret
a6d77e
diff --git a/purgatory/arch/arm64/cache.h b/purgatory/arch/arm64/cache.h
a6d77e
new file mode 100644
a6d77e
index 000000000000..3ca1d7f9a5ca
a6d77e
--- /dev/null
a6d77e
+++ b/purgatory/arch/arm64/cache.h
a6d77e
@@ -0,0 +1,42 @@
a6d77e
+#ifndef	__CACHE_H__
a6d77e
+#define __CACHE_H__
a6d77e
+
a6d77e
+#define VA_BITS			42
a6d77e
+#define SECTION_SHIFT		29
a6d77e
+#define PAGE_TABLE_SIZE		(1 << (VA_BITS - SECTION_SHIFT + 3))
a6d77e
+
a6d77e
+#define TCR_TG0_64K 		(1 << 14)
a6d77e
+#define TCR_SHARED_NON		(0 << 12)
a6d77e
+#define TCR_ORGN_WBWA		(1 << 10)
a6d77e
+#define TCR_IRGN_WBWA		(1 << 8)
a6d77e
+#define TCR_T0SZ(x)		((64 - (x)) << 0)
a6d77e
+#define TCR_EL1_IPS_BITS	(3 << 32) /* 42 bits physical address */
a6d77e
+#define TCR_EL2_IPS_BITS	(3 << 16) /* 42 bits physical address */
a6d77e
+#define TCR_EL3_IPS_BITS	(3 << 16) /* 42 bits physical address */
a6d77e
+
a6d77e
+#define TCR_FLAGS (TCR_TG0_64K | TCR_SHARED_NON | TCR_ORGN_WBWA | \
a6d77e
+		TCR_IRGN_WBWA | TCR_T0SZ(VA_BITS))
a6d77e
+
a6d77e
+#define MT_DEVICE_NGNRNE	0
a6d77e
+#define MT_DEVICE_NGNRE		1
a6d77e
+#define MT_DEVICE_GRE		2
a6d77e
+#define MT_NORMAL_NC		3
a6d77e
+#define MT_NORMAL		4
a6d77e
+
a6d77e
+#define MEMORY_ATTRIBUTES	((0x00 << (MT_DEVICE_NGNRNE*8)) | \
a6d77e
+				(0x04 << (MT_DEVICE_NGNRE*8)) | \
a6d77e
+				(0x0c << (MT_DEVICE_GRE*8)) | \
a6d77e
+				(0x44 << (MT_NORMAL_NC*8)) | \
a6d77e
+				(0xff << (MT_NORMAL*8)))
a6d77e
+
a6d77e
+#define CR_M			(1 << 0)	/* MMU enable */
a6d77e
+#define CR_C			(1 << 2)	/* Dcache enable */
a6d77e
+
a6d77e
+
a6d77e
+#define PMD_TYPE_SECT		(1 << 0)
a6d77e
+#define PMD_SECT_AF		(1 << 10)
a6d77e
+#define PMD_ATTRINDX(t)		((t) << 2)
a6d77e
+#define PMD_FLAGS	(PMD_TYPE_SECT | PMD_SECT_AF)
a6d77e
+#define MM_MMUFLAGS	PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS
a6d77e
+
a6d77e
+#endif
a6d77e
-- 
a6d77e
2.1.0
a6d77e