|
|
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 |
|