Hi
I am currently trying to configure either Altera Soc and Xilinx Zynq to boot
Linux in nonsecure-mode.
This mail focusses on the Altera SOC.
As soon as the u-boot switched to normal mode it seems there is a problem with
code alignment handling?
At least it seems the code which is running beforehand stops working in normal
mode and stops in either
data_abort or prefetch handler. It stopps working when it hits the call to
stdio_devices[file]->puts(s); in console_puts (console.c:255).
print *stdio_devices[file]
$2 = {flags = 16978471, ext = 16978464,
name = "$\022\003\001\202\022\003\001\360\031\003\001\020\060\220", <incomplete
sequence \345>,
start = 0xe92d4070, stop = 0xe2806010, putc = 0xe1530006, puts = 0xe1a04000,
tstc = 0xe1a05001,
getc = 0xe5810024, priv = 0x1a000007, list = { next = 0xe5831004, prev =
0xe5813000}}
As there are unaligned addresses (putc?) in these function calls i have the
impression that this is not working in
normal mode but in secure mode.
Unfortunatly i was not able to get the mainline u-boot to boot on the altera
soc so i patched the altera release:
git://git.rocketboards.org/u-boot-socfpga.git
with the 1740999a39ea4217bf926002d10869c0d925a5dc aka socfpga_v2013.01.01-rel
branch.
As the altera u-boot release socfpga_v2013.01.01-rel is to old to have the
CONFIG_ARMV7_NONSEC patches
i cherry-picked the following patches:
d4296887544ddf95808bfb62f312008f519efb7b extend non-secure switch to
also go into HYP mode
ba6a1698116da272f14c53a3ae41467cb7fc4372 add SMP support for non-secure
switch
bb975455650b1f36681de31a93ffe54952ed3a6b trigger non-secure state switch
during bootm execution
1ef923851ab8ffcc4265fd991815b88d9c1f12d7 add C function to switch to
non-secure state
16212b594f385bd594d5d316bf11b13c1186e3d7 add assembly routine to switch
to non-secure state
45b940d6f9a9d4989452ea67480e299bfa51ee19 add secure monitor handler to
switch to non-secure state
d75ba503a972df09784f1a332ba356ef8b42a0a6 ARM: prepare armv7.h to be
included from assembly source
I also applied the attached hacked together patches to get the system running
and fix up the stack pointer in
normal mode as it pointed to 0.
Best regards
Tim
>From ada1a10d612d8f123ff63b17a7b4e5d586a9a43a Mon Sep 17 00:00:00 2001
From: Tim Sander <t...@krieglstein.org>
Date: Mon, 24 Mar 2014 15:12:47 +0100
Subject: [PATCH 1/3] CONFIG_ARMV7_NONSEC compile fixes
---
arch/arm/cpu/u-boot.lds | 1 +
board/altera/socfpga/socfpga_common.c | 16 ++++++++++++++++
include/configs/socfpga_cyclone5.h | 4 ++++
3 files changed, 21 insertions(+)
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index e6b202b..1ea1ac2 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -88,6 +88,7 @@ SECTIONS
__bss_end__ = .;
}
+ .rel.plt : { *(.rel.plt) }
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
diff --git a/board/altera/socfpga/socfpga_common.c b/board/altera/socfpga/socfpga_common.c
index 5e459bb..8f6d215 100644
--- a/board/altera/socfpga/socfpga_common.c
+++ b/board/altera/socfpga/socfpga_common.c
@@ -81,4 +81,20 @@ int designware_board_phy_init(struct eth_device *dev, int phy_addr,
}
return 0;
}
+
+#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
+/* Setting the address at which secondary cores start from.
+ * Versatile Express uses one address for all cores, so ignore corenr
+ */
+void smp_set_core_boot_addr(unsigned long addr, int corenr)
+{
+ /* The SYSFLAGS register on VExpress needs to be cleared first
+ * by writing to the next address, since any writes to the address
+ * at offset 0 will only be ORed in
+ */
+ writel(~0, CONFIG_SYSFLAGS_ADDR + 4);
+ writel(addr, CONFIG_SYSFLAGS_ADDR);
+}
+#endif
+
#endif
diff --git a/include/configs/socfpga_cyclone5.h b/include/configs/socfpga_cyclone5.h
index 106c52c..a2b8b3b 100644
--- a/include/configs/socfpga_cyclone5.h
+++ b/include/configs/socfpga_cyclone5.h
@@ -35,4 +35,8 @@
#define CONFIG_EPHY_PHY_ADDR CONFIG_EPHY1_PHY_ADDR
#define CONFIG_PHY_INTERFACE_MODE SOCFPGA_PHYSEL_ENUM_RGMII
+#define CONFIG_ARMV7_NONSEC
+#define CONFIG_SYSFLAGS_ADDR 0x1c010030
+#define CONFIG_SMP_PEN_ADDR CONFIG_SYSFLAGS_ADDR
+
#endif /* __CONFIG_H */
--
1.7.9.5
>From 7ead8c23659ad64dfdf54994f0e1c9f6e376b6aa Mon Sep 17 00:00:00 2001
From: Tim Sander <t...@krieglstein.org>
Date: Wed, 26 Mar 2014 13:37:17 +0100
Subject: [PATCH 2/3] restore stack pointer in normal mode, remove prints in
u-boot final stage, add GIC_BASE_ADDRESS
---
arch/arm/cpu/armv7/nonsec_virt.S | 5 +++++
arch/arm/cpu/armv7/virt-v7.c | 18 +++++++++++++++---
arch/arm/include/asm/armv7.h | 7 ++++---
arch/arm/lib/bootm.c | 2 +-
common/bootstage.c | 3 +++
include/configs/socfpga_common.h | 2 ++
include/configs/socfpga_cyclone5.h | 1 +
7 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index 358348f..3048599 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -50,6 +50,7 @@ _monitor_vectors:
*/
.align 5
_secure_monitor:
+ mov r2,r1
mrc p15, 0, r1, c1, c1, 0 @ read SCR
bic r1, r1, #0x4e @ clear IRQ, FIQ, EA, nET bits
orr r1, r1, #0x31 @ enable NS, AW, FW bits
@@ -68,6 +69,7 @@ _secure_monitor:
mcreq p15, 4, r0, c12, c0, 0 @ write HVBAR
#endif
+ mov sp,r2 @ restore stack pointer from caller (eq to secure mode stack)
movs pc, lr @ return to non-secure SVC
_hyp_trap:
@@ -168,12 +170,15 @@ ENTRY(_nonsec_init)
mrc p15, 0, ip, c12, c0, 0 @ save secure copy of VBAR
+ stmfd sp!,{r2} @ save r2 as it is clobbered in monitor mode
+ mov r1,sp
isb
smc #0 @ call into MONITOR mode
mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR
mov r1, #1
+ ldmfd sp!,{r2} @ restore r2
str r1, [r3, #GICC_CTLR] @ enable non-secure CPU i/f
add r2, r2, #GIC_DIST_OFFSET
str r1, [r2, #GICD_CTLR] @ allow private interrupts
diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
index 6de7fe7..322b587 100644
--- a/arch/arm/cpu/armv7/virt-v7.c
+++ b/arch/arm/cpu/armv7/virt-v7.c
@@ -62,7 +62,9 @@ static unsigned long get_gicd_base_address(void)
* which we know only for sure for those two CPUs.
*/
asm("mrc p15, 0, %0, c0, c0, 0\n" : "=r"(midr));
+ printf("midr: %x masked:%x\n",midr,midr & MIDR_PRIMARY_PART_MASK);
switch (midr & MIDR_PRIMARY_PART_MASK) {
+ case MIDR_CORTEX_A9_R0P0:
case MIDR_CORTEX_A9_R0P1:
case MIDR_CORTEX_A15_R0P0:
case MIDR_CORTEX_A7_R0P0:
@@ -75,6 +77,7 @@ static unsigned long get_gicd_base_address(void)
/* get the GIC base address from the CBAR register */
asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase));
+ printf("periphbase: %x working_address:%x\n",periphbase, (periphbase & CBAR_MASK)+GIC_DIST_OFFSET);
/* the PERIPHBASE can be mapped above 4 GB (lower 8 bits used to
* encode this). Bail out here since we cannot access this without
* enabling paging.
@@ -105,7 +108,7 @@ int armv7_switch_hyp(void)
/* check whether we are in HYP mode already */
if ((read_cpsr() & 0x1f) == 0x1a) {
- debug("CPU already in HYP mode\n");
+ printf("CPU already in HYP mode\n");
return 0;
}
@@ -148,11 +151,13 @@ int armv7_switch_nonsec(void)
gic_dist_addr = get_gicd_base_address();
if (gic_dist_addr == -1)
return -1;
-
+
+ printf("enable GIC addr:%x \n", gic_dist_addr + GICD_CTLR);
/* enable the GIC distributor */
writel(readl(gic_dist_addr + GICD_CTLR) | 0x03,
gic_dist_addr + GICD_CTLR);
+ printf("typer register: %x\n", gic_dist_addr + GICD_TYPER);
/* TYPER[4:0] contains an encoded number of available interrupts */
itlinesnr = readl(gic_dist_addr + GICD_TYPER) & 0x1f;
@@ -160,14 +165,21 @@ int armv7_switch_nonsec(void)
* from non-secure state. The first 32 interrupts are private per
* CPU and will be set later when enabling the GIC for each core
*/
+ printf("allow non secure access\n");
for (i = 1; i <= itlinesnr; i++)
writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i);
+ printf("set core boot addr\n");
smp_set_core_boot_addr((unsigned long)_smp_pen, -1);
+ printf("kick cpus\n");
smp_kick_all_cpus();
+ /* read Monitor Vector Base Address Register */
+ asm("mrc p15, 0, %0, c12, c0, 1" : "=r"(reg) : : "cc");
+ printf("MVBAR (p15,0,c12,c0,1):%x\n",reg);
+
/* call the non-sec switching code on this CPU also */
+ printf("nonsec init");
_nonsec_init();
-
return 0;
}
diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
index 73c7d2a..e581fd3 100644
--- a/arch/arm/include/asm/armv7.h
+++ b/arch/arm/include/asm/armv7.h
@@ -25,9 +25,10 @@
#define ARMV7_H
/* Cortex-A9 revisions */
-#define MIDR_CORTEX_A9_R0P1 0x410FC091
-#define MIDR_CORTEX_A9_R1P2 0x411FC092
-#define MIDR_CORTEX_A9_R1P3 0x411FC093
+#define MIDR_CORTEX_A9_R0P0 0x410FC090
+#define MIDR_CORTEX_A9_R0P1 0x410FC091
+#define MIDR_CORTEX_A9_R1P2 0x411FC092
+#define MIDR_CORTEX_A9_R1P3 0x411FC093
#define MIDR_CORTEX_A9_R2P10 0x412FC09A
/* Cortex-A15 revisions */
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 51158eb..35abccf 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -99,7 +99,7 @@ static int fixup_memory_node(void *blob)
static void announce_and_cleanup(void)
{
- printf("\nStarting kernel ...\n\n");
+ //printf("\nStarting kernel ...\n\n");
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
#ifdef CONFIG_BOOTSTAGE_FDT
bootstage_fdt_add_report();
diff --git a/common/bootstage.c b/common/bootstage.c
index a1e0939..b4e7c07 100644
--- a/common/bootstage.c
+++ b/common/bootstage.c
@@ -239,8 +239,11 @@ static int add_bootstages_devicetree(struct fdt_header *blob)
int bootstage_fdt_add_report(void)
{
if (add_bootstages_devicetree(working_fdt))
+ return 0;
+ /* FIXME q
puts("bootstage: Failed to add to device tree\n");
+ */
return 0;
}
#endif
diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h
index ff8824f..b30ae06 100644
--- a/include/configs/socfpga_common.h
+++ b/include/configs/socfpga_common.h
@@ -371,10 +371,12 @@
/*
* L4 Watchdog
*/
+ /*
#define CONFIG_HW_WATCHDOG
#define CONFIG_HW_WATCHDOG_TIMEOUT_MS (2000)
#define CONFIG_DESIGNWARE_WATCHDOG
#define CONFIG_DW_WDT_BASE SOCFPGA_L4WD0_ADDRESS
+ */
/* Clocks source frequency to watchdog timer */
#if defined(CONFIG_SOCFPGA_VIRTUAL_TARGET)
#define CONFIG_DW_WDT_CLOCK_KHZ 2400
diff --git a/include/configs/socfpga_cyclone5.h b/include/configs/socfpga_cyclone5.h
index a2b8b3b..2eac0e1 100644
--- a/include/configs/socfpga_cyclone5.h
+++ b/include/configs/socfpga_cyclone5.h
@@ -38,5 +38,6 @@
#define CONFIG_ARMV7_NONSEC
#define CONFIG_SYSFLAGS_ADDR 0x1c010030
#define CONFIG_SMP_PEN_ADDR CONFIG_SYSFLAGS_ADDR
+#define CONFIG_ARM_GIC_BASE_ADDRESS 0xfffed000 - 0x1000 //GIC_DIST_OFFSET
#endif /* __CONFIG_H */
--
1.7.9.5
>From a2b7d1cf22a41f09f00a7088ca69acd03329cc0c Mon Sep 17 00:00:00 2001
From: Tim Sander <t...@krieglstein.org>
Date: Wed, 26 Mar 2014 13:51:30 +0100
Subject: [PATCH 3/3] move secure mode switch directly in front of kernel boot
---
arch/arm/lib/bootm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 35abccf..39dcf9c 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -337,7 +337,6 @@ static void boot_prep_linux(bootm_headers_t *images)
hang();
#endif /* all tags */
}
- do_nonsec_virt_switch();
}
/* Subcommand: GO */
@@ -368,6 +367,7 @@ static void boot_jump_linux(bootm_headers_t *images)
#endif
r2 = gd->bd->bi_boot_params;
+ do_nonsec_virt_switch();
kernel_entry(0, machid, r2);
}
--
1.7.9.5
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot