Newer
Older
arm-trusted-firmware / plat / fvp / aarch64 / bl32_setup_xlat.c
@Achin Gupta Achin Gupta on 20 Feb 2014 12 KB Add Test Secure Payload (BL3-2) image
/*
 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 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.
 *
 * Neither the name of ARM nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 <string.h>
#include <assert.h>
#include <arch_helpers.h>
#include <platform.h>
#include <bl_common.h>

#define BL32_NUM_L3_PAGETABLES	3
#define BL32_TZRAM_PAGETABLE	0
#define BL32_TZDRAM_PAGETABLE	1
#define BL32_NSRAM_PAGETABLE	2

/*******************************************************************************
 * Level 1 translation tables need 4 entries for the 4GB address space accessib-
 * le by the secure firmware. Input address space will be restricted using the
 * T0SZ settings in the TCR.
 ******************************************************************************/
static unsigned long l1_xlation_table[ADDR_SPACE_SIZE >> 30]
__attribute__ ((aligned((ADDR_SPACE_SIZE >> 30) << 3)));

/*******************************************************************************
 * Level 2 translation tables describe the first & second gb of the address
 * space needed to address secure peripherals e.g. trusted ROM and RAM.
 ******************************************************************************/
static unsigned long l2_xlation_table[NUM_L2_PAGETABLES][NUM_2MB_IN_GB]
__attribute__ ((aligned(NUM_2MB_IN_GB << 3),
	section("xlat_table")));

/*******************************************************************************
 * Level 3 translation tables (2 sets) describe the trusted & non-trusted RAM
 * regions at a granularity of 4K.
 ******************************************************************************/
static unsigned long l3_xlation_table[BL32_NUM_L3_PAGETABLES][NUM_4K_IN_2MB]
__attribute__ ((aligned(NUM_4K_IN_2MB << 3),
	section("xlat_table")));

/*******************************************************************************
 * Create page tables as per the platform memory map. Certain aspects of page
 * talble creating have been abstracted in the above routines. This can be impr-
 * oved further.
 * TODO: Move the page table setup helpers into the arch or lib directory
 *******************************************************************************/
