X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv7%2Fvirt-v7.c;h=d33e5c61a9c29890989666b472ad5eb355961e01;hb=fd12455643dbe68e2a3675b1d2adb384ebacd251;hp=2cd604f97fa1802462ffa41ddf6bb3e362888d0d;hpb=968294bd7b9b540f53c1fb3c809da464623a4362;p=u-boot diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c index 2cd604f97f..d33e5c61a9 100644 --- a/arch/arm/cpu/armv7/virt-v7.c +++ b/arch/arm/cpu/armv7/virt-v7.c @@ -13,16 +13,7 @@ #include #include #include - -unsigned long gic_dist_addr; - -static unsigned int read_cpsr(void) -{ - unsigned int reg; - - asm volatile ("mrs %0, cpsr\n" : "=r" (reg)); - return reg; -} +#include static unsigned int read_id_pfr1(void) { @@ -37,25 +28,8 @@ static unsigned long get_gicd_base_address(void) #ifdef CONFIG_ARM_GIC_BASE_ADDRESS return CONFIG_ARM_GIC_BASE_ADDRESS + GIC_DIST_OFFSET; #else - unsigned midr; unsigned periphbase; - /* check whether we are an Cortex-A15 or A7. - * The actual HYP switch should work with all CPUs supporting - * the virtualization extension, but we need the GIC address, - * which we know only for sure for those two CPUs. - */ - asm("mrc p15, 0, %0, c0, c0, 0\n" : "=r"(midr)); - switch (midr & MIDR_PRIMARY_PART_MASK) { - case MIDR_CORTEX_A9_R0P1: - case MIDR_CORTEX_A15_R0P0: - case MIDR_CORTEX_A7_R0P0: - break; - default: - printf("nonsec: could not determine GIC address.\n"); - return -1; - } - /* get the GIC base address from the CBAR register */ asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase)); @@ -72,6 +46,25 @@ static unsigned long get_gicd_base_address(void) #endif } +/* Define a specific version of this function to enable any available + * hardware protections for the reserved region */ +void __weak protect_secure_section(void) {} + +static void relocate_secure_section(void) +{ +#ifdef CONFIG_ARMV7_SECURE_BASE + size_t sz = __secure_end - __secure_start; + unsigned long szflush = ALIGN(sz + 1, CONFIG_SYS_CACHELINE_SIZE); + + memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz); + + flush_dcache_range(CONFIG_ARMV7_SECURE_BASE, + CONFIG_ARMV7_SECURE_BASE + szflush); + protect_secure_section(); + invalidate_icache_all(); +#endif +} + static void kick_secondary_cpus_gic(unsigned long gicdaddr) { /* kick all CPUs (except this one) by writing to GICD_SGIR */ @@ -80,41 +73,24 @@ static void kick_secondary_cpus_gic(unsigned long gicdaddr) void __weak smp_kick_all_cpus(void) { + unsigned long gic_dist_addr; + + gic_dist_addr = get_gicd_base_address(); + if (gic_dist_addr == -1) + return; + kick_secondary_cpus_gic(gic_dist_addr); } -int armv7_switch_hyp(void) +__weak void psci_board_init(void) { - unsigned int reg; - - /* check whether we are in HYP mode already */ - if ((read_cpsr() & 0x1f) == 0x1a) { - debug("CPU already in HYP mode\n"); - return 0; - } - - /* check whether the CPU supports the virtualization extensions */ - reg = read_id_pfr1(); - if ((reg & CPUID_ARM_VIRT_MASK) != 1 << CPUID_ARM_VIRT_SHIFT) { - printf("HYP mode: Virtualization extensions not implemented.\n"); - return -1; - } - - /* call the HYP switching code on this CPU also */ - _switch_to_hyp(); - - if ((read_cpsr() & 0x1F) != 0x1a) { - printf("HYP mode: switch not successful.\n"); - return -1; - } - - return 0; } -int armv7_switch_nonsec(void) +int armv7_init_nonsec(void) { unsigned int reg; unsigned itlinesnr, i; + unsigned long gic_dist_addr; /* check whether the CPU supports the security extensions */ reg = read_id_pfr1(); @@ -147,11 +123,22 @@ int armv7_switch_nonsec(void) for (i = 1; i <= itlinesnr; i++) writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i); - smp_set_core_boot_addr((unsigned long)_smp_pen, -1); + psci_board_init(); + + /* + * Relocate secure section before any cpu runs in secure ram. + * smp_kick_all_cpus may enable other cores and runs into secure + * ram, so need to relocate secure section before enabling other + * cores. + */ + relocate_secure_section(); + +#ifndef CONFIG_ARMV7_PSCI + smp_set_core_boot_addr((unsigned long)secure_ram_addr(_smp_pen), -1); smp_kick_all_cpus(); +#endif /* call the non-sec switching code on this CPU also */ - _nonsec_init(); - + secure_ram_addr(_nonsec_init)(); return 0; }