[coreboot-gerrit] New patch to review for coreboot: fdc44f5 armv7: import new cache maintenance API from coreboot

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Fri Mar 29 22:11:01 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2974

-gerrit

commit fdc44f536b9c49bd0d937202023d9a6920390d5e
Author: David Hendricks <dhendrix at chromium.org>
Date:   Thu Mar 14 19:06:11 2013 -0700

    armv7: import new cache maintenance API from coreboot
    
    This imports the new cache maintenance API from coreboot at
    commit bba8090. This is a BSD-licensed implementation which
    exposes cache maintenance opertaions necessary for payloads
    for things such as DMA transfers.
    
    Change-Id: I554676db89517bebc6edae4f7ab7e5882e6f986d
    Signed-off-by: David Hendricks <dhendrix at chromium.org>
---
 payloads/libpayload/arch/armv7/Makefile.inc    |   2 +-
 payloads/libpayload/arch/armv7/cache.c         | 178 +++++++++++++++++++
 payloads/libpayload/include/armv7/arch/cache.h | 231 +++++++++++++++++++++++++
 3 files changed, 410 insertions(+), 1 deletion(-)

diff --git a/payloads/libpayload/arch/armv7/Makefile.inc b/payloads/libpayload/arch/armv7/Makefile.inc
index da0030e..9c7fe83 100644
--- a/payloads/libpayload/arch/armv7/Makefile.inc
+++ b/payloads/libpayload/arch/armv7/Makefile.inc
@@ -33,4 +33,4 @@ libc-y += timer.c coreboot.c util.S
 libc-y += virtual.c
 libc-y += memcpy.S memset.S
 libc-y += exception_asm.S exception.c