unsigned long fill_xlation_tables(meminfo *tzdram_layout,
				  unsigned long ro_start,
				  unsigned long ro_limit,
				  unsigned long coh_start,
				  unsigned long coh_limit)
{
	unsigned long l2_desc, l3_desc;
	unsigned long *xt_addr = 0, *pt_addr, off = 0;
	unsigned long trom_start_index, trom_end_index;
	unsigned long tzram_start_index, tzram_end_index;
	unsigned long flash0_start_index, flash0_end_index;
	unsigned long flash1_start_index, flash1_end_index;
	unsigned long vram_start_index, vram_end_index;
	unsigned long nsram_start_index, nsram_end_index;
	unsigned long tzdram_start_index, tzdram_end_index;
	unsigned long dram_start_index, dram_end_index;
	unsigned long dev0_start_index, dev0_end_index;
	unsigned long dev1_start_index, dev1_end_index;
	unsigned int idx;

	/*****************************************************************
	 * LEVEL1 PAGETABLE SETUP
	 *
	 * Find the start and end indices of the memory peripherals in the
	 * first level pagetables. These are the main areas we care about.
	 * Also bump the end index by one if its equal to the start to
	 * allow for regions which lie completely in a GB.
	 *****************************************************************/
	trom_start_index = ONE_GB_INDEX(TZROM_BASE);
	dev0_start_index = ONE_GB_INDEX(TZRNG_BASE);
	dram_start_index = ONE_GB_INDEX(DRAM_BASE);
	dram_end_index = ONE_GB_INDEX(DRAM_BASE + DRAM_SIZE);

	if (dram_end_index == dram_start_index)
		dram_end_index++;

	/*
	 * Fill up the level1 translation table first
	 */
	for (idx = 0; idx < (ADDR_SPACE_SIZE >> 30); idx++) {

		/*
		 * Fill up the entry for the TZROM. This will cover
		 * everything in the first GB.
		 */
		if (idx == trom_start_index) {
			xt_addr = &l2_xlation_table[GB1_L2_PAGETABLE][0];
			l1_xlation_table[idx] = create_table_desc(xt_addr);
			continue;
		}

		/*
		 * Mark the second gb as device
		 */
		if (idx == dev0_start_index) {
			xt_addr = &l2_xlation_table[GB2_L2_PAGETABLE][0];
			l1_xlation_table[idx] = create_table_desc(xt_addr);
			continue;
		}

		/*
		 * Fill up the block entry for the DRAM with Normal
		 * inner-WBWA outer-WBWA non-transient attributes.
		 * This will cover 2-4GB. Note that the acesses are
		 * marked as non-secure.
		 */
		if ((idx >= dram_start_index) && (idx < dram_end_index)) {
			l1_xlation_table[idx] = create_rwmem_block(idx, LEVEL1,
								   NS);
			continue;
		}

		assert(0);
	}


	/*****************************************************************
	 * LEVEL2 PAGETABLE SETUP
	 *
	 * Find the start and end indices of the memory & peripherals in the
	 * second level pagetables.
	 ******************************************************************/

	/* Initializations for the 1st GB */
	trom_start_index = TWO_MB_INDEX(TZROM_BASE);
	trom_end_index = TWO_MB_INDEX(TZROM_BASE + TZROM_SIZE);
	if (trom_end_index == trom_start_index)
		trom_end_index++;

	tzdram_start_index = TWO_MB_INDEX(TZDRAM_BASE);
	tzdram_end_index = TWO_MB_INDEX(TZDRAM_BASE + TZDRAM_SIZE);
	if (tzdram_end_index == tzdram_start_index)
		tzdram_end_index++;

	flash0_start_index = TWO_MB_INDEX(FLASH0_BASE);
	flash0_end_index = TWO_MB_INDEX(FLASH0_BASE + TZROM_SIZE);
	if (flash0_end_index == flash0_start_index)
		flash0_end_index++;

	flash1_start_index = TWO_MB_INDEX(FLASH1_BASE);
	flash1_end_index = TWO_MB_INDEX(FLASH1_BASE + FLASH1_SIZE);
	if (flash1_end_index == flash1_start_index)
		flash1_end_index++;

	vram_start_index = TWO_MB_INDEX(VRAM_BASE);
	vram_end_index = TWO_MB_INDEX(VRAM_BASE + VRAM_SIZE);
	if (vram_end_index == vram_start_index)
		vram_end_index++;

	dev0_start_index = TWO_MB_INDEX(DEVICE0_BASE);
	dev0_end_index = TWO_MB_INDEX(DEVICE0_BASE + DEVICE0_SIZE);
	if (dev0_end_index == dev0_start_index)
		dev0_end_index++;

	dev1_start_index = TWO_MB_INDEX(DEVICE1_BASE);
	dev1_end_index = TWO_MB_INDEX(DEVICE1_BASE + DEVICE1_SIZE);
	if (dev1_end_index == dev1_start_index)
		dev1_end_index++;

	/* Since the size is < 2M this is a single index */
	tzram_start_index = TWO_MB_INDEX(TZRAM_BASE);
	nsram_start_index = TWO_MB_INDEX(NSRAM_BASE);

	/*
	 * Fill up the level2 translation table for the first GB next
	 */
	for (idx = 0; idx < NUM_2MB_IN_GB; idx++) {

		l2_desc = INVALID_DESC;
		xt_addr = &l2_xlation_table[GB1_L2_PAGETABLE][idx];

		/* Block entries for 64M of trusted Boot ROM */
		if ((idx >= trom_start_index) && (idx < trom_end_index))
			l2_desc = create_romem_block(idx, LEVEL2, 0);

		/* Single L3 page table entry for 256K of TZRAM */
		if (idx == tzram_start_index) {
			pt_addr = &l3_xlation_table[BL32_TZRAM_PAGETABLE][0];
			l2_desc = create_table_desc(pt_addr);
		}

		/*
		 * Single L3 page table entry for first 2MB of TZDRAM.
		 * TODO: We are assuming the BL32 image will not
		 * exceed this
		 */
		if (idx == tzdram_start_index) {
			pt_addr = &l3_xlation_table[BL32_TZDRAM_PAGETABLE][0];
			l2_desc = create_table_desc(pt_addr);
		}

		/* Block entries for 32M of trusted DRAM */
		if ((idx >= tzdram_start_index + 1) && (idx <= tzdram_end_index))
			l2_desc = create_rwmem_block(idx, LEVEL2, 0);

		/* Block entries for 64M of aliased trusted Boot ROM */
		if ((idx >= flash0_start_index) && (idx < flash0_end_index))
			l2_desc = create_romem_block(idx, LEVEL2, 0);

		/* Block entries for 64M of flash1 */
		if ((idx >= flash1_start_index) && (idx < flash1_end_index))
			l2_desc = create_romem_block(idx, LEVEL2, 0);

		/* Block entries for 32M of VRAM */
		if ((idx >= vram_start_index) && (idx < vram_end_index))
			l2_desc = create_rwmem_block(idx, LEVEL2, 0);

		/* Block entries for all the devices in the first gb */
		if ((idx >= dev0_start_index) && (idx < dev0_end_index))
			l2_desc = create_device_block(idx, LEVEL2, 0);

		/* Block entries for all the devices in the first gb */
		if ((idx >= dev1_start_index) && (idx < dev1_end_index))
			l2_desc = create_device_block(idx, LEVEL2, 0);

		/* Single L3 page table entry for 64K of NSRAM */
		if (idx == nsram_start_index) {
			pt_addr = &l3_xlation_table[BL32_NSRAM_PAGETABLE][0];
			l2_desc = create_table_desc(pt_addr);
		}

		*xt_addr = l2_desc;
	}


	/*
	 * Initializations for the 2nd GB. Mark everything as device
	 * for the time being as the memory map is not final. Each
	 * index will need to be offset'ed to allow absolute values
	 */
	off = NUM_2MB_IN_GB;
	for (idx = off; idx < (NUM_2MB_IN_GB + off); idx++) {
		l2_desc = create_device_block(idx, LEVEL2, 0);
		xt_addr = &l2_xlation_table[GB2_L2_PAGETABLE][idx - off];
		*xt_addr = l2_desc;
	}


	/*****************************************************************
	 * LEVEL3 PAGETABLE SETUP
	 *****************************************************************/

	/* Fill up the level3 pagetable for the trusted SRAM. */
	tzram_start_index = FOUR_KB_INDEX(TZRAM_BASE);
	tzram_end_index = FOUR_KB_INDEX(TZRAM_BASE + TZRAM_SIZE);
	if (tzram_end_index == tzram_start_index)
		tzram_end_index++;

	/* Each index will need to be offset'ed to allow absolute values */
	off = FOUR_KB_INDEX(TZRAM_BASE);
	for (idx = off; idx < (NUM_4K_IN_2MB + off); idx++) {

		l3_desc = INVALID_DESC;
		xt_addr = &l3_xlation_table[BL32_TZRAM_PAGETABLE][idx - off];

		/*
		 * TODO: All TZRAM memory is being mapped as RW while
		 * earlier boot stages map parts of it as Device. This
		 * could lead to possible coherency issues. Ditto for
		 * the way earlier boot loader stages map TZDRAM
		 */
		if (idx >= tzram_start_index && idx < tzram_end_index)
			l3_desc = create_rwmem_block(idx, LEVEL3, 0);

		*xt_addr = l3_desc;
	}

	/* Fill up the level3 pagetable for the trusted DRAM. */
	tzdram_start_index = FOUR_KB_INDEX(tzdram_layout->total_base);
	tzdram_end_index = FOUR_KB_INDEX(tzdram_layout->total_base +
					 tzdram_layout->total_size);
	if (tzdram_end_index == tzdram_start_index)
		tzdram_end_index++;

	/* Reusing trom* to mark RO memory. */
	trom_start_index = FOUR_KB_INDEX(ro_start);
	trom_end_index = FOUR_KB_INDEX(ro_limit);
	if (trom_end_index == trom_start_index)
		trom_end_index++;

	/* Reusing dev* to mark coherent device memory. */
	dev0_start_index = FOUR_KB_INDEX(coh_start);
	dev0_end_index = FOUR_KB_INDEX(coh_limit);
	if (dev0_end_index == dev0_start_index)
		dev0_end_index++;

	/* Each index will need to be offset'ed to allow absolute values */
	off = FOUR_KB_INDEX(TZDRAM_BASE);
	for (idx = off; idx < (NUM_4K_IN_2MB + off); idx++) {

		l3_desc = INVALID_DESC;
		xt_addr = &l3_xlation_table[BL32_TZDRAM_PAGETABLE][idx - off];

		if (idx >= tzdram_start_index && idx < tzdram_end_index)
			l3_desc = create_rwmem_block(idx, LEVEL3, 0);

		if (idx >= trom_start_index && idx < trom_end_index)
			l3_desc = create_romem_block(idx, LEVEL3, 0);

		if (idx >= dev0_start_index && idx < dev0_end_index)
			l3_desc = create_device_block(idx, LEVEL3, 0);

		*xt_addr = l3_desc;
	}

	/* Fill up the level3 pagetable for the non-trusted SRAM. */
	nsram_start_index = FOUR_KB_INDEX(NSRAM_BASE);
	nsram_end_index = FOUR_KB_INDEX(NSRAM_BASE + NSRAM_SIZE);
	if (nsram_end_index == nsram_start_index)
		nsram_end_index++;

	 /* Each index will need to be offset'ed to allow absolute values */
	off = FOUR_KB_INDEX(NSRAM_BASE);
	for (idx = off; idx < (NUM_4K_IN_2MB + off); idx++) {

		l3_desc = INVALID_DESC;
		xt_addr = &l3_xlation_table[BL32_NSRAM_PAGETABLE][idx - off];

		if (idx >= nsram_start_index && idx < nsram_end_index)
			l3_desc = create_rwmem_block(idx, LEVEL3, NS);

		*xt_addr = l3_desc;
	}

	return (unsigned long) l1_xlation_table;
}