在 2012-9-5,下午9:00, Dave Martin 写道: On Wed, Sep 05, 2012 at 04:32:01PM +0800, Guodong Xu wrote: Turn on CCI snoops. Data abort exception is captured and handled
for implementations where CCI is not integrated.
This may work for now, but it's potentially fragile. We may get platform variants where there is some different peripheral at 0x2c090000.
<guodong> Actually, peripheral base address should be get by reading cp15, for both GIC (+0x1000), and CCI (+0x90000). Eg. ; Get the address of the GIC MRC p15, 4, r0, c15, c0, 0 ; Read periph base address (see DE593076) ADD r0, r0, #0x1000 ; Add GIC offset to base address
But in current boot wrapper, GIC address is also hardcoded, so I just follow for CCI. Maybe I can submit another patch to change both these to reading from cp15?
The cleanest solution would be to examine the device tree, but
<guodong> Our tests show 'Turning on CCI snoop' in Hyp mode fails. But current boot-wrapper C code and Linux kernel runs in Hyp mode. So, device tree method may not work. unfortunately there are no mature bindings for the CCI yet. We should fix that in parallel, but in the meantime we could add boot arguments to provide the CCI base address and identify which master port(s) to enable snooping for. --cci=0x2c090000:3,4 or --board=<boardname> where we use <boardname> to select which extra board setup code we need to run. Cheers ---Dave
Signed-off-by: Guodong Xu <guodong.xu@xxxxxxxxxx>
---
Makefile | 6 +++++-
boot.S | 41 ++++++++++++++++++++++++++++++++++++++---
model.lds.S | 4 ++++
secure.S | 28 ++++++++++++++++++++++++++++
4 files changed, 75 insertions(+), 4 deletions(-)
create mode 100644 secure.S
diff --git a/Makefile b/Makefile
index 995fd8f..f3cdee3 100644
--- a/Makefile
+++ b/Makefile
@@ -15,9 +15,10 @@ endif
LIBFDTOBJS = libfdt/fdt.o libfdt/fdt_ro.o libfdt/fdt_wip.o \
libfdt/fdt_sw.o libfdt/fdt_rw.o libfdt/fdt_strerror.o
+SECURE = secure.S
MONITOR = monitor.S
BOOTLOADER = boot.S
-OBJS = boot.o c_start.o monitor.o semihosting.o string.o semi_loader.o $(LIBFDTOBJS)
+OBJS = boot.o c_start.o monitor.o secure.o semihosting.o string.o semi_loader.o $(LIBFDTOBJS)
KERNEL = uImage
IMAGE = linux-system.axf
@@ -53,6 +54,9 @@ $(SEMIIMG): $(OBJS) modelsemi.lds
boot.o: $(BOOTLOADER)
$(CC) $(CPPFLAGS) -DKCMD='$(KCMD)' -c -o $@ $<
+secure.o: $(SECURE)
+ $(CC) $(CPPFLAGS) -c -o $@ $<
+
monitor.o: $(MONITOR)
$(CC) $(CPPFLAGS) -c -o $@ $<
diff --git a/boot.S b/boot.S
index 61cd93f..a5f3f20 100644
--- a/boot.S
+++ b/boot.S
@@ -67,14 +67,49 @@ start:
mov r0, #0xf0000000
mcr p15, 0, r0, c12, c0, 1 @ Monitor vector base address
- @ Set up hvbar so hvc comes back here.
+ @ Load secure.S, Secure Vector Table
+ add r0, r0, #0x4000 @ SEC_OFFSET
+ mcr p15, 0, r0, c12, c0, 0 @ VBR Secure vector base address
+
+ @ Check CPU nr again
+ mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only)
+ bfc r0, #24, #8 @ CPU number and cluster
+ cmp r0, #0 @ primary CPU?
+ bne 4f
+
+ @ primary CPU
+
+ @
+ @ Turn on CCI snoops
+ @
+ ldr r4, =0x2c090000
+ ldr r3, [r4, #0xc] @ status reg
+ @
+ @ If CCI doesn't exist, access to it can cause data abort exception.
+ @ Data abort handling routine marks r4
+ @
+ nop
+ nop
+ cmp r4, #0xba
+ beq 4f @ no CCI, skip
+
+ mov r3, #3
+ mov r5, #0x4000 @ A15
+ str r3, [r4, r5]
+ mov r5, #0x5000 @ A7
+ str r3, [r4, r5]
+3: ldr r3, [r4, #0xc] @ status reg
+ tst r3, #1
+ bne 3b
+
+4: @ Set up hvbar so hvc comes back here.
ldr r0, =vectors
mov r7, #0xfffffff0
smc #0 @ Set HVBAR
@ We can't call hvc from secure mode, so drop down first.
mov r7, #0xffffffff
- smc #0 @ Change to NS-mode
+ smc #0 @ Change to NS-mode
@ This is how we enter hyp mode, for booting the next stage.
hvc #0
@@ -93,7 +128,7 @@ vectors:
into_hyp_mode:
@ Check CPU nr again
mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only)
- and r0, r0, #15 @ CPU number
+ bfc r0, #24, #8 @ CPU number and cluster
cmp r0, #0 @ primary CPU?
beq 2f
diff --git a/model.lds.S b/model.lds.S
index 07fae8c..aa7d3b8 100644
--- a/model.lds.S
+++ b/model.lds.S
@@ -22,6 +22,7 @@ INPUT(./uImage)
PHYS_OFFSET = 0x80000000;
MON_OFFSET = 0xf0000000;
+SEC_OFFSET = 0xf0004000;
STACKTOP = 0xff000000;
@@ -49,6 +50,9 @@ SECTIONS
. = MON_OFFSET;
.monitor : { monitor.o }
+ . = SEC_OFFSET;
+ .secure : { secure.o }
+
/* Put most of the actual boot loader code up in high memory
* where it won't get overwritten by kernel, initrd or atags.
*/
diff --git a/secure.S b/secure.S
new file mode 100644
index 0000000..681e212
--- /dev/null
+++ b/secure.S
@@ -0,0 +1,28 @@
+/*
+ * secure.S - simple monitor code to switch to NS state before executing kernel
+ *
+ * Copyright (C) 2012 Linaro - http://www.linaro.org. All rights reserved.
+ * Guodong Xu <guodong.xu@xxxxxxxxxx>
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE.txt file.
+ */
+
+#.syntax unified
+ .section secure, "x"
+
+ .word 0 /* reset */
+ .word 0 /* undefined instruction */
+ .word 0 /* supervisor call */
+ .word 0 /* prefetch abort */
+ b 1f /* data abort */
+ .word 0 /* not useed */
+ .word 0 /* IRQ */
+ .word 0 /* FIQ */
+
+1: @
+ @ data abort handling
+ @
+ /* do nothing, just return */
+ mov r4, #0xba @ mark r4
+ subs pc, lr, #0 @ return where from
--
1.7.4.1
|