-
+libc-y += cache.c
diff --git a/payloads/libpayload/arch/armv7/cache.c b/payloads/libpayload/arch/armv7/cache.c
new file mode 100644
index 0000000..60d5f74
--- /dev/null
+++ b/payloads/libpayload/arch/armv7/cache.c
@@ -0,0 +1,178 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * cache.c: Low-level cache operations for ARMv7
+ */
+
+#include <inttypes.h>
+
+#include <arch/cache.h>
+
+#define bitmask(high, low) ((1UL << (high)) + \
+			((1UL << (high)) - 1) - ((1UL << (low)) - 1))
+
+/* Basic log2() implementation. Note: log2(0) is 0 for our purposes. */
+/* FIXME: src/include/lib.h is difficult to work with due to romcc */
+static unsigned long log2(unsigned long u)
+{
+	int i = 0;
+
+	while (u >>= 1)
+		i++;
+
+	return i;
+}
+
+void tlb_invalidate_all(void)
+{
+	/*
+	 * FIXME: ARMv7 Architecture Ref. Manual claims that the distinction
+	 * instruction vs. data TLBs is deprecated in ARMv7. But that doesn't
+	 * really seem true for Cortex-A15?
+	 */
+	tlbiall();
+	dtlbiall();
+	itlbiall();
+	isb();
+	dsb();
+}
+
+void icache_invalidate_all(void)
+{
+	/* icache can be entirely invalidated with one operation.
+	 * Note: If branch predictors are architecturally-visible, ICIALLU
+	 * also performs a BPIALL operation (B2-1283 in arch manual)
+	 */
+	iciallu();
+	isb();
+}
+
+enum dcache_op {
+	OP_DCCISW,
+	OP_DCISW
+};
+
+/* do a dcache operation on entire cache by set/way */
+static void dcache_op_set_way(enum dcache_op op)
+{
+	uint32_t ccsidr;
+	unsigned int associativity, num_sets, linesize_bytes;
+	unsigned int set, way;
+	unsigned int level;
+
+	level = (read_csselr() >> 1) & 0x7;
+
+	/*
+	 * dcache must be invalidated by set/way for portability since virtual
+	 * memory mapping is system-defined. The number of sets and
+	 * associativity is given by CCSIDR. We'll use DCISW to invalidate the
+	 * dcache.
+	 */
+	ccsidr = read_ccsidr();
+
+	/* FIXME: rounding up required here? */
+	num_sets = ((ccsidr & bitmask(27, 13)) >> 13) + 1;
+	associativity = ((ccsidr & bitmask(12, 3)) >> 3) + 1;
+	/* FIXME: do we need to use CTR.DminLine here? */
+	linesize_bytes = (1 << ((ccsidr & 0x7) + 2)) * 4;
+
+	/*
+	 * Set/way operations require an interesting bit packing. See section
+	 * B4-35 in the ARMv7 Architecture Reference Manual:
+	 *
+	 * A: Log2(associativity)
+	 * B: L+S
+	 * L: Log2(linesize)
+	 * S: Log2(num_sets)
+	 *
+	 * The bits are packed as follows:
+	 *  31  31-A        B B-1    L L-1   4 3   1 0
+	 * |---|-------------|--------|-------|-----|-|
+	 * |Way|    zeros    |   Set  | zeros |level|0|
+	 * |---|-------------|--------|-------|-----|-|
+	 */
+	for (way = 0; way < associativity; way++) {
+		for (set = 0; set < num_sets; set++) {
+			uint32_t val = 0;
+			val |= way << (32 - log2(associativity));
+			val |= set << log2(linesize_bytes);
+			val |= level << 1;
+			switch(op) {
+			case OP_DCCISW:
+				dccisw(val);
+				break;
+			case OP_DCISW:
+				dcisw(val);
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	dsb();
+}
+
+void dcache_clean_invalidate_all(void)
+{
+	dcache_op_set_way(OP_DCCISW);
+}
+
+void dcache_invalidate_all(void)
+{
+	dcache_op_set_way(OP_DCISW);
+}
+
+static unsigned int line_bytes(void)
+{
+	uint32_t ccsidr;
+	unsigned int size;
+
+	ccsidr = read_ccsidr();
+	/* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */
+	size = 1 << ((ccsidr & 0x7) + 2);	/* words per line */
+	size *= sizeof(unsigned int);		/* bytes per line */
+
+	return size;
+}
+
+void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len)
+{
+	unsigned long line, i;
+
+	line = line_bytes();
+	for (i = addr & ~(line - 1); i < addr + len - 1; i += line)
+		dccimvac(addr);
+}
+
+/* FIXME: wrapper around imported mmu_setup() for now */
+extern void mmu_setup(unsigned long start, unsigned long size);
+void mmu_setup_by_mva(unsigned long start, unsigned long size)
+{
+	mmu_setup(start, size);
+}
diff --git a/payloads/libpayload/include/armv7/arch/cache.h b/payloads/libpayload/include/armv7/arch/cache.h
new file mode 100644
index 0000000..5125b8c
--- /dev/null
+++ b/payloads/libpayload/include/armv7/arch/cache.h
@@ -0,0 +1,231 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ARMV7_CACHE_H
+#define ARMV7_CACHE_H
+
+/* SCTLR bits */
+#define SCTLR_M		(1 << 0)	/* MMU enable			*/
+#define SCTLR_A		(1 << 1)	/* Alignment check enable	*/
+#define SCTLR_C		(1 << 2)	/* Data/unified cache enable	*/
+/* Bits 4:3 are reserved */
+#define SCTLR_CP15BEN	(1 << 5)	/* CP15 barrier enable		*/
+/* Bit 6 is reserved */
+#define SCTLR_B		(1 << 7)	/* Endianness			*/
+/* Bits 9:8 */
+#define SCTLR_SW	(1 << 10)	/* SWP and SWPB enable		*/
+#define SCTLR_Z		(1 << 11)	/* Branch prediction enable	*/
+#define SCTLR_I		(1 << 12)	/* Instruction cache enable	*/
+#define SCTLR_V		(1 << 13)	/* Low/high exception vectors 	*/
+#define SCTLR_RR  	(1 << 14)	/* Round Robin select		*/
+/* Bits 16:15 are reserved */
+#define SCTLR_HA	(1 << 17)	/* Hardware Access flag enable	*/
+/* Bit 18 is reserved */
+/* Bits 20:19 reserved virtualization not supported */
+#define SCTLR_WXN	(1 << 19)	/* Write permission implies XN	*/
+#define SCTLR_UWXN	(1 << 20)	/* Unprivileged write permission
+					   implies PL1 XN		*/
+#define SCTLR_FI	(1 << 21)	/* Fast interrupt config enable	*/
+#define SCTLR_U		(1 << 22)	/* Unaligned access behavior	*/
+#define SCTLR_VE	(1 << 24)	/* Interrupt vectors enable	*/
+#define SCTLR_EE	(1 << 25)	/* Exception endianness		*/
+/* Bit 26 is reserved */
+#define SCTLR_NMFI	(1 << 27)	/* Non-maskable FIQ support	*/
+#define SCTLR_TRE	(1 << 28)	/* TEX remap enable		*/
+#define SCTLR_AFE	(1 << 29)	/* Access flag enable		*/
+#define SCTLR_TE	(1 << 30)	/* Thumb exception enable	*/
+/* Bit 31 is reserved */
+
+/*
+ * Sync primitives
+ */
+
+/* data memory barrier */
+static inline void dmb(void)
+{
+	asm volatile ("dmb" : : : "memory");
+}
+
+/* data sync barrier */
+static inline void dsb(void)
+{
+	asm volatile ("dsb" : : : "memory");
+}
+
+/* instruction sync barrier */
+static inline void isb(void)
+{
+	asm volatile ("isb" : : : "memory");
+}
+
+/*
+ * Low-level TLB maintenance operations
+ */
+
+/* invalidate entire data TLB */
+static inline void dtlbiall(void)
+{
+	asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0));
+}
+
+/* invalidate entire instruction TLB */
+static inline void itlbiall(void)
+{
+	asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0));
+}
+
+/* invalidate entire unified TLB */
+static inline void tlbiall(void)
+{
+	asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0));
+}
+
+/*
+ * Low-level cache maintenance operations
+ */
+
+/* branch predictor invalidate all */
+static inline void bpiall(void)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0));
+}
+
+/* data cache clean and invalidate by MVA to PoC */
+static inline void dccimvac(unsigned long mva)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva));
+}
+
+/* data cache invalidate by set/way */
+static inline void dccisw(uint32_t val)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c14, 2" : : "r" (val));
+}
+
+/* data cache invalidate by set/way */
+static inline void dcisw(uint32_t val)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c6, 2" : : "r" (val));
+}
+
+/* data cache clean by MVA to PoC */
+static inline void dccmvac(unsigned long mva)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c10, 1" : : "r" (mva));
+}
+
+/* data cache invalidate by MVA to PoC */
+static inline void dcimvac(unsigned long mva)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (mva));
+}
+
+/* instruction cache invalidate all by PoU */
+static inline void iciallu(void)
+{
+	asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+}
+
+/*
+ * Cache co-processor (CP15) access functions
+ */
+
+/* read cache level ID register (CLIDR) */
+static inline uint32_t read_clidr(void)
+{
+	uint32_t val = 0;
+	asm volatile ("mrc p15, 1, %0, c0, c0, 1" : "=r" (val));
+	return val;
+}
+
+/* read cache size ID register register (CCSIDR) */
+static inline uint32_t read_ccsidr(void)
+{
+	uint32_t val = 0;
+	asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (val));
+	return val;
+}
+
+/* read cache size selection register (CSSELR) */
+static inline uint32_t read_csselr(void)
+{
+	uint32_t val = 0;
+	asm volatile ("mrc p15, 2, %0, c0, c0, 0" : "=r" (val));
+	return val;
+}
+
+/* write to cache size selection register (CSSELR) */
+static inline void write_csselr(uint32_t val)
+{
+	/*
+	 * Bits [3:1] - Cache level + 1 (0b000 = L1, 0b110 = L7, 0b111 is rsvd)
+	 * Bit 0 - 0 = data or unified cache, 1 = instruction cache
+	 */
+	asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (val));
+	isb();	/* ISB to sync the change to CCSIDR */
+}
+
+/* read system control register (SCTLR) */
+static inline unsigned int read_sctlr(void)
+{
+	unsigned int val;
+	asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (val) : : "cc");
+	return val;
+}
+
+/* write system control register (SCTLR) */
+static inline void write_sctlr(unsigned int val)
+{
+	asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r" (val) : "cc");
+	isb();
+}
+
+/*
+ * Cache maintenance API
+ */
+
+/* invalidate all TLBs */
+void tlb_invalidate_all(void);
+
+/* clean and invalidate entire dcache on current level (given by CCSELR) */
+void dcache_clean_invalidate_all(void);
+
+/* invalidate entire dcache on current level (given by CCSELR) */
+void dcache_invalidate_all(void);
+
+/* invalidate and clean dcache by machine virtual address to PoC */
+void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len);
+
+/* invalidate entire icache on current level (given by CSSELR) */
+void icache_invalidate_all(void);
+
+/* MMU setup by machine virtual address */
+void mmu_setup_by_mva(unsigned long start, unsigned long size);
+
+#endif /* ARMV7_CACHE_H */



More information about the coreboot-gerrit mailing list