d4d6a407f7
This adds a call to tlb_invalidate_all() after configuring a range of memory. Change-Id: I558402e7e54b6bf9e0b013f153d9b84c0873a6cf Signed-off-by: David Hendricks <dhendrix@chromium.org> Reviewed-on: http://review.coreboot.org/2946 Reviewed-by: Ronald G. Minnich <rminnich@gmail.com> Tested-by: build bot (Jenkins)
135 lines
4.4 KiB
C
135 lines
4.4 KiB
C
/*
|
|
* 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 <stdlib.h>
|
|
#include <stdint.h>
|
|
|
|
#include <cbmem.h>
|
|
#include <console/console.h>
|
|
|
|
#include <arch/cache.h>
|
|
|
|
#define L1_TLB_ENTRIES 4096 /* 1 entry for each 1MB address space */
|
|
|
|
static uintptr_t ttb_addr;
|
|
|
|
void mmu_config_range(unsigned long start_mb, unsigned long size_mb,
|
|
enum dcache_policy policy)
|
|
{
|
|
unsigned int i;
|
|
uint32_t attr;
|
|
uint32_t *ttb_entry = (uint32_t *)ttb_addr;
|
|
const char *str = NULL;
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
switch(policy) {
|
|
case DCACHE_OFF:
|
|
/* XN set to avoid prefetches to uncached/unbuffered regions */
|
|
attr = (0x3 << 10) | (1 << 4) | 0x2;
|
|
str = "off";
|
|
break;
|
|
case DCACHE_WRITEBACK:
|
|
attr = (0x3 << 10) | (1 << 3) | (1 << 2) | 0x2;
|
|
str = "writeback";
|
|
break;
|
|
case DCACHE_WRITETHROUGH:
|
|
attr = (0x3 << 10) | (1 << 3) | (1 << 2) | 0x2;
|
|
str = "writethrough";
|
|
break;
|
|
default:
|
|
printk(BIOS_ERR, "unknown dcache policy: %02x\n", policy);
|
|
return;
|
|
}
|
|
|
|
printk(BIOS_DEBUG, "Setting dcache policy: 0x%08lx:0x%08lx [%s]\n",
|
|
start_mb << 20, ((start_mb + size_mb) << 20) - 1, str);
|
|
|
|
for (i = start_mb; i < start_mb + size_mb; i++)
|
|
ttb_entry[i] = (i << 20) | attr;
|
|
|
|
/* TODO: add helper to invalidate TLB by MVA */
|
|
tlb_invalidate_all();
|
|
}
|
|
|
|
void mmu_init(void)
|
|
{
|
|
unsigned int ttb_size;
|
|
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(unsigned long);
|
|
ttb_addr = (uintptr_t)cbmem_add(CBMEM_ID_GDT, ttb_size * 2);
|
|
ttb_addr = ALIGN(ttb_addr + ttb_size, ttb_size);
|
|
printk(BIOS_DEBUG, "Translation table is @ 0x%08x\n", ttb_addr);
|
|
|
|
/*
|
|
* 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);
|
|
}
|