David Hendricks (dhendrix@chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2877
-gerrit
commit 0790bd842dd46ed5305d11e3341537d95620e765 Author: David Hendricks dhendrix@chromium.org Date: Thu Mar 21 21:58:50 2013 -0700
armv7: add new dcache and MMU setup functions
** do not submit **
This is a work-in-progress patch.
This adds new MMU setup code which uses cbmem_add() to determine the translation table base address, which in turn helps our payload to avoid clobbering the page table.
Right now it dies when cbmem_toc is accessed in cbmem_reinit(). Sounds like I'm not setting up permissions correctly or something. Hmmmmm...
Change-Id: Iba5295a801e8058a3694e4ec5b94bbe9a69d3ee6 Signed-off-by: David Hendricks dhendrix@chromium.org --- src/Kconfig | 1 + src/arch/armv7/bootblock_simple.c | 6 +- src/arch/armv7/include/arch/cache.h | 32 ++++++++++ src/arch/armv7/lib/Makefile.inc | 1 + src/arch/armv7/lib/cache.c | 29 ++++++--- src/arch/armv7/lib/mmu.c | 119 +++++++++++++++++++++++++++++++++++ src/lib/Makefile.inc | 3 +- src/mainboard/google/snow/romstage.c | 10 ++- 8 files changed, 190 insertions(+), 11 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 18b5bad..f15c32d 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -225,6 +225,7 @@ config ARCH_X86 config ARCH_ARMV7 bool default n + select EARLY_CBMEM_INIT
# Warning: The file is included whether or not the if is here. # but the if controls how the evaluation occurs. diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c index ad25b41..0a5d6c3 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/armv7/bootblock_simple.c @@ -53,12 +53,14 @@ void main(void) armv7_invalidate_caches();
/* - * Re-enable caches and branch prediction. MMU will be set up later. + * Re-enable icache and branch prediction. Dcache and MMU will be + * set up in romstage along with DRAM. + * * Note: If booting from USB, we need to disable branch prediction * before copying from USB into RAM (FIXME: why?) */ sctlr = read_sctlr(); - sctlr |= SCTLR_C | SCTLR_Z | SCTLR_I; + sctlr |= SCTLR_Z | SCTLR_I; write_sctlr(sctlr);
if (boot_cpu()) { diff --git a/src/arch/armv7/include/arch/cache.h b/src/arch/armv7/include/arch/cache.h index c003256..1d7518f 100644 --- a/src/arch/armv7/include/arch/cache.h +++ b/src/arch/armv7/include/arch/cache.h @@ -108,6 +108,32 @@ static inline void tlbiall(void) asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); }
+/* write data access control register (DACR) */ +static inline void write_dacr(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c3, c0, 0" : : "r" (val)); +} + +/* write translation table base register 0 (TTBR0) */ +static inline void write_ttbr0(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (val) : "memory"); +} + +/* read translation table base control register (TTBCR) */ +static inline uint32_t read_ttbcr(void) +{ + uint32_t val = 0; + asm volatile ("mrc p15, 0, %0, c2, c0, 2" : "=r" (val)); + return val; +} + +/* write translation table base control register (TTBCR) */ +static inline void write_ttbcr(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c2, c0, 2" : : "r" (val) : "memory"); +} + /* * Low-level cache maintenance operations */ @@ -224,6 +250,12 @@ void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len); /* dcache invalidate all (on current level given by CCSELR) */ void dcache_invalidate_all(void);
+/* dcache and MMU disable */ +void dcache_mmu_disable(void); + +/* dcache and MMU enable */ +void dcache_mmu_enable(void); + /* icache invalidate all (on current level given by CSSELR) */ void icache_invalidate_all(void);
diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc index c248b9e..de41f7f 100644 --- a/src/arch/armv7/lib/Makefile.inc +++ b/src/arch/armv7/lib/Makefile.inc @@ -9,6 +9,7 @@ bootblock-y += cache-cp15.c romstage-y += cache.c romstage-y += cache_v7.c romstage-y += cache-cp15.c +romstage-y += mmu.c romstage-y += div0.c romstage-y += syslib.c romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c diff --git a/src/arch/armv7/lib/cache.c b/src/arch/armv7/lib/cache.c index 63e406c..2686db7 100644 --- a/src/arch/armv7/lib/cache.c +++ b/src/arch/armv7/lib/cache.c @@ -204,6 +204,28 @@ void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len) dcache_op_mva(addr, len, OP_DCCIMVAC); }
+ +void dcache_mmu_disable(void) +{ + uint32_t sctlr; + + sctlr = read_sctlr(); + dcache_clean_invalidate_all(); + sctlr &= ~(SCTLR_C | SCTLR_M); + write_sctlr(sctlr); +} + + +void dcache_mmu_enable(void) +{ + uint32_t sctlr; + + sctlr = read_sctlr(); + dcache_clean_invalidate_all(); + sctlr |= SCTLR_C | SCTLR_M; + write_sctlr(sctlr); +} + void armv7_invalidate_caches(void) { uint32_t clidr; @@ -252,10 +274,3 @@ void armv7_invalidate_caches(void) /* Invalidate TLB */ tlb_invalidate_all(); } - -/* 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/src/arch/armv7/lib/mmu.c b/src/arch/armv7/lib/mmu.c new file mode 100644 index 0000000..eb66186 --- /dev/null +++ b/src/arch/armv7/lib/mmu.c @@ -0,0 +1,119 @@ +/* + * 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. + */ + +#include <types.h> +#include <stdlib.h> + +#include <cbmem.h> +#include <console/console.h> + +#include <arch/cache.h> + +#define L1_TLB_ENTRIES 4096 + +void mmu_setup_by_mva(unsigned long dram_start_mb, unsigned long dram_size_mb) +{ + int i; + uintptr_t ttb_addr; + unsigned int ttb_size; + uint32_t *p; + uint32_t attr; + uint32_t ttbcr; + + /* + * For coreboot's purposes, we will create a simple L1 page table + * in RAM with 1MB section translation entries over the 4GB address + * space. + * (ref: section 10.2 and example 15-4 in Cortex-A series + * programmer's guide) + * + * FIXME: TLB needs to be aligned to 16KB, but cbmem_add() aligns to + * 512 bytes. So add double the space in cbmem and fix-up the pointer. + */ + ttb_size = L1_TLB_ENTRIES * sizeof(int); + ttb_addr = (uintptr_t)cbmem_add(CBMEM_ID_GDT, ttb_size * 2); + ttb_addr = ALIGN(ttb_addr + ttb_size, ttb_size); + p = (uint32_t *)ttb_addr; + + /* + * Section entry bits: + * 31:20 - section base address + * 18 - 0 to indicate normal section (versus supersection) + * 17 - nG, 0 to indicate page is global + * 16 - S, 0 for non-shareable (?) + * 15 - APX, 0 for full access + * 14:12 - TEX, 0b000 for outer and inner write-back + * 11:10 - AP, 0b11 for full access + * 9 - P, ? (FIXME: not described or possibly obsolete?) + * 8: 5 - Domain + * 4 - XN, 1 to set execute-never (and also avoid prefetches) + * 3 - C, 1 for cacheable + * 2 - B, 1 for bufferable + * 1: 0 - 0b10 to indicate section entry + */ + printk(BIOS_DEBUG, "%s: Writing page table @ to 0x%p\n", __func__, p); + printk(BIOS_DEBUG, "%s: Non-cachable region: page table @ to 0x%p\n", __func__, p); + + /* + * Non-DRAM pages are non-cacheable. Since this may correspond to read- + * sensitive regions (ie MMIO), mark as XN to disable speculative + * prefetching. + */ + attr = (0x3 << 10) | (1 << 4) | 0x2; + for (i = 0; i < dram_start_mb; i++) + p[i] = (i << 20) | attr; + + for (i = dram_start_mb + dram_size_mb; i < L1_TLB_ENTRIES; i++) + p[i] = (i << 20) | attr; + + /* DRAM portion will be write-back for coreboot */ + attr = (0x3 << 10) | (1 << 4) | (1 << 3) | (1 << 2) | 0x2; + for (i = dram_start_mb; i < dram_size_mb; i++) + p[i] = (i << 20) | attr; + + /* + * Disable TTBR1 by setting TTBCR.N to 0b000, which means the TTBR0 + * table size is 16KB and has indices VA[31:20]. + * + * ref: Arch Ref. Manual for ARMv7-A, B3.5.4, + */ + ttbcr = read_ttbcr(); + ttbcr &= ~(0x3); + write_ttbcr(ttbcr); + + /* + * Translation table base 0 address is in bits 31:14-N, where N is given + * by bits 2:0 in TTBCR (which we set to 0). All lower bits in this + * register should be zero for coreboot. + */ + write_ttbr0(ttb_addr); + + /* disable domain-level checking of permissions */ + write_dacr(~0); +} diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6193e63..041de70 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -47,7 +47,8 @@ romstage-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem.c romstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c romstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c romstage-$(CONFIG_USBDEBUG) += usbdebug.c -romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c cbmem.c +romstage-$(CONFIG_EARLY_CBMEM_INIT) += cbmem.c +romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c romstage-y += compute_ip_checksum.c romstage-y += memmove.c romstage-$(CONFIG_ARCH_X86) += gcc.c diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c index bfb4156..ceffc65 100644 --- a/src/mainboard/google/snow/romstage.c +++ b/src/mainboard/google/snow/romstage.c @@ -74,6 +74,13 @@ static void graphics(void) exynos_pinmux_config(PERIPH_ID_DPHPD, 0); }
+/* for cbmem_initialize() */ +unsigned long get_top_of_ram(void); +unsigned long get_top_of_ram(void) +{ + return CONFIG_SYS_SDRAM_BASE + CONFIG_DRAM_SIZE_MB - 1UL; +} + void main(void) { struct mem_timings *mem; @@ -113,8 +120,9 @@ void main(void) while(1); }
- /* Set up MMU and caches */ + /* Set up dcache and MMU */ mmu_setup_by_mva(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB); + dcache_mmu_enable();
initialize_s5p_mshc();