[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] icount mode
From: |
Wu, Wentong |
Subject: |
Re: [Qemu-devel] icount mode |
Date: |
Mon, 24 Jun 2019 20:43:31 +0000 |
Hi Alex,
Thanks for your reply.
For the different frequencies, please see below code in armv7m_systick.c and
mps2.c first, the s->reload will be set by the guest os code according to the
CPU's frequency which will be SYSCLK_FRQ, and s->tick will be set as "s->tick
+= (s->reload + 1) * systick_scale(s);", it means the frequency of this timer
which I called qemu timer will be NANOSECONDS_PER_SECOND.
static void systick_reload(SysTickState *s, int reset)
{
/* The Cortex-M3 Devices Generic User Guide says that "When the
* ENABLE bit is set to 1, the counter loads the RELOAD value from the
* SYST RVR register and then counts down". So, we need to check the
* ENABLE bit before reloading the value.
*/
trace_systick_reload();
if ((s->control & SYSTICK_ENABLE) == 0) {
return;
}
if (reset) {
s->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
s->tick += (s->reload + 1) * systick_scale(s);
timer_mod(s->timer, s->tick);
}
static void mps2_common_init(MachineState *machine)
{
...
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
...
}
But for below code, it will use qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) to get
the current time which will be calculated by 2^N ns * instruction counter, but
this frequency will be NANOSECONDS_PER_SECOND / 2^N. Below code is an example
two different frequencies are used, actually in cpus.c,
qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL) will use the qemu timer(freq is
NANOSECONDS_PER_SECOND), and cpu_icount_to_ns will calcaute time with frequency
NANOSECONDS_PER_SECOND / 2^N.
static void systick_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
SysTickState *s = opaque;
trace_systick_write(addr, value, size);
switch (addr) {
case 0x0: /* SysTick Control and Status. */
{
uint32_t oldval = s->control;
s->control &= 0xfffffff8;
s->control |= value & 7;
if ((oldval ^ value) & SYSTICK_ENABLE) {
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (value & SYSTICK_ENABLE) {
if (s->tick) {
s->tick += now;
timer_mod(s->timer, s->tick);
} else {
systick_reload(s, 1);
}
} else {
timer_del(s->timer);
s->tick -= now;
if (s->tick < 0) {
s->tick = 0;
}
}
} else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
/* This is a hack. Force the timer to be reloaded
when the reference clock is changed. */
systick_reload(s, 1);
}
break;
}
case 0x4: /* SysTick Reload Value. */
s->reload = value;
break;
......
Yes, I'm for the for determinism, in my guest image there are some testing
cases for timer system which locate in a small rtos.
And for shift value, I mean it seems shift value impact system greatly, for the
same one guest image and different shift value in count mode(-icount
shift=4,align=off,sleep=off -rtc clock=vm) give very different accuracy for
guest timer. So my question is how to calculate the shift value for the end
user.
Thanks again for your help.
Thanks
-----Original Message-----
From: Qemu-devel [mailto:qemu-devel-bounces+wentong.wu=address@hidden] On
Behalf Of Alex Bennée
Sent: Monday, June 24, 2019 11:48 PM
To: address@hidden
Subject: Re: [Qemu-devel] icount mode
Wu, Wentong <address@hidden> writes:
> Hi all,
>
> Recently I'm using Qemu TCG icount mode, from the code I found Qemu
> timers run at 1GHz, and for ArmV7M example, there will be conversion
Are you talking about:
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
because as far as I can tell that only affects the scaling factors applied to
PMU counters. The internal counters (CNTFRQ_EL0 and friends) are hardwired to:
/* Scale factor for generic timers, ie number of ns per tick.
* This gives a 62.5MHz timer.
*/
#define GTIMER_SCALE 16
but this only affects the nominal rate the counters expire at. Software could
attempt to reprogram it and the emulation will read-as-written but it won't
actually change anything. However this only affects the clocks
- it implies nothing about how fast the core may be executing. In fact unless
you are using icount we will just run as fast a possible.
> factor from qemu timer to SysTick frequency which will be calculated
> by NANOSECONDS_PER_SECOND / SYSCLK_FRQ.
You need to be a little more precise here. ARM systems vary in the number of
timer sources they have. The qemu timers are an internal implementation detail
for providing a way to track time. The value of SYSCLK_FRQ varies depending on
what board you have launched and mostly seems to be used to calculate the
additional timer values for various peripherals.
> But the shift value also define the target cpu frequency(2^N ns /one
> instruction), and both frequencies will be used together to calculate
> the guest timer, so I think there is buggy because of the different
> frequency, can anyone give some explanation for this? Thanks a lot!
All icount does is peg the elapsed virtual time to the number of instructions
executed (the instruction count). This means whenever the code requests:
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
Instead of returning the number of ns the guest has been running based on
elapsed host time it will return the number of instructions run shifted by
icount_shift. So with higher shift values each instruction sees an increased
amount of virtual time pass - the practical effect will be you see less
instructions executed between timer interrupts.
>
> Also can anyone give some hints about how to give the shift value when
> use icount TCG mode?
$QEMU $QEMU_ARGS -icount N
or
$QEMU $QEMU_ARGS -icount shift=N
What is your interest in icount? Is it purely for determinism?
--
Alex Bennée