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/s... 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