diff options
author | Vishnu Banavath <vishnu.banavath@arm.com> | 2022-04-06 16:30:01 +0100 |
---|---|---|
committer | Vishnu <vishnu.banavath@arm.com> | 2022-04-28 17:42:43 +0200 |
commit | 7f660cbe5f04cf86ebe4dd09c6316634972d0934 (patch) | |
tree | fcd3d939556d58bd3ced3a2e2fbd9d633cc218f9 | |
parent | 39054c3002cf0a7fa52c9b8a24813c10ad1212e9 (diff) | |
download | tf-a-tests-7f660cbe5f04cf86ebe4dd09c6316634972d0934.tar.gz |
feat(plat/arm): add corstone1000 platform support
These changes are to add corstone1000 platform support
Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
Change-Id: I1a61539326b595faadcf919da24699cd8e4c3a41
-rw-r--r-- | plat/arm/corstone1000/corstone1000_def.h | 48 | ||||
-rw-r--r-- | plat/arm/corstone1000/corstone1000_mem_prot.c | 23 | ||||
-rw-r--r-- | plat/arm/corstone1000/corstone1000_pwr_state.c | 66 | ||||
-rw-r--r-- | plat/arm/corstone1000/corstone1000_topology.c | 48 | ||||
-rw-r--r-- | plat/arm/corstone1000/include/platform_def.h | 174 | ||||
-rw-r--r-- | plat/arm/corstone1000/plat_helpers.S | 91 | ||||
-rw-r--r-- | plat/arm/corstone1000/plat_setup.c | 40 | ||||
-rw-r--r-- | plat/arm/corstone1000/platform.mk | 28 | ||||
-rw-r--r-- | plat/arm/corstone1000/tests_to_skip.txt | 15 | ||||
-rw-r--r-- | tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c | 4 |
10 files changed, 536 insertions, 1 deletions
diff --git a/plat/arm/corstone1000/corstone1000_def.h b/plat/arm/corstone1000/corstone1000_def.h new file mode 100644 index 000000000..3e6f036ac --- /dev/null +++ b/plat/arm/corstone1000/corstone1000_def.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORSTONE1000_DEF_H__ +#define __CORSTONE1000_DEF_H__ + +#include <common_def.h> +#include <platform_def.h> + +/******************************************************************************* + * HOST memory map related constants + ******************************************************************************/ + +#define HOST_PERIPHERAL_BASE (0x1A000000) +#define HOST_PERIPHERAL_SIZE (608 * SZ_1M) + +#define ON_CHIP_MEM_BASE (0x02000000) +#define ON_CHIP_MEM_SIZE (SZ_4M) + +#define DRAM_BASE (0x80000000) +#define DRAM_SIZE (SZ_2G) +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ +/* GIC memory map */ +#define GICD_BASE 0x1C010000 +#define GICC_BASE 0x1C02F000 +/* GIC re-distributor doesn't exits on gic-400, but we still need to + * provide GICR_BASE as the gic driver needs it + */ +#define GICR_BASE 0x0 + +/******************************************************************************* + * PL011 related constants + ******************************************************************************/ +#define PL011_UART0_BASE 0x1A510000 +#define PL011_UART1_BASE 0x1A520000 + +#define PL011_UART0_CLK_IN_HZ 50000000 +#define PL011_UART1_CLK_IN_HZ 50000000 + +#define PLAT_ARM_UART_BASE PL011_UART0_BASE +#define PLAT_ARM_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ + +#endif /* __CORSTONE1000_DEF_H__ */ diff --git a/plat/arm/corstone1000/corstone1000_mem_prot.c b/plat/arm/corstone1000/corstone1000_mem_prot.c new file mode 100644 index 000000000..8e4a27027 --- /dev/null +++ b/plat/arm/corstone1000/corstone1000_mem_prot.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform.h> +#include <psci.h> +#include <utils_def.h> +#include <xlat_tables_v2.h> + +#define NS_IMAGE_OFFSET TFTF_BASE +#define NS_IMAGE_LIMIT (NS_IMAGE_OFFSET + (32 << TWO_MB_SHIFT)) + +static const mem_region_t corstone1000_ram_ranges[] = { + {NS_IMAGE_LIMIT, 128 << TWO_MB_SHIFT}, +}; + +const mem_region_t *plat_get_prot_regions(int *nelem) +{ + *nelem = ARRAY_SIZE(corstone1000_ram_ranges); + return corstone1000_ram_ranges; +} diff --git a/plat/arm/corstone1000/corstone1000_pwr_state.c b/plat/arm/corstone1000/corstone1000_pwr_state.c new file mode 100644 index 000000000..b2f0bc82a --- /dev/null +++ b/plat/arm/corstone1000/corstone1000_pwr_state.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> +#include <arch.h> +#include <platform.h> +#include <psci.h> + +/* + * State IDs for local power states on Corstone1000. + */ +#define CORSTONE1000_RUN_STATE_ID 0 /* Valid for CPUs and Clusters */ +#define CORSTONE1000_RETENTION_STATE_ID 1 /* Valid for only CPUs */ +#define CORSTONE1000_OFF_STATE_ID 2 /* Valid for CPUs and Clusters */ + +/* + * Suspend depth definitions for each power state + */ +typedef enum { + CORSTONE1000_RUN_DEPTH = 0, + CORSTONE1000_RETENTION_DEPTH, + CORSTONE1000_OFF_DEPTH, +} suspend_depth_t; + +/* The state property array with details of idle state possible for the core */ +static const plat_state_prop_t core_state_prop[] = { + {CORSTONE1000_RETENTION_DEPTH, CORSTONE1000_RETENTION_STATE_ID, PSTATE_TYPE_STANDBY}, + {CORSTONE1000_OFF_DEPTH, CORSTONE1000_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN}, + {0}, +}; + +/* + * The state property array with details of idle state possible + * for the cluster + */ +static const plat_state_prop_t cluster_state_prop[] = { + {CORSTONE1000_OFF_DEPTH, CORSTONE1000_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN}, + {0}, +}; + +/* + * The state property array with details of idle state possible + * for the system. Currently Corstone1000 does not support CPU SUSPEND + * at system power level. + */ +static const plat_state_prop_t system_state_prop[] = { + {CORSTONE1000_OFF_DEPTH, CORSTONE1000_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN}, + {0}, +}; + +const plat_state_prop_t *plat_get_state_prop(unsigned int level) +{ + switch (level) { + case MPIDR_AFFLVL0: + return core_state_prop; + case MPIDR_AFFLVL1: + return cluster_state_prop; + case MPIDR_AFFLVL2: + return system_state_prop; + default: + return NULL; + } +} diff --git a/plat/arm/corstone1000/corstone1000_topology.c b/plat/arm/corstone1000/corstone1000_topology.c new file mode 100644 index 000000000..37055ec4a --- /dev/null +++ b/plat/arm/corstone1000/corstone1000_topology.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stddef.h> +#include <arch.h> +#include <tftf_lib.h> +#include <plat_topology.h> +#include <platform_def.h> + +static const struct { + unsigned int cluster_id; + unsigned int cpu_id; +} corstone1000_cores[] = { + /* SMP with single core, cluster_id is same as cpu_id */ + { 0, 0 }, +}; + +/* + * The Corstone1000 power domain tree descriptor. Corstone1000 implements a system + * power domain at the level 2. The first entry in the power domain descriptor + * specifies the number of power domains at the highest power level. For Corstone1000 + * this is 1 i.e. the number of system power domain. + */ +static const unsigned char corstone1000_power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* Number of children of root node */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the second cluster */ + PLATFORM_CLUSTER0_CORE_COUNT +}; + +const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void) +{ + return corstone1000_power_domain_tree_desc; +} + +uint64_t tftf_plat_get_mpidr(unsigned int core_pos) +{ + assert(core_pos < PLATFORM_CORE_COUNT); + + return make_mpid(corstone1000_cores[core_pos].cluster_id, + corstone1000_cores[core_pos].cpu_id); +} diff --git a/plat/arm/corstone1000/include/platform_def.h b/plat/arm/corstone1000/include/platform_def.h new file mode 100644 index 000000000..a0d6f7b3b --- /dev/null +++ b/plat/arm/corstone1000/include/platform_def.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <utils_def.h> + +#include "../corstone1000_def.h" + +/******************************************************************************* + * Platform definitions used by common code + ******************************************************************************/ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#ifdef __aarch64__ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 +#else +#define PLATFORM_LINKER_FORMAT "elf32-littlearm" +#define PLATFORM_LINKER_ARCH arm +#endif + +/******************************************************************************* + * Run-time address of the TFTF image. + * It has to match the location where the Trusted Firmware-A loads the BL33 + * image. + ******************************************************************************/ +#define TFTF_BASE 0x80000000 + +/****************************************************************************** + * Memory mapped Generic timer interfaces + *******************************************************************************/ +/* REFCLK CNTControl, Generic Timer. Secure Access only. */ +#define SYS_CNT_CONTROL_BASE 0x1A200000 +/* REFCLK CNTRead, Generic Timer. */ +#define SYS_CNT_READ_BASE 0x1A210000 +/* AP_REFCLK CNTBase1, Generic Timer. */ +#define SYS_CNT_BASE1 0x1A240000 + +/******************************************************************************* + * Base address and size of external NVM flash + ******************************************************************************/ +#define FLASH_BASE 0x08000000 + +#define NOR_FLASH_BLOCK_SIZE 0x40000 +#define NOR_FLASH_BLOCKS_COUNT 255 +#define FLASH_SIZE (NOR_FLASH_BLOCK_SIZE * NOR_FLASH_BLOCKS_COUNT) + +/* watchdog timer */ +#define IRQ_TWDOG_INTID 56 + +/* Size of cacheable stacks */ +#if IMAGE_NS_BL1U +#define PLATFORM_STACK_SIZE 0x1000 +#elif IMAGE_NS_BL2U +#define PLATFORM_STACK_SIZE 0x1000 +#elif IMAGE_TFTF +#define PLATFORM_STACK_SIZE 0x1400 +#endif + +/* Size of coherent stacks for debug and release builds */ +#if DEBUG +#define PCPU_DV_MEM_STACK_SIZE 0x600 +#else +#define PCPU_DV_MEM_STACK_SIZE 0x500 +#endif + +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT 1 /* Cortex-A35 Cluster */ +#define PLATFORM_CORE_COUNT 1 +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LEVEL PLATFORM_MAX_AFFLVL +#define PLAT_MAX_PWR_STATES_PER_LVL 2 + +#define CORSTONE1000_MAX_CPUS_PER_CLUSTER 4 +#define CORSTONE1000_MAX_PE_PER_CPU 1 + +/* Local state bit width for each level in the state-ID field of power state */ +#define PLAT_LOCAL_PSTATE_WIDTH 4 + +#if IMAGE_NS_BL1U +#define MAX_IO_DEVICES 2 +#define MAX_IO_HANDLES 2 +#else +#define MAX_IO_DEVICES 1 +#define MAX_IO_HANDLES 1 +#endif + +/* + * USE 0x200000 DRAM offset to store TFTF data + * + * Please note that this won't be suitable for all test scenarios and + * for this reason some tests will be disabled in this configuration. + */ +#define TFTF_NVM_OFFSET 0x40000 +#define TFTF_NVM_SIZE (128 * SZ_1M) /* 128 MB */ + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 34) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 34) +#else +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) +#endif + +#if IMAGE_TFTF +/* For testing xlat tables lib v2 */ +#define MAX_XLAT_TABLES 20 +#define MAX_MMAP_REGIONS 50 +#else +#define MAX_XLAT_TABLES 5 +#define MAX_MMAP_REGIONS 16 +#endif + +/******************************************************************************* + * Used to align variables 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) + +/******************************************************************************* + * Non-Secure Software Generated Interupts IDs + ******************************************************************************/ +#define IRQ_NS_SGI_0 0 +#define IRQ_NS_SGI_1 1 +#define IRQ_NS_SGI_2 2 +#define IRQ_NS_SGI_3 3 +#define IRQ_NS_SGI_4 4 +#define IRQ_NS_SGI_5 5 +#define IRQ_NS_SGI_6 6 +#define IRQ_NS_SGI_7 7 + +#define PLAT_MAX_SPI_OFFSET_ID 220 + +/* The IRQ generated by Ethernet controller */ +#define IRQ_ETHERNET 116 + +#define IRQ_CNTPSIRQ1 92 +/* Per-CPU Hypervisor Timer Interrupt ID */ +#define IRQ_PCPU_HP_TIMER 26 +/* Per-CPU Non-Secure Timer Interrupt ID */ +#define IRQ_PCPU_NS_TIMER 30 + +/* + * Times(in ms) used by test code for completion of different events. + * Suspend entry time for debug build is high due to the time taken + * by the VERBOSE/INFO prints. The value considers the worst case scenario + * where all CPUs are going and coming out of suspend continuously. + */ +#if DEBUG +#define PLAT_SUSPEND_ENTRY_TIME 0x100 +#define PLAT_SUSPEND_ENTRY_EXIT_TIME 0x200 +#else +#define PLAT_SUSPEND_ENTRY_TIME 10 +#define PLAT_SUSPEND_ENTRY_EXIT_TIME 20 +#endif + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/arm/corstone1000/plat_helpers.S b/plat/arm/corstone1000/plat_helpers.S new file mode 100644 index 000000000..a87f36f1a --- /dev/null +++ b/plat/arm/corstone1000/plat_helpers.S @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <drivers/arm/pl011.h> +#include "corstone1000_def.h" + + .globl platform_get_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + +/*---------------------------------------------------------------------- + * unsigned int platform_get_core_pos(unsigned long mpid) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func platform_get_core_pos + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x3, #CORSTONE1000_MAX_CPUS_PER_CLUSTER + madd x1, x2, x3, x1 + mov x3, #CORSTONE1000_MAX_PE_PER_CPU + madd x0, x1, x3, x0 + ret +endfunc platform_get_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_ARM_UART_BASE + mov_imm x1, PLAT_ARM_UART_CLK_IN_HZ + mov_imm x2, PL011_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_ARM_UART_BASE + b console_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * int plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : return -1 on error else return 0. + * Clobber list : r0 - r1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x1, PLAT_ARM_UART_BASE + b console_core_flush +endfunc plat_crash_console_flush diff --git a/plat/arm/corstone1000/plat_setup.c b/plat/arm/corstone1000/plat_setup.c new file mode 100644 index 000000000..342885d76 --- /dev/null +++ b/plat/arm/corstone1000/plat_setup.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/arm_gic.h> +#include <mmio.h> +#include <platform.h> +#include <xlat_tables_v2.h> +#include <plat_arm.h> + +/* + * Table of regions to map using the MMU. + */ +static const mmap_region_t mmap[] = { + MAP_REGION_FLAT(HOST_PERIPHERAL_BASE, HOST_PERIPHERAL_SIZE, + MT_DEVICE | MT_RW | MT_NS), + MAP_REGION_FLAT(ON_CHIP_MEM_BASE, ON_CHIP_MEM_SIZE, MT_MEMORY | MT_RW | MT_SECURE), +#if USE_NVM + MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS), +#endif + MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE, MT_MEMORY | MT_RW | MT_NS), + {0} +}; + +const mmap_region_t *tftf_platform_get_mmap(void) +{ + return mmap; +} + +void tftf_platform_setup(void) +{ + arm_platform_setup(); +} + +void plat_arm_gic_init(void) +{ + arm_gic_init(GICC_BASE, GICD_BASE, GICR_BASE); +} diff --git a/plat/arm/corstone1000/platform.mk b/plat/arm/corstone1000/platform.mk new file mode 100644 index 000000000..a5a011d51 --- /dev/null +++ b/plat/arm/corstone1000/platform.mk @@ -0,0 +1,28 @@ +# +# Copyright (c) 2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/arm/corstone1000/include/ + +PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \ + drivers/arm/gic/gic_v2.c \ + drivers/arm/timer/private_timer.c \ + drivers/arm/timer/system_timer.c \ + plat/arm/corstone1000/plat_helpers.S \ + plat/arm/corstone1000/corstone1000_pwr_state.c \ + plat/arm/corstone1000/corstone1000_topology.c \ + plat/arm/corstone1000/corstone1000_mem_prot.c \ + plat/arm/corstone1000/plat_setup.c + +PLAT_SUPPORTS_NS_RESET := 1 + +# Process PLAT_SUPPORTS_NS_RESET flag +$(eval $(call assert_boolean,PLAT_SUPPORTS_NS_RESET)) +$(eval $(call add_define,TFTF_DEFINES,PLAT_SUPPORTS_NS_RESET)) + +FIRMWARE_UPDATE := 0 +PLAT_TESTS_SKIP_LIST := plat/arm/corstone1000/tests_to_skip.txt + +include plat/arm/common/arm_common.mk diff --git a/plat/arm/corstone1000/tests_to_skip.txt b/plat/arm/corstone1000/tests_to_skip.txt new file mode 100644 index 000000000..fdab2309c --- /dev/null +++ b/plat/arm/corstone1000/tests_to_skip.txt @@ -0,0 +1,15 @@ +Realm payload tests +Realm payload boot +Realm payload multi CPU request +Realm payload Delegate and Undelegate +Multi CPU Realm payload Delegate and Undelegate +Testing delegation fails +Realm testing with SPM tests +PSCI System Suspend Validation +PSCI STAT/Stats test cases after system suspend +IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND +PSCI SYSTEM SUSPEND stress tests +Timer framework Validation/Verify the timer interrupt generation +CPU Hotplug/CPU hotplug +PSCI CPU Suspend +PSCI STAT/for valid composite state CPU suspend diff --git a/tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c b/tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c index a1e07e924..d11c1c97a 100644 --- a/tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c +++ b/tftf/tests/runtime_services/realm_payload/realm_payload_spm_test.c @@ -46,14 +46,16 @@ static int cpu_test_spm_rmi[PLATFORM_CORE_COUNT]; static void rand_cpu_spm_rmi(void) { int fentry; - int seln; + int seln = 0; for (int i = 0; i < PLATFORM_CORE_COUNT; i++) { cpu_test_spm_rmi[i] = -1; } for (int i = 0; i < NUM_CPU_DED_SPM; i++) { fentry = 0; while (fentry == 0) { +#if (PLATFORM_CORE_COUNT > 1) seln = (rand() % (PLATFORM_CORE_COUNT - 1)) + 1; +#endif if (cpu_test_spm_rmi[seln] == -1) { cpu_test_spm_rmi[seln] = 1; fentry = 1; |