I wrote a simple secure kernel in TrustZone secure world and was trying to boot the default Linux kernel Image (shipped along within the SABRE getting started DVD) in the normal world. However, it stops with a DATA_ABORT in non-secure world with the output (see <<CONSOLE_OUTPUT>):
In my current secure kernel, I set SCR.IRQ = 0, SCR.FIQ = 0, SCR.EA= 0, SCR.FW=1, SCR.AW=1. Set all TZIC_INTSEC registers to be 0xFFFFFFFF. Set all the CSL registers to be 0x00FF00FF. Set all the TZIC_PRIORITY registers to be 0x1F1F1F1F and set TZIC_INTCTRL.NSEN=1, TZIC_INTCTRL.NS=1 (According to the description in https://community.freescale.com/thread/300696). I also set IIM.SCS1.LOCK=0, IIM.SCS1.SECURE_ENBL=0. What else should I set?
While I can boot Linux in secure kernel, I compare <CONSOLE_OUTPUT> with the successful output. I find two problems (marked in the <CONSOLE_OUTPUT>). So how can I let Linux in the non-secure world access IRAM partition (or SCC configuration). And what setting causes the DATA_ABORT marked in Problem 2?
<CONSOLE_OUTPUT>
NET: Registered protocol family 16
i.MX IRAM pool: 128 KB@0x9c840000
FAILED TO RELEASE IRAM PARTITION <-----------------------------------Problem 1. "IRAM READY" in the correct case
CPU is i.MX53 Revision 2.1
Unhandled fault: external abort on non-linefetch (0x1008) at 0x9c82c00c <-----------------------------------Problem 2.
Internal error: : 1008 [#1] PREEMPT
last sysfs file:
Modules linked in:
CPU: 0 Not tainted (2.6.35.3 #3)
PC is at mxc_cpu_lp_set+0x14/0x13c
LR is at arch_idle+0x60/0x234
pc : [<80042c10>] lr : [<80042d98>] psr: 60000093
sp : 8089bf80 ip : 00000003 fp : 00000000
r10: 0000001f r9 : 412fc085 r8 : 7002ecbc
r7 : 8089ea10 r6 : 808ff024 r5 : 8089ea18 r4 : 808ff248
r3 : f7ed8fff r2 : 9c82c000 r1 : 00000002 r0 : 00000002
Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 10c5387f Table: 70004019 DAC: 00000017
Process swapper (pid: 0, stack limit = 0x8089a2e8)
Stack: (0x8089bf80 to 0x8089c000)
bf80: 808ff248 8089ea18 808ff024 8089ea10 7002ecbc 412fc085 0000001f 80042d98
bfa0: 8089a000 8089ea18 808ff024 8089ea10 7002ecbc 412fc085 0000001f 8003aaa4
bfc0: 8089a000 8003af88 8090add8 00000000 8089eab8 800089b8 800084e8 00000bc3
bfe0: 70000100 80031018 10c53c7d 808ff0d0 80031014 70008034 00000000 00000000
[<80042c10>] (mxc_cpu_lp_set+0x14/0x13c) from [<80042d98>] (arch_idle+0x60/0x234)
[<80042d98>] (arch_idle+0x60/0x234) from [<8003aaa4>] (default_idle+0x20/0x28)
[<8003aaa4>] (default_idle+0x20/0x28) from [<8003af88>] (cpu_idle+0x48/0xa0)
[<8003af88>] (cpu_idle+0x48/0xa0) from [<800089b8>] (start_kernel+0x294/0x2f4
Solved! Go to Solution.
Hi Miao Yu,
well, I can only see that Linux tries to access memory at guest virtual memory address 0x9c82c00c. It depends on: what physical address is mapped to that location. The instruction pointer 0x80042c10 will give you a hint. In principle, you might compile your own Linux binary, and use objdump or instrument the source to find out which physical memory is addressed. By looking at function "mxc_cpu_lp_set" (you can find it in your output, the PC points to it), I assume it's the access to the CPU I/O memory at 0x63fa0000 (ARM PLatform Memory), which causes the data-abort. Have a look at my patches for Linux to run it on my virtual machine monitor at Github:
https://github.com/skalk/linux/tree/imx53-tz
There you'll see, that I've factored out that access. Most of the ARM CortexA8 platform registers can only be accessed from secure, supervisor mode. For more details, have a look at "i.MX53 Multimedia Applications Processor Reference Manual" chapter 11.
Furthermore, I assume you don't run active tasks on the secure side? Because in your current implementation no action from the Linux side will cause a world switch apart from an explicitly triggered one via 'smc' instruction. Otherwise, if you intend to do scheduling on the secure side, you'll have to set at least SCR.FIQ to 1.
Hi Miao Yu,
well, I can only see that Linux tries to access memory at guest virtual memory address 0x9c82c00c. It depends on: what physical address is mapped to that location. The instruction pointer 0x80042c10 will give you a hint. In principle, you might compile your own Linux binary, and use objdump or instrument the source to find out which physical memory is addressed. By looking at function "mxc_cpu_lp_set" (you can find it in your output, the PC points to it), I assume it's the access to the CPU I/O memory at 0x63fa0000 (ARM PLatform Memory), which causes the data-abort. Have a look at my patches for Linux to run it on my virtual machine monitor at Github:
https://github.com/skalk/linux/tree/imx53-tz
There you'll see, that I've factored out that access. Most of the ARM CortexA8 platform registers can only be accessed from secure, supervisor mode. For more details, have a look at "i.MX53 Multimedia Applications Processor Reference Manual" chapter 11.
Furthermore, I assume you don't run active tasks on the secure side? Because in your current implementation no action from the Linux side will cause a world switch apart from an explicitly triggered one via 'smc' instruction. Otherwise, if you intend to do scheduling on the secure side, you'll have to set at least SCR.FIQ to 1.
Hi Stefan,
Thanks a lot! It works and THAT is the root reason. Yes, I just use SMC to trigger the secure kernel at the moment. Thank you very much! Your project is really helpful.