Add support for QEMU virt ARMv8-A target
This patch adds support for the QEMU virt ARMv8-A target. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
This commit is contained in:
parent
ae43c9493d
commit
419e0d262b
|
@ -0,0 +1,44 @@
|
||||||
|
ARM Trusted Firmware for QEMU virt ARMv8-A
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
ARM Trusted Firmware implements the EL3 firmware layer for QEMU virt
|
||||||
|
ARMv8-A. BL1 is used as the BootROM, supplied with the -bios argument.
|
||||||
|
When QEMU starts all CPUs are released simultaneously, BL1 selects a
|
||||||
|
primary CPU to handle the boot and the secondaries are placed in a polling
|
||||||
|
loop to be released by normal world via PSCI.
|
||||||
|
|
||||||
|
BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to
|
||||||
|
add a node describing PSCI and also enable methods for the CPUs.
|
||||||
|
|
||||||
|
An ARM64 defonfig v4.5 Linux kernel is known to boot, FTD doesn't need to be
|
||||||
|
provided as it's generated by QEMU.
|
||||||
|
|
||||||
|
Current limitations:
|
||||||
|
* Only cold boot is supported
|
||||||
|
* No build instructions for QEMU_EFI.fd and rootfs-arm64.cpio.gz
|
||||||
|
* No instructions for how to load a BL32 (Secure Payload)
|
||||||
|
|
||||||
|
`QEMU_EFI.fd` can be dowloaded from
|
||||||
|
http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC49/QEMU_EFI.fd
|
||||||
|
|
||||||
|
Boot binaries, except BL1, are primarily loaded via semi-hosting so all
|
||||||
|
binaries has to reside in the same directory as QEMU is started from. This
|
||||||
|
is conveniently achieved with symlinks the local names as:
|
||||||
|
* `bl2.bin` -> BL2
|
||||||
|
* `bl31.bin` -> BL31
|
||||||
|
* `bl33.bin` -> BL33 (`QEMU_EFI.fd`)
|
||||||
|
* `Image` -> linux/Image
|
||||||
|
|
||||||
|
To build:
|
||||||
|
```
|
||||||
|
make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu
|
||||||
|
```
|
||||||
|
|
||||||
|
To start (QEMU v2.6.0):
|
||||||
|
```
|
||||||
|
qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \
|
||||||
|
-kernel Image \
|
||||||
|
-append console=ttyAMA0,38400 keep_bootcon root=/dev/vda2 \
|
||||||
|
-initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin \
|
||||||
|
-d unimp -semihosting-config enable,target=native
|
||||||
|
```
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <arch.h>
|
||||||
|
#include <asm_macros.S>
|
||||||
|
#include <assert_macros.S>
|
||||||
|
#include <platform_def.h>
|
||||||
|
|
||||||
|
.globl plat_my_core_pos
|
||||||
|
.globl plat_get_my_entrypoint
|
||||||
|
.globl platform_mem_init
|
||||||
|
.globl plat_qemu_calc_core_pos
|
||||||
|
.globl plat_crash_console_init
|
||||||
|
.globl plat_crash_console_putc
|
||||||
|
.globl plat_secondary_cold_boot_setup
|
||||||
|
.globl plat_get_my_entrypoint
|
||||||
|
.globl plat_is_my_cpu_primary
|
||||||
|
|
||||||
|
|
||||||
|
func plat_my_core_pos
|
||||||
|
mrs x0, mpidr_el1
|
||||||
|
b plat_qemu_calc_core_pos
|
||||||
|
endfunc plat_my_core_pos
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
|
||||||
|
* With this function: CorePos = (ClusterId * 4) + CoreId
|
||||||
|
*/
|
||||||
|
func plat_qemu_calc_core_pos
|
||||||
|
and x1, x0, #MPIDR_CPU_MASK
|
||||||
|
and x0, x0, #MPIDR_CLUSTER_MASK
|
||||||
|
add x0, x1, x0, LSR #6
|
||||||
|
ret
|
||||||
|
endfunc plat_qemu_calc_core_pos
|
||||||
|
|
||||||
|
/* -----------------------------------------------------
|
||||||
|
* unsigned int plat_is_my_cpu_primary (void);
|
||||||
|
*
|
||||||
|
* Find out whether the current cpu is the primary
|
||||||
|
* cpu.
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
func plat_is_my_cpu_primary
|
||||||
|
mrs x0, mpidr_el1
|
||||||
|
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
|
||||||
|
cmp x0, #QEMU_PRIMARY_CPU
|
||||||
|
cset w0, eq
|
||||||
|
ret
|
||||||
|
endfunc plat_is_my_cpu_primary
|
||||||
|
|
||||||
|
/* -----------------------------------------------------
|
||||||
|
* void plat_secondary_cold_boot_setup (void);
|
||||||
|
*
|
||||||
|
* This function performs any platform specific actions
|
||||||
|
* needed for a secondary cpu after a cold reset e.g
|
||||||
|
* mark the cpu's presence, mechanism to place it in a
|
||||||
|
* holding pen etc.
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
func plat_secondary_cold_boot_setup
|
||||||
|
/* Calculate address of our hold entry */
|
||||||
|
bl plat_my_core_pos
|
||||||
|
mov_imm x2, PLAT_QEMU_HOLD_BASE
|
||||||
|
|
||||||
|
/* Wait until we have a go */
|
||||||
|
poll_mailbox:
|
||||||
|
ldr x1, [x2, x0]
|
||||||
|
cbz x1, 1f
|
||||||
|
mov_imm x0, PLAT_QEMU_TRUSTED_MAILBOX_BASE
|
||||||
|
ldr x1, [x0]
|
||||||
|
br x1
|
||||||
|
1:
|
||||||
|
wfe
|
||||||
|
b poll_mailbox
|
||||||
|
endfunc plat_secondary_cold_boot_setup
|
||||||
|
|
||||||
|
func plat_get_my_entrypoint
|
||||||
|
/* TODO support warm boot */
|
||||||
|
mov x0, #0
|
||||||
|
ret
|
||||||
|
endfunc plat_get_my_entrypoint
|
||||||
|
|
||||||
|
func platform_mem_init
|
||||||
|
ret
|
||||||
|
endfunc platform_mem_init
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* int plat_crash_console_init(void)
|
||||||
|
* Function to initialize the crash console
|
||||||
|
* without a C Runtime to print crash report.
|
||||||
|
* Clobber list : x0, x1, x2
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
func plat_crash_console_init
|
||||||
|
mov_imm x0, PLAT_QEMU_CRASH_UART_BASE
|
||||||
|
mov_imm x1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ
|
||||||
|
mov_imm x2, PLAT_QEMU_CONSOLE_BAUDRATE
|
||||||
|
b console_core_init
|
||||||
|
endfunc plat_crash_console_init
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* int plat_crash_console_putc(int c)
|
||||||
|
* Function to print a character on the crash
|
||||||
|
* console without a C Runtime.
|
||||||
|
* Clobber list : x1, x2
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
func plat_crash_console_putc
|
||||||
|
mov_imm x1, PLAT_QEMU_CRASH_UART_BASE
|
||||||
|
b console_core_putc
|
||||||
|
endfunc plat_crash_console_putc
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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 <console.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <libfdt.h>
|
||||||
|
#include <psci.h>
|
||||||
|
#include "qemu_private.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int append_psci_compatible(void *fdt, int offs, const char *str)
|
||||||
|
{
|
||||||
|
return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dt_add_psci_node(void *fdt)
|
||||||
|
{
|
||||||
|
int offs;
|
||||||
|
|
||||||
|
if (fdt_path_offset(fdt, "/psci") >= 0) {
|
||||||
|
WARN("PSCI Device Tree node already exists!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offs = fdt_path_offset(fdt, "/");
|
||||||
|
if (offs < 0)
|
||||||
|
return -1;
|
||||||
|
offs = fdt_add_subnode(fdt, offs, "psci");
|
||||||
|
if (offs < 0)
|
||||||
|
return -1;
|
||||||
|
if (append_psci_compatible(fdt, offs, "arm,psci-1.0"))
|
||||||
|
return -1;
|
||||||
|
if (append_psci_compatible(fdt, offs, "arm,psci-0.2"))
|
||||||
|
return -1;
|
||||||
|
if (append_psci_compatible(fdt, offs, "arm,psci"))
|
||||||
|
return -1;
|
||||||
|
if (fdt_setprop_string(fdt, offs, "method", "smc"))
|
||||||
|
return -1;
|
||||||
|
if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_AARCH64))
|
||||||
|
return -1;
|
||||||
|
if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF))
|
||||||
|
return -1;
|
||||||
|
if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_AARCH64))
|
||||||
|
return -1;
|
||||||
|
if (fdt_setprop_u32(fdt, offs, "sys_poweroff", PSCI_SYSTEM_OFF))
|
||||||
|
return -1;
|
||||||
|
if (fdt_setprop_u32(fdt, offs, "sys_reset", PSCI_SYSTEM_RESET))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_node_compat_prefix(void *fdt, int offs, const char *prefix)
|
||||||
|
{
|
||||||
|
const size_t prefix_len = strlen(prefix);
|
||||||
|
size_t l;
|
||||||
|
int plen;
|
||||||
|
const char *prop;
|
||||||
|
|
||||||
|
prop = fdt_getprop(fdt, offs, "compatible", &plen);
|
||||||
|
if (!prop)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (plen > 0) {
|
||||||
|
if (memcmp(prop, prefix, prefix_len) == 0)
|
||||||
|
return 0; /* match */
|
||||||
|
|
||||||
|
l = strlen(prop) + 1;
|
||||||
|
prop += l;
|
||||||
|
plen -= l;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dt_add_psci_cpu_enable_methods(void *fdt)
|
||||||
|
{
|
||||||
|
int offs = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
offs = fdt_next_node(fdt, offs, NULL);
|
||||||
|
if (offs < 0)
|
||||||
|
break;
|
||||||
|
if (fdt_getprop(fdt, offs, "enable-method", NULL))
|
||||||
|
continue; /* already set */
|
||||||
|
if (check_node_compat_prefix(fdt, offs, "arm,cortex-a"))
|
||||||
|
continue; /* no compatible */
|
||||||
|
if (fdt_setprop_string(fdt, offs, "enable-method", "psci"))
|
||||||
|
return -1;
|
||||||
|
/* Need to restart scanning as offsets may have changed */
|
||||||
|
offs = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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.
|
||||||
|
*/
|
||||||
|
#ifndef __PLAT_MACROS_S__
|
||||||
|
#define __PLAT_MACROS_S__
|
||||||
|
|
||||||
|
#include <arm_macros.S>
|
||||||
|
#include <platform_def.h>
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* The below required platform porting macro
|
||||||
|
* prints out relevant GIC and CCI registers
|
||||||
|
* whenever an unhandled exception is taken in
|
||||||
|
* BL31.
|
||||||
|
* Clobbers: x0 - x10, x16, x17, sp
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
.macro plat_crash_print_regs
|
||||||
|
mov_imm x17, GICC_BASE
|
||||||
|
mov_imm x16, GICD_BASE
|
||||||
|
arm_print_gic_regs
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#endif /* __PLAT_MACROS_S__ */
|
|
@ -0,0 +1,244 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PLATFORM_DEF_H__
|
||||||
|
#define __PLATFORM_DEF_H__
|
||||||
|
|
||||||
|
#include <arch.h>
|
||||||
|
#include <common_def.h>
|
||||||
|
#include <tbbr_img_def.h>
|
||||||
|
|
||||||
|
/* Special value used to verify platform parameters from BL2 to BL3-1 */
|
||||||
|
#define QEMU_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
|
||||||
|
|
||||||
|
#define PLATFORM_STACK_SIZE 0x1000
|
||||||
|
|
||||||
|
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
|
||||||
|
#define PLATFORM_CLUSTER_COUNT 2
|
||||||
|
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||||
|
#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||||
|
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
|
||||||
|
PLATFORM_CLUSTER1_CORE_COUNT)
|
||||||
|
|
||||||
|
#define QEMU_PRIMARY_CPU 0
|
||||||
|
|
||||||
|
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||||
|
PLATFORM_CORE_COUNT)
|
||||||
|
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||||
|
|
||||||
|
#define PLAT_MAX_RET_STATE 1
|
||||||
|
#define PLAT_MAX_OFF_STATE 2
|
||||||
|
|
||||||
|
/* Local power state for power domains in Run state. */
|
||||||
|
#define PLAT_LOCAL_STATE_RUN 0
|
||||||
|
/* Local power state for retention. Valid only for CPU power domains */
|
||||||
|
#define PLAT_LOCAL_STATE_RET 1
|
||||||
|
/*
|
||||||
|
* Local power state for OFF/power-down. Valid for CPU and cluster power
|
||||||
|
* domains.
|
||||||
|
*/
|
||||||
|
#define PLAT_LOCAL_STATE_OFF 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros used to parse state information from State-ID if it is using the
|
||||||
|
* recommended encoding for State-ID.
|
||||||
|
*/
|
||||||
|
#define PLAT_LOCAL_PSTATE_WIDTH 4
|
||||||
|
#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some data must be aligned on the biggest cache line size in the platform.
|
||||||
|
* This is known only to the platform as it might have a combination of
|
||||||
|
* integrated and external caches.
|
||||||
|
*/
|
||||||
|
#define CACHE_WRITEBACK_SHIFT 6
|
||||||
|
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Partition memory into secure ROM, non-secure DRAM, secure "SRAM",
|
||||||
|
* and secure DRAM.
|
||||||
|
*/
|
||||||
|
#define SEC_ROM_BASE 0x00000000
|
||||||
|
#define SEC_ROM_SIZE 0x00020000
|
||||||
|
|
||||||
|
#define NS_DRAM0_BASE 0x40000000
|
||||||
|
#define NS_DRAM0_SIZE 0x3de00000
|
||||||
|
|
||||||
|
#define SEC_SRAM_BASE 0x0e000000
|
||||||
|
#define SEC_SRAM_SIZE 0x00040000
|
||||||
|
|
||||||
|
#define SEC_DRAM_BASE 0x0e100000
|
||||||
|
#define SEC_DRAM_SIZE 0x00f00000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ARM-TF lives in SRAM, partition it here
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SHARED_RAM_BASE SEC_SRAM_BASE
|
||||||
|
#define SHARED_RAM_SIZE 0x00001000
|
||||||
|
|
||||||
|
#define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
|
||||||
|
#define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE)
|
||||||
|
#define PLAT_QEMU_HOLD_BASE (PLAT_QEMU_TRUSTED_MAILBOX_BASE + 8)
|
||||||
|
#define PLAT_QEMU_HOLD_SIZE (PLATFORM_CORE_COUNT * \
|
||||||
|
PLAT_QEMU_HOLD_ENTRY_SIZE)
|
||||||
|
#define PLAT_QEMU_HOLD_ENTRY_SIZE 8
|
||||||
|
#define PLAT_QEMU_HOLD_STATE_WAIT 0
|
||||||
|
#define PLAT_QEMU_HOLD_STATE_GO 1
|
||||||
|
|
||||||
|
#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE)
|
||||||
|
#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BL1 specific defines.
|
||||||
|
*
|
||||||
|
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
|
||||||
|
* addresses.
|
||||||
|
* Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
|
||||||
|
* the current BL1 RW debug size plus a little space for growth.
|
||||||
|
*/
|
||||||
|
#define BL1_RO_BASE SEC_ROM_BASE
|
||||||
|
#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
|
||||||
|
#define BL1_RW_BASE (BL1_RW_LIMIT - 0x12000)
|
||||||
|
#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BL2 specific defines.
|
||||||
|
*
|
||||||
|
* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
|
||||||
|
* size plus a little space for growth.
|
||||||
|
*/
|
||||||
|
#define BL2_BASE (BL31_BASE - 0x1D000)
|
||||||
|
#define BL2_LIMIT BL31_BASE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BL3-1 specific defines.
|
||||||
|
*
|
||||||
|
* Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
|
||||||
|
* current BL3-1 debug size plus a little space for growth.
|
||||||
|
*/
|
||||||
|
#define BL31_BASE (BL31_LIMIT - 0x20000)
|
||||||
|
#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
|
||||||
|
#define BL31_PROGBITS_LIMIT BL1_RW_BASE
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BL3-2 specific defines.
|
||||||
|
*
|
||||||
|
* BL3-2 can execute from Secure SRAM, or Secure DRAM.
|
||||||
|
*/
|
||||||
|
#define BL32_SRAM_BASE BL_RAM_BASE
|
||||||
|
#define BL32_SRAM_LIMIT BL31_BASE
|
||||||
|
#define BL32_DRAM_BASE SEC_DRAM_BASE
|
||||||
|
#define BL32_DRAM_LIMIT (SEC_DRAM_BASE + SEC_DRAM_SIZE)
|
||||||
|
|
||||||
|
#define SEC_SRAM_ID 0
|
||||||
|
#define SEC_DRAM_ID 1
|
||||||
|
|
||||||
|
#if BL32_RAM_LOCATION_ID == SEC_SRAM_ID
|
||||||
|
# define BL32_MEM_BASE BL_RAM_BASE
|
||||||
|
# define BL32_MEM_SIZE BL_RAM_SIZE
|
||||||
|
# define BL32_BASE BL32_SRAM_BASE
|
||||||
|
# define BL32_LIMIT BL32_SRAM_LIMIT
|
||||||
|
#elif BL32_RAM_LOCATION_ID == SEC_DRAM_ID
|
||||||
|
# define BL32_MEM_BASE SEC_DRAM_BASE
|
||||||
|
# define BL32_MEM_SIZE SEC_DRAM_SIZE
|
||||||
|
# define BL32_BASE BL32_DRAM_BASE
|
||||||
|
# define BL32_LIMIT BL32_DRAM_LIMIT
|
||||||
|
#else
|
||||||
|
# error "Unsupported BL32_RAM_LOCATION_ID value"
|
||||||
|
#endif
|
||||||
|
#define BL32_SIZE (BL32_LIMIT - BL32_BASE)
|
||||||
|
|
||||||
|
#define NS_IMAGE_OFFSET 0x60000000
|
||||||
|
|
||||||
|
#define ADDR_SPACE_SIZE (1ull << 32)
|
||||||
|
#define MAX_MMAP_REGIONS 8
|
||||||
|
#define MAX_XLAT_TABLES 6
|
||||||
|
#define MAX_IO_DEVICES 3
|
||||||
|
#define MAX_IO_HANDLES 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PL011 related constants
|
||||||
|
*/
|
||||||
|
#define UART0_BASE 0x09000000
|
||||||
|
#define UART1_BASE 0x09040000
|
||||||
|
#define UART0_CLK_IN_HZ 1
|
||||||
|
#define UART1_CLK_IN_HZ 1
|
||||||
|
|
||||||
|
#define PLAT_QEMU_BOOT_UART_BASE UART0_BASE
|
||||||
|
#define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ
|
||||||
|
|
||||||
|
#define PLAT_QEMU_CRASH_UART_BASE UART1_BASE
|
||||||
|
#define PLAT_QEMU_CRASH_UART_CLK_IN_HZ UART1_CLK_IN_HZ
|
||||||
|
|
||||||
|
#define PLAT_QEMU_CONSOLE_BAUDRATE 115200
|
||||||
|
|
||||||
|
#define QEMU_FLASH0_BASE 0x04000000
|
||||||
|
#define QEMU_FLASH0_SIZE 0x04000000
|
||||||
|
|
||||||
|
#define PLAT_QEMU_FIP_BASE QEMU_FLASH0_BASE
|
||||||
|
#define PLAT_QEMU_FIP_MAX_SIZE QEMU_FLASH0_SIZE
|
||||||
|
|
||||||
|
#define DEVICE0_BASE 0x08000000
|
||||||
|
#define DEVICE0_SIZE 0x00021000
|
||||||
|
#define DEVICE1_BASE 0x09000000
|
||||||
|
#define DEVICE1_SIZE 0x00011000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GIC related constants
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GICD_BASE 0x8000000
|
||||||
|
#define GICC_BASE 0x8010000
|
||||||
|
#define GICR_BASE 0
|
||||||
|
|
||||||
|
|
||||||
|
#define QEMU_IRQ_SEC_SGI_0 8
|
||||||
|
#define QEMU_IRQ_SEC_SGI_1 9
|
||||||
|
#define QEMU_IRQ_SEC_SGI_2 10
|
||||||
|
#define QEMU_IRQ_SEC_SGI_3 11
|
||||||
|
#define QEMU_IRQ_SEC_SGI_4 12
|
||||||
|
#define QEMU_IRQ_SEC_SGI_5 13
|
||||||
|
#define QEMU_IRQ_SEC_SGI_6 14
|
||||||
|
#define QEMU_IRQ_SEC_SGI_7 15
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DT related constants
|
||||||
|
*/
|
||||||
|
#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE
|
||||||
|
#define PLAT_QEMU_DT_MAX_SIZE 0x10000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System counter
|
||||||
|
*/
|
||||||
|
#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16)
|
||||||
|
|
||||||
|
#endif /* __PLATFORM_DEF_H__ */
|
|
@ -0,0 +1,99 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013-2015, 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 lib/libfdt/libfdt.mk
|
||||||
|
|
||||||
|
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
||||||
|
-Iinclude/plat/arm/common/aarch64/ \
|
||||||
|
-Iplat/qemu/include \
|
||||||
|
-Iinclude/common/tbbr
|
||||||
|
|
||||||
|
|
||||||
|
PLAT_BL_COMMON_SOURCES := plat/qemu/qemu_common.c \
|
||||||
|
drivers/arm/pl011/pl011_console.S \
|
||||||
|
lib/xlat_tables/xlat_tables_common.c \
|
||||||
|
lib/xlat_tables/aarch64/xlat_tables.c
|
||||||
|
|
||||||
|
BL1_SOURCES += drivers/io/io_semihosting.c \
|
||||||
|
drivers/io/io_storage.c \
|
||||||
|
drivers/io/io_fip.c \
|
||||||
|
drivers/io/io_memmap.c \
|
||||||
|
lib/semihosting/semihosting.c \
|
||||||
|
lib/semihosting/aarch64/semihosting_call.S \
|
||||||
|
plat/qemu/qemu_io_storage.c \
|
||||||
|
lib/cpus/aarch64/aem_generic.S \
|
||||||
|
lib/cpus/aarch64/cortex_a53.S \
|
||||||
|
lib/cpus/aarch64/cortex_a57.S \
|
||||||
|
plat/common/aarch64/platform_mp_stack.S \
|
||||||
|
plat/qemu/aarch64/plat_helpers.S \
|
||||||
|
plat/qemu/qemu_bl1_setup.c
|
||||||
|
|
||||||
|
BL2_SOURCES += drivers/io/io_semihosting.c \
|
||||||
|
drivers/io/io_storage.c \
|
||||||
|
drivers/io/io_fip.c \
|
||||||
|
drivers/io/io_memmap.c \
|
||||||
|
plat/common/aarch64/platform_mp_stack.S \
|
||||||
|
lib/semihosting/semihosting.c \
|
||||||
|
lib/semihosting/aarch64/semihosting_call.S\
|
||||||
|
plat/qemu/qemu_io_storage.c \
|
||||||
|
plat/qemu/aarch64/plat_helpers.S \
|
||||||
|
plat/qemu/qemu_bl2_setup.c \
|
||||||
|
plat/qemu/dt.c \
|
||||||
|
$(LIBFDT_SRCS)
|
||||||
|
|
||||||
|
BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
|
||||||
|
lib/cpus/aarch64/cortex_a53.S \
|
||||||
|
lib/cpus/aarch64/cortex_a57.S \
|
||||||
|
drivers/arm/gic/v2/gicv2_helpers.c \
|
||||||
|
drivers/arm/gic/v2/gicv2_main.c \
|
||||||
|
drivers/arm/gic/common/gic_common.c \
|
||||||
|
plat/common/aarch64/platform_mp_stack.S \
|
||||||
|
plat/common/aarch64/plat_psci_common.c \
|
||||||
|
plat/common/aarch64/plat_common.c \
|
||||||
|
plat/qemu/qemu_pm.c \
|
||||||
|
plat/qemu/topology.c \
|
||||||
|
plat/qemu/aarch64/plat_helpers.S \
|
||||||
|
plat/qemu/qemu_bl31_setup.c \
|
||||||
|
plat/qemu/qemu_gic.c
|
||||||
|
|
||||||
|
# Disable the PSCI platform compatibility layer
|
||||||
|
ENABLE_PLAT_COMPAT := 0
|
||||||
|
|
||||||
|
BL32_RAM_LOCATION := tdram
|
||||||
|
ifeq (${BL32_RAM_LOCATION}, tsram)
|
||||||
|
BL32_RAM_LOCATION_ID = SEC_SRAM_ID
|
||||||
|
else ifeq (${BL32_RAM_LOCATION}, tdram)
|
||||||
|
BL32_RAM_LOCATION_ID = SEC_DRAM_ID
|
||||||
|
else
|
||||||
|
$(error "Unsupported BL32_RAM_LOCATION value")
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Process flags
|
||||||
|
$(eval $(call add_define,BL32_RAM_LOCATION_ID))
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <arch.h>
|
||||||
|
#include <arch_helpers.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include "qemu_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 2 constants identify the extents of the coherent memory region.
|
||||||
|
* These addresses are used by the MMU setup code and therefore they must be
|
||||||
|
* page-aligned. It is the responsibility of the linker script to ensure that
|
||||||
|
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
|
||||||
|
* page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
|
||||||
|
#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Declarations of linker defined symbols which will tell us where BL1 lives
|
||||||
|
* in Trusted RAM
|
||||||
|
******************************************************************************/
|
||||||
|
extern uint64_t __BL1_RAM_START__;
|
||||||
|
extern uint64_t __BL1_RAM_END__;
|
||||||
|
#define BL1_RAM_BASE (uint64_t)(&__BL1_RAM_START__)
|
||||||
|
#define BL1_RAM_LIMIT (uint64_t)(&__BL1_RAM_END__)
|
||||||
|
|
||||||
|
/* Data structure which holds the extents of the trusted SRAM for BL1*/
|
||||||
|
static meminfo_t bl1_tzram_layout;
|
||||||
|
|
||||||
|
|
||||||
|
meminfo_t *bl1_plat_sec_mem_layout(void)
|
||||||
|
{
|
||||||
|
return &bl1_tzram_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Perform any BL1 specific platform actions.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl1_early_platform_setup(void)
|
||||||
|
{
|
||||||
|
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
|
||||||
|
|
||||||
|
/* Initialize the console to provide early debug support */
|
||||||
|
console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
|
||||||
|
PLAT_QEMU_CONSOLE_BAUDRATE);
|
||||||
|
|
||||||
|
/* Allow BL1 to see the whole Trusted RAM */
|
||||||
|
bl1_tzram_layout.total_base = BL_RAM_BASE;
|
||||||
|
bl1_tzram_layout.total_size = BL_RAM_SIZE;
|
||||||
|
|
||||||
|
/* Calculate how much RAM BL1 is using and how much remains free */
|
||||||
|
bl1_tzram_layout.free_base = BL_RAM_BASE;
|
||||||
|
bl1_tzram_layout.free_size = BL_RAM_SIZE;
|
||||||
|
reserve_mem(&bl1_tzram_layout.free_base, &bl1_tzram_layout.free_size,
|
||||||
|
BL1_RAM_BASE, bl1_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Perform the very early platform specific architecture setup. This only
|
||||||
|
* does basic initialization. Later architectural setup (bl1_arch_setup())
|
||||||
|
* does not do anything platform specific.
|
||||||
|
*****************************************************************************/
|
||||||
|
void bl1_plat_arch_setup(void)
|
||||||
|
{
|
||||||
|
qemu_configure_mmu_el3(bl1_tzram_layout.total_base,
|
||||||
|
bl1_tzram_layout.total_size,
|
||||||
|
BL1_RO_BASE, BL1_RO_LIMIT,
|
||||||
|
BL1_COHERENT_RAM_BASE, BL1_COHERENT_RAM_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bl1_platform_setup(void)
|
||||||
|
{
|
||||||
|
plat_qemu_io_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Function that takes a memory layout into which BL2 has been loaded and
|
||||||
|
* populates a new memory layout for BL2 that ensures that BL1's data sections
|
||||||
|
* resident in secure RAM are not visible to BL2.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
|
||||||
|
meminfo_t *bl2_mem_layout)
|
||||||
|
{
|
||||||
|
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
|
||||||
|
|
||||||
|
assert(bl1_mem_layout != NULL);
|
||||||
|
assert(bl2_mem_layout != NULL);
|
||||||
|
|
||||||
|
/* Check that BL1's memory is lying outside of the free memory */
|
||||||
|
assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) ||
|
||||||
|
(BL1_RAM_BASE >= (bl1_mem_layout->free_base +
|
||||||
|
bl1_mem_layout->free_size)));
|
||||||
|
|
||||||
|
/* Remove BL1 RW data from the scope of memory visible to BL2 */
|
||||||
|
*bl2_mem_layout = *bl1_mem_layout;
|
||||||
|
reserve_mem(&bl2_mem_layout->total_base,
|
||||||
|
&bl2_mem_layout->total_size,
|
||||||
|
BL1_RAM_BASE,
|
||||||
|
bl1_size);
|
||||||
|
|
||||||
|
flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Before calling this function BL2 is loaded in memory and its entrypoint
|
||||||
|
* is set by load_image. This is a placeholder for the platform to change
|
||||||
|
* the entrypoint of BL2 and set SPSR and security state.
|
||||||
|
* On ARM standard platforms we only set the security state of the entrypoint
|
||||||
|
******************************************************************************/
|
||||||
|
void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image,
|
||||||
|
entry_point_info_t *bl2_ep)
|
||||||
|
{
|
||||||
|
SET_SECURITY_STATE(bl2_ep->h.attr, SECURE);
|
||||||
|
bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||||
|
}
|
|
@ -0,0 +1,327 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <arch_helpers.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <libfdt.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include "qemu_private.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 2 constants identify the extents of the code & RO data region.
|
||||||
|
* These addresses are used by the MMU setup code and therefore they must be
|
||||||
|
* page-aligned. It is the responsibility of the linker script to ensure that
|
||||||
|
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define BL2_RO_BASE (unsigned long)(&__RO_START__)
|
||||||
|
#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 2 constants identify the extents of the coherent memory region.
|
||||||
|
* These addresses are used by the MMU setup code and therefore they must be
|
||||||
|
* page-aligned. It is the responsibility of the linker script to ensure that
|
||||||
|
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
|
||||||
|
* page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
|
||||||
|
#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This structure represents the superset of information that is passed to
|
||||||
|
* BL3-1, e.g. while passing control to it from BL2, bl31_params
|
||||||
|
* and other platform specific params
|
||||||
|
******************************************************************************/
|
||||||
|
typedef struct bl2_to_bl31_params_mem {
|
||||||
|
bl31_params_t bl31_params;
|
||||||
|
image_info_t bl31_image_info;
|
||||||
|
image_info_t bl32_image_info;
|
||||||
|
image_info_t bl33_image_info;
|
||||||
|
entry_point_info_t bl33_ep_info;
|
||||||
|
entry_point_info_t bl32_ep_info;
|
||||||
|
entry_point_info_t bl31_ep_info;
|
||||||
|
} bl2_to_bl31_params_mem_t;
|
||||||
|
|
||||||
|
|
||||||
|
static bl2_to_bl31_params_mem_t bl31_params_mem;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Data structure which holds the extents of the trusted SRAM for BL2 */
|
||||||
|
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
|
||||||
|
|
||||||
|
meminfo_t *bl2_plat_sec_mem_layout(void)
|
||||||
|
{
|
||||||
|
return &bl2_tzram_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function assigns a pointer to the memory that the platform has kept
|
||||||
|
* aside to pass platform specific and trusted firmware related information
|
||||||
|
* to BL31. This memory is allocated by allocating memory to
|
||||||
|
* bl2_to_bl31_params_mem_t structure which is a superset of all the
|
||||||
|
* structure whose information is passed to BL31
|
||||||
|
* NOTE: This function should be called only once and should be done
|
||||||
|
* before generating params to BL31
|
||||||
|
******************************************************************************/
|
||||||
|
bl31_params_t *bl2_plat_get_bl31_params(void)
|
||||||
|
{
|
||||||
|
bl31_params_t *bl2_to_bl31_params;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise the memory for all the arguments that needs to
|
||||||
|
* be passed to BL3-1
|
||||||
|
*/
|
||||||
|
memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
|
||||||
|
|
||||||
|
/* Assign memory for TF related information */
|
||||||
|
bl2_to_bl31_params = &bl31_params_mem.bl31_params;
|
||||||
|
SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
|
||||||
|
|
||||||
|
/* Fill BL3-1 related information */
|
||||||
|
bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
|
||||||
|
SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
|
||||||
|
VERSION_1, 0);
|
||||||
|
|
||||||
|
/* Fill BL3-2 related information */
|
||||||
|
bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
|
||||||
|
SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
|
||||||
|
VERSION_1, 0);
|
||||||
|
bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
|
||||||
|
SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
|
||||||
|
VERSION_1, 0);
|
||||||
|
|
||||||
|
/* Fill BL3-3 related information */
|
||||||
|
bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
|
||||||
|
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
|
||||||
|
PARAM_EP, VERSION_1, 0);
|
||||||
|
|
||||||
|
/* BL3-3 expects to receive the primary CPU MPID (through x0) */
|
||||||
|
bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
|
||||||
|
|
||||||
|
bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
|
||||||
|
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
|
||||||
|
VERSION_1, 0);
|
||||||
|
|
||||||
|
return bl2_to_bl31_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush the TF params and the TF plat params */
|
||||||
|
void bl2_plat_flush_bl31_params(void)
|
||||||
|
{
|
||||||
|
flush_dcache_range((unsigned long)&bl31_params_mem,
|
||||||
|
sizeof(bl2_to_bl31_params_mem_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function returns a pointer to the shared memory that the platform
|
||||||
|
* has kept to point to entry point information of BL31 to BL2
|
||||||
|
******************************************************************************/
|
||||||
|
struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
bl31_params_mem.bl31_ep_info.args.arg1 = QEMU_BL31_PLAT_PARAM_VAL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &bl31_params_mem.bl31_ep_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void bl2_early_platform_setup(meminfo_t *mem_layout)
|
||||||
|
{
|
||||||
|
/* Initialize the console to provide early debug support */
|
||||||
|
console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
|
||||||
|
PLAT_QEMU_CONSOLE_BAUDRATE);
|
||||||
|
|
||||||
|
/* Setup the BL2 memory layout */
|
||||||
|
bl2_tzram_layout = *mem_layout;
|
||||||
|
|
||||||
|
plat_qemu_io_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void security_setup(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is where a TrustZone address space controller and other
|
||||||
|
* security related peripherals, would be configured.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_dt(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
void *fdt = (void *)(uintptr_t)PLAT_QEMU_DT_BASE;
|
||||||
|
|
||||||
|
ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dt_add_psci_node(fdt)) {
|
||||||
|
ERROR("Failed to add PSCI Device Tree node\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dt_add_psci_cpu_enable_methods(fdt)) {
|
||||||
|
ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fdt_pack(fdt);
|
||||||
|
if (ret < 0)
|
||||||
|
ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bl2_platform_setup(void)
|
||||||
|
{
|
||||||
|
security_setup();
|
||||||
|
update_dt();
|
||||||
|
|
||||||
|
/* TODO Initialize timer */
|
||||||
|
}
|
||||||
|
|
||||||
|
void bl2_plat_arch_setup(void)
|
||||||
|
{
|
||||||
|
qemu_configure_mmu_el1(bl2_tzram_layout.total_base,
|
||||||
|
bl2_tzram_layout.total_size,
|
||||||
|
BL2_RO_BASE, BL2_RO_LIMIT,
|
||||||
|
BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Gets SPSR for BL32 entry
|
||||||
|
******************************************************************************/
|
||||||
|
static uint32_t qemu_get_spsr_for_bl32_entry(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The Secure Payload Dispatcher service is responsible for
|
||||||
|
* setting the SPSR prior to entry into the BL3-2 image.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Gets SPSR for BL33 entry
|
||||||
|
******************************************************************************/
|
||||||
|
static uint32_t qemu_get_spsr_for_bl33_entry(void)
|
||||||
|
{
|
||||||
|
unsigned long el_status;
|
||||||
|
unsigned int mode;
|
||||||
|
uint32_t spsr;
|
||||||
|
|
||||||
|
/* Figure out what mode we enter the non-secure world in */
|
||||||
|
el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
|
||||||
|
el_status &= ID_AA64PFR0_ELX_MASK;
|
||||||
|
|
||||||
|
mode = (el_status) ? MODE_EL2 : MODE_EL1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Consider the possibility of specifying the SPSR in
|
||||||
|
* the FIP ToC and allowing the platform to have a say as
|
||||||
|
* well.
|
||||||
|
*/
|
||||||
|
spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||||
|
return spsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Before calling this function BL3-1 is loaded in memory and its entrypoint
|
||||||
|
* is set by load_image. This is a placeholder for the platform to change
|
||||||
|
* the entrypoint of BL3-1 and set SPSR and security state.
|
||||||
|
* On ARM standard platforms we only set the security state of the entrypoint
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info,
|
||||||
|
entry_point_info_t *bl31_ep_info)
|
||||||
|
{
|
||||||
|
SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
|
||||||
|
bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||||
|
DISABLE_ALL_EXCEPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Before calling this function BL3-2 is loaded in memory and its entrypoint
|
||||||
|
* is set by load_image. This is a placeholder for the platform to change
|
||||||
|
* the entrypoint of BL3-2 and set SPSR and security state.
|
||||||
|
* On ARM standard platforms we only set the security state of the entrypoint
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
|
||||||
|
entry_point_info_t *bl32_ep_info)
|
||||||
|
{
|
||||||
|
SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
|
||||||
|
bl32_ep_info->spsr = qemu_get_spsr_for_bl32_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Before calling this function BL3-3 is loaded in memory and its entrypoint
|
||||||
|
* is set by load_image. This is a placeholder for the platform to change
|
||||||
|
* the entrypoint of BL3-3 and set SPSR and security state.
|
||||||
|
* On ARM standard platforms we only set the security state of the entrypoint
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_plat_set_bl33_ep_info(image_info_t *image,
|
||||||
|
entry_point_info_t *bl33_ep_info)
|
||||||
|
{
|
||||||
|
|
||||||
|
SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
|
||||||
|
bl33_ep_info->spsr = qemu_get_spsr_for_bl33_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Populate the extents of memory available for loading BL32
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Populate the extents of memory available for loading BL32.
|
||||||
|
*/
|
||||||
|
bl32_meminfo->total_base = BL32_BASE;
|
||||||
|
bl32_meminfo->free_base = BL32_BASE;
|
||||||
|
bl32_meminfo->total_size = (BL32_MEM_BASE + BL32_MEM_SIZE) - BL32_BASE;
|
||||||
|
bl32_meminfo->free_size = (BL32_MEM_BASE + BL32_MEM_SIZE) - BL32_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Populate the extents of memory available for loading BL33
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
|
||||||
|
{
|
||||||
|
bl33_meminfo->total_base = NS_DRAM0_BASE;
|
||||||
|
bl33_meminfo->total_size = NS_DRAM0_SIZE;
|
||||||
|
bl33_meminfo->free_base = NS_DRAM0_BASE;
|
||||||
|
bl33_meminfo->free_size = NS_DRAM0_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long plat_get_ns_image_entrypoint(void)
|
||||||
|
{
|
||||||
|
return NS_IMAGE_OFFSET;
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <assert.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <gicv2.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include "qemu_private.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 3 constants identify the extents of the code, RO data region and the
|
||||||
|
* limit of the BL3-1 image. These addresses are used by the MMU setup code and
|
||||||
|
* therefore they must be page-aligned. It is the responsibility of the linker
|
||||||
|
* script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
|
||||||
|
* refer to page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define BL31_RO_BASE (unsigned long)(&__RO_START__)
|
||||||
|
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
|
||||||
|
#define BL31_END (unsigned long)(&__BL31_END__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 2 constants identify the extents of the coherent memory region.
|
||||||
|
* These addresses are used by the MMU setup code and therefore they must be
|
||||||
|
* page-aligned. It is the responsibility of the linker script to ensure that
|
||||||
|
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
|
||||||
|
* refer to page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
|
||||||
|
#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Placeholder variables for copying the arguments that have been passed to
|
||||||
|
* BL3-1 from BL2.
|
||||||
|
*/
|
||||||
|
static entry_point_info_t bl32_image_ep_info;
|
||||||
|
static entry_point_info_t bl33_image_ep_info;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Perform any BL3-1 early platform setup. Here is an opportunity to copy
|
||||||
|
* parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
|
||||||
|
* they are lost (potentially). This needs to be done before the MMU is
|
||||||
|
* initialized so that the memory layout can be used while creating page
|
||||||
|
* tables. BL2 has flushed this information to memory, so we are guaranteed
|
||||||
|
* to pick up good data.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl31_early_platform_setup(bl31_params_t *from_bl2,
|
||||||
|
void *plat_params_from_bl2)
|
||||||
|
{
|
||||||
|
/* Initialize the console to provide early debug support */
|
||||||
|
console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
|
||||||
|
PLAT_QEMU_CONSOLE_BAUDRATE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check params passed from BL2 should not be NULL,
|
||||||
|
*/
|
||||||
|
assert(from_bl2 != NULL);
|
||||||
|
assert(from_bl2->h.type == PARAM_BL31);
|
||||||
|
assert(from_bl2->h.version >= VERSION_1);
|
||||||
|
/*
|
||||||
|
* In debug builds, we pass a special value in 'plat_params_from_bl2'
|
||||||
|
* to verify platform parameters from BL2 to BL3-1.
|
||||||
|
* In release builds, it's not used.
|
||||||
|
*/
|
||||||
|
assert(((unsigned long long)plat_params_from_bl2) ==
|
||||||
|
QEMU_BL31_PLAT_PARAM_VAL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy BL3-2 (if populated by BL2) and BL3-3 entry point information.
|
||||||
|
* They are stored in Secure RAM, in BL2's address space.
|
||||||
|
*/
|
||||||
|
if (from_bl2->bl32_ep_info)
|
||||||
|
bl32_image_ep_info = *from_bl2->bl32_ep_info;
|
||||||
|
bl33_image_ep_info = *from_bl2->bl33_ep_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bl31_plat_arch_setup(void)
|
||||||
|
{
|
||||||
|
qemu_configure_mmu_el3(BL31_RO_BASE, (BL31_END - BL31_RO_BASE),
|
||||||
|
BL31_RO_BASE, BL31_RO_LIMIT,
|
||||||
|
BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned int irq_sec_array[] = {
|
||||||
|
QEMU_IRQ_SEC_SGI_0,
|
||||||
|
QEMU_IRQ_SEC_SGI_1,
|
||||||
|
QEMU_IRQ_SEC_SGI_2,
|
||||||
|
QEMU_IRQ_SEC_SGI_3,
|
||||||
|
QEMU_IRQ_SEC_SGI_4,
|
||||||
|
QEMU_IRQ_SEC_SGI_5,
|
||||||
|
QEMU_IRQ_SEC_SGI_6,
|
||||||
|
QEMU_IRQ_SEC_SGI_7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct gicv2_driver_data plat_gicv2_driver_data = {
|
||||||
|
.gicd_base = GICD_BASE,
|
||||||
|
.gicc_base = GICC_BASE,
|
||||||
|
.g0_interrupt_num = ARRAY_SIZE(irq_sec_array),
|
||||||
|
.g0_interrupt_array = irq_sec_array,
|
||||||
|
};
|
||||||
|
|
||||||
|
void bl31_platform_setup(void)
|
||||||
|
{
|
||||||
|
/* Initialize the gic cpu and distributor interfaces */
|
||||||
|
gicv2_driver_init(&plat_gicv2_driver_data);
|
||||||
|
gicv2_distif_init();
|
||||||
|
gicv2_pcpu_distif_init();
|
||||||
|
gicv2_cpuif_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int plat_get_syscnt_freq2(void)
|
||||||
|
{
|
||||||
|
return SYS_COUNTER_FREQ_IN_TICKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Return a pointer to the 'entry_point_info' structure of the next image
|
||||||
|
* for the security state specified. BL3-3 corresponds to the non-secure
|
||||||
|
* image type while BL3-2 corresponds to the secure image type. A NULL
|
||||||
|
* pointer is returned if the image does not exist.
|
||||||
|
******************************************************************************/
|
||||||
|
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||||
|
{
|
||||||
|
entry_point_info_t *next_image_info;
|
||||||
|
|
||||||
|
assert(sec_state_is_valid(type));
|
||||||
|
next_image_info = (type == NON_SECURE)
|
||||||
|
? &bl33_image_ep_info : &bl32_image_ep_info;
|
||||||
|
/*
|
||||||
|
* None of the images on the ARM development platforms can have 0x0
|
||||||
|
* as the entrypoint
|
||||||
|
*/
|
||||||
|
if (next_image_info->pc)
|
||||||
|
return next_image_info;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <arch_helpers.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include "qemu_private.h"
|
||||||
|
#include <xlat_tables.h>
|
||||||
|
|
||||||
|
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
|
||||||
|
DEVICE0_SIZE, \
|
||||||
|
MT_DEVICE | MT_RW | MT_SECURE)
|
||||||
|
|
||||||
|
#ifdef DEVICE1_BASE
|
||||||
|
#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
|
||||||
|
DEVICE1_SIZE, \
|
||||||
|
MT_DEVICE | MT_RW | MT_SECURE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEVICE2_BASE
|
||||||
|
#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \
|
||||||
|
DEVICE2_SIZE, \
|
||||||
|
MT_DEVICE | MT_RO | MT_SECURE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \
|
||||||
|
SHARED_RAM_SIZE, \
|
||||||
|
MT_DEVICE | MT_RW | MT_SECURE)
|
||||||
|
|
||||||
|
#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \
|
||||||
|
MT_MEMORY | MT_RW | MT_SECURE)
|
||||||
|
|
||||||
|
#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \
|
||||||
|
MT_MEMORY | MT_RW | MT_NS)
|
||||||
|
|
||||||
|
#define MAP_FLASH0 MAP_REGION_FLAT(QEMU_FLASH0_BASE, QEMU_FLASH0_SIZE, \
|
||||||
|
MT_MEMORY | MT_RO | MT_SECURE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table of regions for various BL stages to map using the MMU.
|
||||||
|
* This doesn't include TZRAM as the 'mem_layout' argument passed to
|
||||||
|
* arm_configure_mmu_elx() will give the available subset of that,
|
||||||
|
*/
|
||||||
|
#if IMAGE_BL1
|
||||||
|
static const mmap_region_t plat_qemu_mmap[] = {
|
||||||
|
MAP_FLASH0,
|
||||||
|
MAP_SHARED_RAM,
|
||||||
|
MAP_DEVICE0,
|
||||||
|
#ifdef MAP_DEVICE1
|
||||||
|
MAP_DEVICE1,
|
||||||
|
#endif
|
||||||
|
#ifdef MAP_DEVICE2
|
||||||
|
MAP_DEVICE2,
|
||||||
|
#endif
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#if IMAGE_BL2
|
||||||
|
static const mmap_region_t plat_qemu_mmap[] = {
|
||||||
|
MAP_FLASH0,
|
||||||
|
MAP_SHARED_RAM,
|
||||||
|
MAP_DEVICE0,
|
||||||
|
#ifdef MAP_DEVICE1
|
||||||
|
MAP_DEVICE1,
|
||||||
|
#endif
|
||||||
|
#ifdef MAP_DEVICE2
|
||||||
|
MAP_DEVICE2,
|
||||||
|
#endif
|
||||||
|
MAP_NS_DRAM0,
|
||||||
|
MAP_BL32_MEM,
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#if IMAGE_BL31
|
||||||
|
static const mmap_region_t plat_qemu_mmap[] = {
|
||||||
|
MAP_SHARED_RAM,
|
||||||
|
MAP_DEVICE0,
|
||||||
|
#ifdef MAP_DEVICE1
|
||||||
|
MAP_DEVICE1,
|
||||||
|
#endif
|
||||||
|
MAP_BL32_MEM,
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Macro generating the code for the function setting up the pagetables as per
|
||||||
|
* the platform memory map & initialize the mmu, for the given exception level
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#define DEFINE_CONFIGURE_MMU_EL(_el) \
|
||||||
|
void qemu_configure_mmu_el##_el(unsigned long total_base, \
|
||||||
|
unsigned long total_size, \
|
||||||
|
unsigned long ro_start, \
|
||||||
|
unsigned long ro_limit, \
|
||||||
|
unsigned long coh_start, \
|
||||||
|
unsigned long coh_limit) \
|
||||||
|
{ \
|
||||||
|
mmap_add_region(total_base, total_base, \
|
||||||
|
total_size, \
|
||||||
|
MT_MEMORY | MT_RW | MT_SECURE); \
|
||||||
|
mmap_add_region(ro_start, ro_start, \
|
||||||
|
ro_limit - ro_start, \
|
||||||
|
MT_MEMORY | MT_RO | MT_SECURE); \
|
||||||
|
mmap_add_region(coh_start, coh_start, \
|
||||||
|
coh_limit - coh_start, \
|
||||||
|
MT_DEVICE | MT_RW | MT_SECURE); \
|
||||||
|
mmap_add(plat_qemu_mmap); \
|
||||||
|
init_xlat_tables(); \
|
||||||
|
\
|
||||||
|
enable_mmu_el##_el(0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define EL1 and EL3 variants of the function initialising the MMU */
|
||||||
|
DEFINE_CONFIGURE_MMU_EL(1)
|
||||||
|
DEFINE_CONFIGURE_MMU_EL(3)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <assert.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
#include <gicv2.h>
|
||||||
|
#include <interrupt_mgmt.h>
|
||||||
|
|
||||||
|
uint32_t plat_ic_get_pending_interrupt_id(void)
|
||||||
|
{
|
||||||
|
return gicv2_get_pending_interrupt_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t plat_ic_get_pending_interrupt_type(void)
|
||||||
|
{
|
||||||
|
return gicv2_get_pending_interrupt_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t plat_ic_acknowledge_interrupt(void)
|
||||||
|
{
|
||||||
|
return gicv2_acknowledge_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t plat_ic_get_interrupt_type(uint32_t id)
|
||||||
|
{
|
||||||
|
uint32_t group;
|
||||||
|
|
||||||
|
group = gicv2_get_interrupt_group(id);
|
||||||
|
|
||||||
|
/* Assume that all secure interrupts are S-EL1 interrupts */
|
||||||
|
if (!group)
|
||||||
|
return INTR_TYPE_S_EL1;
|
||||||
|
else
|
||||||
|
return INTR_TYPE_NS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void plat_ic_end_of_interrupt(uint32_t id)
|
||||||
|
{
|
||||||
|
gicv2_end_of_interrupt(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t plat_interrupt_type_to_line(uint32_t type,
|
||||||
|
uint32_t security_state)
|
||||||
|
{
|
||||||
|
assert(type == INTR_TYPE_S_EL1 ||
|
||||||
|
type == INTR_TYPE_EL3 ||
|
||||||
|
type == INTR_TYPE_NS);
|
||||||
|
|
||||||
|
assert(sec_state_is_valid(security_state));
|
||||||
|
|
||||||
|
/* Non-secure interrupts are signalled on the IRQ line always */
|
||||||
|
if (type == INTR_TYPE_NS)
|
||||||
|
return __builtin_ctz(SCR_IRQ_BIT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secure interrupts are signalled using the IRQ line if the FIQ_EN
|
||||||
|
* bit is not set else they are signalled using the FIQ line.
|
||||||
|
*/
|
||||||
|
if (gicv2_is_fiq_enabled())
|
||||||
|
return __builtin_ctz(SCR_FIQ_BIT);
|
||||||
|
else
|
||||||
|
return __builtin_ctz(SCR_IRQ_BIT);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,378 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <assert.h>
|
||||||
|
#include <bl_common.h> /* For ARRAY_SIZE */
|
||||||
|
#include <debug.h>
|
||||||
|
#include <firmware_image_package.h>
|
||||||
|
#include <io_driver.h>
|
||||||
|
#include <io_fip.h>
|
||||||
|
#include <io_memmap.h>
|
||||||
|
#include <io_semihosting.h>
|
||||||
|
#include <io_storage.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include <semihosting.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Semihosting filenames */
|
||||||
|
#define BL2_IMAGE_NAME "bl2.bin"
|
||||||
|
#define BL31_IMAGE_NAME "bl31.bin"
|
||||||
|
#define BL32_IMAGE_NAME "bl32.bin"
|
||||||
|
#define BL33_IMAGE_NAME "bl33.bin"
|
||||||
|
|
||||||
|
#if TRUSTED_BOARD_BOOT
|
||||||
|
#define BL2_CERT_NAME "bl2.crt"
|
||||||
|
#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
|
||||||
|
#define BL31_KEY_CERT_NAME "bl31_key.crt"
|
||||||
|
#define BL32_KEY_CERT_NAME "bl32_key.crt"
|
||||||
|
#define BL33_KEY_CERT_NAME "bl33_key.crt"
|
||||||
|
#define BL31_CERT_NAME "bl31.crt"
|
||||||
|
#define BL32_CERT_NAME "bl32.crt"
|
||||||
|
#define BL33_CERT_NAME "bl33.crt"
|
||||||
|
#endif /* TRUSTED_BOARD_BOOT */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* IO devices */
|
||||||
|
static const io_dev_connector_t *fip_dev_con;
|
||||||
|
static uintptr_t fip_dev_handle;
|
||||||
|
static const io_dev_connector_t *memmap_dev_con;
|
||||||
|
static uintptr_t memmap_dev_handle;
|
||||||
|
static const io_dev_connector_t *sh_dev_con;
|
||||||
|
static uintptr_t sh_dev_handle;
|
||||||
|
|
||||||
|
static const io_block_spec_t fip_block_spec = {
|
||||||
|
.offset = PLAT_QEMU_FIP_BASE,
|
||||||
|
.length = PLAT_QEMU_FIP_MAX_SIZE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl2_uuid_spec = {
|
||||||
|
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl31_uuid_spec = {
|
||||||
|
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl32_uuid_spec = {
|
||||||
|
.uuid = UUID_SECURE_PAYLOAD_BL32,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl33_uuid_spec = {
|
||||||
|
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if TRUSTED_BOARD_BOOT
|
||||||
|
static const io_uuid_spec_t bl2_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_TRUSTED_KEY_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl31_key_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl32_key_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl33_key_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl31_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl32_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_SECURE_PAYLOAD_BL32_CERT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const io_uuid_spec_t bl33_cert_uuid_spec = {
|
||||||
|
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
|
||||||
|
};
|
||||||
|
#endif /* TRUSTED_BOARD_BOOT */
|
||||||
|
|
||||||
|
static const io_file_spec_t sh_file_spec[] = {
|
||||||
|
[BL2_IMAGE_ID] = {
|
||||||
|
.path = BL2_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL31_IMAGE_ID] = {
|
||||||
|
.path = BL31_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL32_IMAGE_ID] = {
|
||||||
|
.path = BL32_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL33_IMAGE_ID] = {
|
||||||
|
.path = BL33_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
#if TRUSTED_BOARD_BOOT
|
||||||
|
[BL2_CERT_ID] = {
|
||||||
|
.path = BL2_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[TRUSTED_KEY_CERT_ID] = {
|
||||||
|
.path = TRUSTED_KEY_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL31_KEY_CERT_ID] = {
|
||||||
|
.path = BL31_KEY_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL32_KEY_CERT_ID] = {
|
||||||
|
.path = BL32_KEY_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL33_KEY_CERT_ID] = {
|
||||||
|
.path = BL33_KEY_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL31_CERT_ID] = {
|
||||||
|
.path = BL31_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL32_CERT_ID] = {
|
||||||
|
.path = BL32_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
[BL33_CERT_ID] = {
|
||||||
|
.path = BL33_CERT_NAME,
|
||||||
|
.mode = FOPEN_MODE_RB
|
||||||
|
},
|
||||||
|
#endif /* TRUSTED_BOARD_BOOT */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int open_fip(const uintptr_t spec);
|
||||||
|
static int open_memmap(const uintptr_t spec);
|
||||||
|
|
||||||
|
struct plat_io_policy {
|
||||||
|
uintptr_t *dev_handle;
|
||||||
|
uintptr_t image_spec;
|
||||||
|
int (*check)(const uintptr_t spec);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* By default, ARM platforms load images from the FIP */
|
||||||
|
static const struct plat_io_policy policies[] = {
|
||||||
|
[FIP_IMAGE_ID] = {
|
||||||
|
&memmap_dev_handle,
|
||||||
|
(uintptr_t)&fip_block_spec,
|
||||||
|
open_memmap
|
||||||
|
},
|
||||||
|
[BL2_IMAGE_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl2_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL31_IMAGE_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl31_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL32_IMAGE_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl32_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL33_IMAGE_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl33_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
#if TRUSTED_BOARD_BOOT
|
||||||
|
[BL2_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl2_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[TRUSTED_KEY_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&trusted_key_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL31_KEY_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl31_key_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL32_KEY_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl32_key_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL33_KEY_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl33_key_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL31_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl31_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL32_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl32_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
[BL33_CERT_ID] = {
|
||||||
|
&fip_dev_handle,
|
||||||
|
(uintptr_t)&bl33_cert_uuid_spec,
|
||||||
|
open_fip
|
||||||
|
},
|
||||||
|
#endif /* TRUSTED_BOARD_BOOT */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int open_fip(const uintptr_t spec)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
uintptr_t local_image_handle;
|
||||||
|
|
||||||
|
/* See if a Firmware Image Package is available */
|
||||||
|
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
|
||||||
|
if (result == 0) {
|
||||||
|
result = io_open(fip_dev_handle, spec, &local_image_handle);
|
||||||
|
if (result == 0) {
|
||||||
|
VERBOSE("Using FIP\n");
|
||||||
|
io_close(local_image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_memmap(const uintptr_t spec)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
uintptr_t local_image_handle;
|
||||||
|
|
||||||
|
result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
|
||||||
|
if (result == 0) {
|
||||||
|
result = io_open(memmap_dev_handle, spec, &local_image_handle);
|
||||||
|
if (result == 0) {
|
||||||
|
VERBOSE("Using Memmap\n");
|
||||||
|
io_close(local_image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_semihosting(const uintptr_t spec)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
uintptr_t local_image_handle;
|
||||||
|
|
||||||
|
/* See if the file exists on semi-hosting.*/
|
||||||
|
result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
|
||||||
|
if (result == 0) {
|
||||||
|
result = io_open(sh_dev_handle, spec, &local_image_handle);
|
||||||
|
if (result == 0) {
|
||||||
|
VERBOSE("Using Semi-hosting IO\n");
|
||||||
|
io_close(local_image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plat_qemu_io_setup(void)
|
||||||
|
{
|
||||||
|
int io_result;
|
||||||
|
|
||||||
|
io_result = register_io_dev_fip(&fip_dev_con);
|
||||||
|
assert(io_result == 0);
|
||||||
|
|
||||||
|
io_result = register_io_dev_memmap(&memmap_dev_con);
|
||||||
|
assert(io_result == 0);
|
||||||
|
|
||||||
|
/* Open connections to devices and cache the handles */
|
||||||
|
io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
|
||||||
|
&fip_dev_handle);
|
||||||
|
assert(io_result == 0);
|
||||||
|
|
||||||
|
io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
|
||||||
|
&memmap_dev_handle);
|
||||||
|
assert(io_result == 0);
|
||||||
|
|
||||||
|
/* Register the additional IO devices on this platform */
|
||||||
|
io_result = register_io_dev_sh(&sh_dev_con);
|
||||||
|
assert(io_result == 0);
|
||||||
|
|
||||||
|
/* Open connections to devices and cache the handles */
|
||||||
|
io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
|
||||||
|
assert(io_result == 0);
|
||||||
|
|
||||||
|
/* Ignore improbable errors in release builds */
|
||||||
|
(void)io_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
|
||||||
|
uintptr_t *image_spec)
|
||||||
|
{
|
||||||
|
int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
*dev_handle = sh_dev_handle;
|
||||||
|
*image_spec = (uintptr_t)&sh_file_spec[image_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return an IO device handle and specification which can be used to access
|
||||||
|
* an image. Use this to enforce platform load policy
|
||||||
|
*/
|
||||||
|
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
|
||||||
|
uintptr_t *image_spec)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
const struct plat_io_policy *policy;
|
||||||
|
|
||||||
|
assert(image_id < ARRAY_SIZE(policies));
|
||||||
|
|
||||||
|
policy = &policies[image_id];
|
||||||
|
result = policy->check(policy->image_spec);
|
||||||
|
if (result == 0) {
|
||||||
|
*image_spec = policy->image_spec;
|
||||||
|
*dev_handle = *(policy->dev_handle);
|
||||||
|
} else {
|
||||||
|
VERBOSE("Trying alternative IO\n");
|
||||||
|
result = get_alt_image_source(image_id, dev_handle, image_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <arch_helpers.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <gicv2.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <psci.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The secure entry point to be used on warm reset.
|
||||||
|
*/
|
||||||
|
static unsigned long secure_entrypoint;
|
||||||
|
|
||||||
|
/* Make composite power state parameter till power level 0 */
|
||||||
|
#if PSCI_EXTENDED_STATE_ID
|
||||||
|
|
||||||
|
#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
|
||||||
|
(((lvl0_state) << PSTATE_ID_SHIFT) | \
|
||||||
|
((type) << PSTATE_TYPE_SHIFT))
|
||||||
|
#else
|
||||||
|
#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
|
||||||
|
(((lvl0_state) << PSTATE_ID_SHIFT) | \
|
||||||
|
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
|
||||||
|
((type) << PSTATE_TYPE_SHIFT))
|
||||||
|
#endif /* PSCI_EXTENDED_STATE_ID */
|
||||||
|
|
||||||
|
|
||||||
|
#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
|
||||||
|
(((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
|
||||||
|
qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The table storing the valid idle power states. Ensure that the
|
||||||
|
* array entries are populated in ascending order of state-id to
|
||||||
|
* enable us to use binary search during power state validation.
|
||||||
|
* The table must be terminated by a NULL entry.
|
||||||
|
*/
|
||||||
|
static const unsigned int qemu_pm_idle_states[] = {
|
||||||
|
/* State-id - 0x01 */
|
||||||
|
qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
|
||||||
|
MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
|
||||||
|
/* State-id - 0x02 */
|
||||||
|
qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
|
||||||
|
MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
|
||||||
|
/* State-id - 0x22 */
|
||||||
|
qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
|
||||||
|
MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called to check the validity of the power state
|
||||||
|
* parameter. The power state parameter has to be a composite power state.
|
||||||
|
******************************************************************************/
|
||||||
|
static int qemu_validate_power_state(unsigned int power_state,
|
||||||
|
psci_power_state_t *req_state)
|
||||||
|
{
|
||||||
|
unsigned int state_id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(req_state);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently we are using a linear search for finding the matching
|
||||||
|
* entry in the idle power state array. This can be made a binary
|
||||||
|
* search if the number of entries justify the additional complexity.
|
||||||
|
*/
|
||||||
|
for (i = 0; !!qemu_pm_idle_states[i]; i++) {
|
||||||
|
if (power_state == qemu_pm_idle_states[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return error if entry not found in the idle state array */
|
||||||
|
if (!qemu_pm_idle_states[i])
|
||||||
|
return PSCI_E_INVALID_PARAMS;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
state_id = psci_get_pstate_id(power_state);
|
||||||
|
|
||||||
|
/* Parse the State ID and populate the state info parameter */
|
||||||
|
while (state_id) {
|
||||||
|
req_state->pwr_domain_state[i++] = state_id &
|
||||||
|
PLAT_LOCAL_PSTATE_MASK;
|
||||||
|
state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PSCI_E_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called to check the validity of the non secure
|
||||||
|
* entrypoint.
|
||||||
|
******************************************************************************/
|
||||||
|
static int qemu_validate_ns_entrypoint(uintptr_t entrypoint)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check if the non secure entrypoint lies within the non
|
||||||
|
* secure DRAM.
|
||||||
|
*/
|
||||||
|
if ((entrypoint >= NS_DRAM0_BASE) &&
|
||||||
|
(entrypoint < (NS_DRAM0_BASE + NS_DRAM0_SIZE)))
|
||||||
|
return PSCI_E_SUCCESS;
|
||||||
|
return PSCI_E_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called when a CPU is about to enter standby.
|
||||||
|
******************************************************************************/
|
||||||
|
static void qemu_cpu_standby(plat_local_state_t cpu_state)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(cpu_state == PLAT_LOCAL_STATE_RET);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enter standby state
|
||||||
|
* dsb is good practice before using wfi to enter low power states
|
||||||
|
*/
|
||||||
|
dsb();
|
||||||
|
wfi();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called when a power domain is about to be turned on. The
|
||||||
|
* mpidr determines the CPU to be turned on.
|
||||||
|
******************************************************************************/
|
||||||
|
static int qemu_pwr_domain_on(u_register_t mpidr)
|
||||||
|
{
|
||||||
|
int rc = PSCI_E_SUCCESS;
|
||||||
|
unsigned pos = plat_core_pos_by_mpidr(mpidr);
|
||||||
|
uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE;
|
||||||
|
|
||||||
|
hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO;
|
||||||
|
sev();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called when a power domain is about to be turned off. The
|
||||||
|
* target_state encodes the power state that each level should transition to.
|
||||||
|
******************************************************************************/
|
||||||
|
void qemu_pwr_domain_off(const psci_power_state_t *target_state)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called when a power domain is about to be suspended. The
|
||||||
|
* target_state encodes the power state that each level should transition to.
|
||||||
|
******************************************************************************/
|
||||||
|
void qemu_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called when a power domain has just been powered on after
|
||||||
|
* being turned off earlier. The target_state encodes the low power state that
|
||||||
|
* each level has woken up from.
|
||||||
|
******************************************************************************/
|
||||||
|
void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||||
|
{
|
||||||
|
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||||
|
PLAT_LOCAL_STATE_OFF);
|
||||||
|
|
||||||
|
/* TODO: This setup is needed only after a cold boot */
|
||||||
|
gicv2_pcpu_distif_init();
|
||||||
|
|
||||||
|
/* Enable the gic cpu interface */
|
||||||
|
gicv2_cpuif_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handler called when a power domain has just been powered on after
|
||||||
|
* having been suspended earlier. The target_state encodes the low power state
|
||||||
|
* that each level has woken up from.
|
||||||
|
******************************************************************************/
|
||||||
|
void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform handlers to shutdown/reboot the system
|
||||||
|
******************************************************************************/
|
||||||
|
static void __dead2 qemu_system_off(void)
|
||||||
|
{
|
||||||
|
ERROR("QEMU System Off: operation not handled.\n");
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __dead2 qemu_system_reset(void)
|
||||||
|
{
|
||||||
|
ERROR("QEMU System Reset: operation not handled.\n");
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const plat_psci_ops_t plat_qemu_psci_pm_ops = {
|
||||||
|
.cpu_standby = qemu_cpu_standby,
|
||||||
|
.pwr_domain_on = qemu_pwr_domain_on,
|
||||||
|
.pwr_domain_off = qemu_pwr_domain_off,
|
||||||
|
.pwr_domain_suspend = qemu_pwr_domain_suspend,
|
||||||
|
.pwr_domain_on_finish = qemu_pwr_domain_on_finish,
|
||||||
|
.pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish,
|
||||||
|
.system_off = qemu_system_off,
|
||||||
|
.system_reset = qemu_system_reset,
|
||||||
|
.validate_power_state = qemu_validate_power_state,
|
||||||
|
.validate_ns_entrypoint = qemu_validate_ns_entrypoint
|
||||||
|
};
|
||||||
|
|
||||||
|
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||||
|
const plat_psci_ops_t **psci_ops)
|
||||||
|
{
|
||||||
|
uintptr_t *mailbox = (void *) PLAT_QEMU_TRUSTED_MAILBOX_BASE;
|
||||||
|
|
||||||
|
*mailbox = sec_entrypoint;
|
||||||
|
secure_entrypoint = (unsigned long) sec_entrypoint;
|
||||||
|
*psci_ops = &plat_qemu_psci_pm_ops;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __QEMU_PRIVATE_H
|
||||||
|
#define __QEMU_PRIVATE_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size,
|
||||||
|
unsigned long ro_start, unsigned long ro_limit,
|
||||||
|
unsigned long coh_start, unsigned long coh_limit);
|
||||||
|
|
||||||
|
void qemu_configure_mmu_el3(unsigned long total_base, unsigned long total_size,
|
||||||
|
unsigned long ro_start, unsigned long ro_limit,
|
||||||
|
unsigned long coh_start, unsigned long coh_limit);
|
||||||
|
|
||||||
|
void plat_qemu_io_setup(void);
|
||||||
|
unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
|
||||||
|
|
||||||
|
int dt_add_psci_node(void *fdt);
|
||||||
|
int dt_add_psci_cpu_enable_methods(void *fdt);
|
||||||
|
|
||||||
|
#endif /*__QEMU_PRIVATE_H*/
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2016, 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 <arch.h>
|
||||||
|
#include <platform_def.h>
|
||||||
|
#include "qemu_private.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* The power domain tree descriptor */
|
||||||
|
static unsigned char power_domain_tree_desc[] = {
|
||||||
|
/* Number of root nodes */
|
||||||
|
PLATFORM_CLUSTER_COUNT,
|
||||||
|
/* Number of children for the first node */
|
||||||
|
PLATFORM_CLUSTER0_CORE_COUNT,
|
||||||
|
/* Number of children for the second node */
|
||||||
|
PLATFORM_CLUSTER1_CORE_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function returns the ARM default topology tree information.
|
||||||
|
******************************************************************************/
|
||||||
|
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||||
|
{
|
||||||
|
return power_domain_tree_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function implements a part of the critical interface between the psci
|
||||||
|
* generic layer and the platform that allows the former to query the platform
|
||||||
|
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
|
||||||
|
* in case the MPIDR is invalid.
|
||||||
|
******************************************************************************/
|
||||||
|
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||||
|
{
|
||||||
|
unsigned int cluster_id, cpu_id;
|
||||||
|
|
||||||
|
mpidr &= MPIDR_AFFINITY_MASK;
|
||||||
|
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
|
||||||
|
if (cluster_id >= PLATFORM_CLUSTER_COUNT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return plat_qemu_calc_core_pos(mpidr);
|
||||||
|
}
|
Loading…
Reference in New Issue