Shared Memory in tz_vmm demo

Martin Stein martin.stein at ...1...
Thu Apr 14 13:12:41 CEST 2016


Hi Joseph,

Am 14.04.2016 um 02:44 schrieb Joseph Lee:
> I just only commented out line 118 (i.e.,/if (_handle_vm())/) in
> https://github.com/genodelabs/genode/blob/15.11/repos/os/src/server/tz_vmm/spec/imx53/main.cc
> so that the TZ VMM switches to the normal world immediately by invoking
> the run function of the VM session interface. I don't know how to do
> with instruction re-ordering in secure world kernel. Can you please give
> me some hint?

Maybe there is a misconception about the VM session run function. It
does not directly switch to the VM but rather marks it as executable
again. A mere hint for the scheduler. It is up to the Scheduler when to
schedule the VM according to the active subjects and their priorities /
quotas. Assuming that you use the vanilla 'tz_vmm' scenario, there are
additional subjects like the timer or the SD card driver that may be
scheduled in between VMM and VM. And the same applies for the switch
from VM to VMM. You can solve the latter by adding priorities:

<config verbose="yes" prio_levels="1">
	...
	<start name="tz_vmm" priority="0">
		<resource name="CPU" quantum="40"/>
		...
	</start>
	...
</config>

The easiest way to improve the former (VMM to VM) temporarily is by
hacking the priority/quota of VMs in [1] like:

#include <cpu_session/cpu_session.h>

size_t percentage_to_quota(size_t const quota_percentage)
{
	using Genode::Cpu_session;
	using Genode::sizet_arithm_t;
	size_t const tics = cpu_pool()->
	timer()->ms_to_tics(Kernel::cpu_quota_ms);

	size_t quota_user = Cpu_session::
	quota_lim_upscale(quota_percentage, 100);

	return Cpu_session::
	quota_lim_downscale<sizet_arithm_t>(quota_user, tics);
}

Kernel::Vm::Vm(void                   * const state,
               Kernel::Signal_context * const context,
               void                   * const table)
:  Cpu_job(Cpu_priority::MAX-1, percentage_to_quota(40)),
	...

Leaving 20% CPU quota unused ensures that the other subjects don't starve.

> I wonder if you could tell me assembly instructions to measure small
> intervals? i have tried the following but i got 0 value.
> 
> /      asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(t1));
> /
> /        // smc call
> //      asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(t2));
> /
> /      interval = t2 - t1;
> /

As far as I understand, the performance counter you're accessing here
wont help you. It counts processor cycles whereas you like to measure
time. For an MMIO timer, you can do something like:

/* Initialize timer */
unsigned v1 = 0;
unsigned v2 = TIMER_VALUE_REG_BASE;
asm volatile (
	"dsb\n"
	"ldr %1, [%2]\n"
	"dsb\n"
	"smc #0\n"
	"dsb\n"
	"ldr %2, [%2]\n"
	"dsb\n"
	: "=r" (v1), "+r" (v2) : );
unsigned interval = v2 - v1

You may use the FLEXCAN Free Running Timer or the General Purpose Timer
(GPT). You don't want to use the EPIT timers as they are needed by the
secure world for the scheduler and the userland timer that is needed by
the SDHC driver.

The DSB instructions avoid re-ordering. I'm not sure if you need that
many DSBs but as soon as the first DSB is through, the other DSBs
shouldn't cause big overhead.

> how do we measure the time taken to execute some instructions in the
> secure world? 

Cheers,
Martin

[1] base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc




More information about the users mailing list