Query regarding extracting instruction which caused a data-abort exception

Stefan Kalkowski stefan.kalkowski at ...1...
Fri Jun 23 10:43:07 CEST 2017


On 06/22/2017 07:02 PM, rijurekha at ...71... wrote:
> Thanks a lot Stefan! base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
> and base-hw/src/core/spec/arm_v7/trustzone/mode_transition.s makes the
> memory sharing and register read/write between vmm and vm clearer.
> Further doubts:
> (1)We put three print statements:
> (a) In os/src/server/tz_vmm/spec/imx53/main.cc,
> printf1
> Signal s = _sig_rcv.wait_for_signal()
> printf3
> (b) In base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc,
> printf2
> mtc()->switch_to(reinterpret_cast<Cpu::Context*>(_state), cpu,
> 	                 (addr_t)&_mt_nonsecure_entry_pic,
> 	                 (addr_t)&_tz_client_context);
> printf1 prints once. printf2 prints multiple times, followed by printf3
> (we make uart secure in csu_config.h, so we hit printf3 followed by the
> register dumps). Why do we switch from secure to normal world so many
> times (indicated by multiple printf2), while _sig_rcv.wait_for_signal()?
> What causes a switch back from normal to secure, before the UART related
> abort?

Secure interrupts. Please keep in mind that in your scenario there is
more than the VMM component and the VM. The kernel schedules different
entities, thereby it uses its schedule clock. Probably you also have a
user-land timer for all other components, and maybe additional drivers,
which can use secure interrupts. Each secure interrupt hits the
fast-interrupt exception vector of the monitor mode, and thereby
initiates a world-switch.

> (2) Every time we switch from secure to normal world, .macro
> _secure_to_nonsecure does
> mov   lr, #13
> mcr   p15, 0, lr, c1, c1, 0  /* enable EA, FIQ, and NS bit in SCTRL  */
> So a csu based uart abort in normal world is expected to trap to monitor?


> Are you saying this behavior is something peripheral/vendor specific?

No, I don't meant that whether an external data abort hits the monitor
mode is peripheral/vendor specific, like it is configured above. What I
meant is how a peripheral (e.g.: the CSU) signals a security violation
or error condition is not necessarily determined, and might differ from
peripheral to peripheral. I also said the update of the DFAR and DFSR
register is nothing I would count on. I only observed in my experiments
that DFAR was set to the correct value when the CSU signaled a
data-abort. Therefore, the kernel saved that register to the VM state,
and the VMM dumped it for debugging purposes.

> (3) We suspect that the csu based uart abort doesn't trap to monitor
> handler. If it came to the handler with a DABT excpetion, DFAR would be
> copied to r3 and saved in the memory shared with _state at
> .macro _nonsecure_to_secure
> In that case _state->dfar would give the same value, with and without the
> explicit read in base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
> case Genode::Cpu_state::DATA_ABORT:
> 		state->dfar = Cpu::Dfar::read();
> But we see without this read, _state->dfar prints all zeros, and with this
> read it gives a uart address. So dfar is not saved in the monitor handler,
> and therefore no other register would be saved. Is this understanding
> correct?

No. The DFAR register simply is not saved within the assembler path, but
at a later point using the "read" you refered to. All other relevant
registers are already saved in the assembler path. As I said, reading
out the DFAR was done for debugging purposes only, and enabled at a
later point in time. There was no need to read its value within the
assembler path.

> (4) What does Signal s = _sig_rcv.wait_for_signal(); do in
> os/src/server/tz_vmm/spec/imx53/main.cc? If the uart abort doesn't trap to
> the monitor, what raises the signal so that we come to this main.cc and
> execute the subsequent code like _handle_vm() that calls _vm->dump()? Is
> vmm doing some sort of polling to check cpu exception states in normal
> world?

It waits for all signals registered at the signal receiver. It does not
poll at all. It blocks until a signal arrives. The VM session's signal
context is definitely connected to that signal receiver, so that
whenever the VM produced an exception, e.g. an abort, or smc call, the
VMM gets unblocked. But the signal receiver can be attached to other
signal sources too, e.g.: para-virtual driver backends like a block
session. So in general the VMM can also be woken up by another signal
source, as long as you use para-virtual devices in your scenario, which
is probably not the case if you use the tz_vmm example for the
Quickstart board.

> (5) If abort doesn't trap to monitor, then only dfar and dfsr will hold
> the normal world relevant values, as that was the last abort? The other
> registers will be over-written, as normal world continued to execute,
> until vmm polled it? So emulating the abort causing instruction in secure
> world looks infeasible?

as being said, just do not uncomment DFAR saving, and it will work again.

> (6) Is there a way to print something from
> base-hw/src/core/spec/arm_v7/trustzone/mode_transition.s? Most of the
> actions happen here, but we are not able to trace when those macros are
> executed.

Not easily, you can write your own assembler macro that writes to the
UART directly. But changing anything there is very much error-prone. If
you have a JTAG adapter you should use that instead.


> Thanks for your constant assistance.
> Riju
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> genode-main mailing list
> genode-main at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/genode-main

Stefan Kalkowski
Genode Labs

https://github.com/skalk ยท http://genode.org/

More information about the users mailing list