mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
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
15 changed files with 2331 additions and 0 deletions
44
docs/plat/qemu.md
Normal file
44
docs/plat/qemu.md
Normal file
|
@ -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
|
||||
```
|
140
plat/qemu/aarch64/plat_helpers.S
Normal file
140
plat/qemu/aarch64/plat_helpers.S
Normal file
|
@ -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
|
||||
|
||||
|
119
plat/qemu/dt.c
Normal file
119
plat/qemu/dt.c
Normal file
|
@ -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;
|
||||
}
|
50
plat/qemu/include/plat_macros.S
Normal file
50
plat/qemu/include/plat_macros.S
Normal file
|
@ -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__ */
|
244
plat/qemu/include/platform_def.h
Normal file
244
plat/qemu/include/platform_def.h
Normal file
|
@ -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__ */
|
99
plat/qemu/platform.mk
Normal file
99
plat/qemu/platform.mk
Normal file
|
@ -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))
|
148
plat/qemu/qemu_bl1_setup.c
Normal file
148
plat/qemu/qemu_bl1_setup.c
Normal file
|
@ -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);
|
||||
}
|
327
plat/qemu/qemu_bl2_setup.c
Normal file
327
plat/qemu/qemu_bl2_setup.c
Normal file
|
@ -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;
|
||||
}
|
164
plat/qemu/qemu_bl31_setup.c
Normal file
164
plat/qemu/qemu_bl31_setup.c
Normal file
|
@ -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;
|
||||
}
|
145
plat/qemu/qemu_common.c
Normal file
145
plat/qemu/qemu_common.c
Normal file
|
@ -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)
|
||||
|
||||
|
92
plat/qemu/qemu_gic.c
Normal file
92
plat/qemu/qemu_gic.c
Normal file
|
@ -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);
|
||||
}
|
||||
|
378
plat/qemu/qemu_io_storage.c
Normal file
378
plat/qemu/qemu_io_storage.c
Normal file
|
@ -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;
|
||||
}
|
253
plat/qemu/qemu_pm.c
Normal file
253
plat/qemu/qemu_pm.c
Normal file
|
@ -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;
|
||||
}
|
50
plat/qemu/qemu_private.h
Normal file
50
plat/qemu/qemu_private.h
Normal file
|
@ -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*/
|
78
plat/qemu/topology.c
Normal file
78
plat/qemu/topology.c
Normal file
|
@ -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…
Add table
Reference in a new issue