* [Qemu-devel] icount mode
@ 2019-06-24 14:20 Wu, Wentong
2019-06-24 15:47 ` Alex Bennée
0 siblings, 1 reply; 4+ messages in thread
From: Wu, Wentong @ 2019-06-24 14:20 UTC (permalink / raw)
To: qemu-devel
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 factor from qemu timer to SysTick frequency which will be calculated by NANOSECONDS_PER_SECOND / SYSCLK_FRQ.
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!
Also can anyone give some hints about how to give the shift value when use icount TCG mode?
Thanks
Wentong Wu
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] icount mode
2019-06-24 14:20 [Qemu-devel] icount mode Wu, Wentong
@ 2019-06-24 15:47 ` Alex Bennée
2019-06-24 20:43 ` Wu, Wentong
2019-06-25 11:57 ` Wu, Wentong
0 siblings, 2 replies; 4+ messages in thread
From: Alex Bennée @ 2019-06-24 15:47 UTC (permalink / raw)
To: qemu-devel
Wu, Wentong <wentong.wu@intel.com> 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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] icount mode
2019-06-24 15:47 ` Alex Bennée
@ 2019-06-24 20:43 ` Wu, Wentong
2019-06-25 11:57 ` Wu, Wentong
1 sibling, 0 replies; 4+ messages in thread
From: Wu, Wentong @ 2019-06-24 20:43 UTC (permalink / raw)
To: Alex Bennée, qemu-devel
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=intel.com@nongnu.org] On Behalf Of Alex Bennée
Sent: Monday, June 24, 2019 11:48 PM
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] icount mode
Wu, Wentong <wentong.wu@intel.com> 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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] icount mode
2019-06-24 15:47 ` Alex Bennée
2019-06-24 20:43 ` Wu, Wentong
@ 2019-06-25 11:57 ` Wu, Wentong
1 sibling, 0 replies; 4+ messages in thread
From: Wu, Wentong @ 2019-06-25 11:57 UTC (permalink / raw)
To: Alex Bennée, qemu-devel
Hi Alex,
If there is something wrong, please tell me. I really like to have some discusses with Qemu developers about icount mode.
Thanks a lot!
Wentong Wu
-----Original Message-----
From: Wu, Wentong
Sent: Tuesday, June 25, 2019 4:44 AM
To: 'Alex Bennée' <alex.bennee@linaro.org>; qemu-devel@nongnu.org
Subject: RE: [Qemu-devel] icount mode
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=intel.com@nongnu.org] On Behalf Of Alex Bennée
Sent: Monday, June 24, 2019 11:48 PM
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] icount mode
Wu, Wentong <wentong.wu@intel.com> 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
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-06-25 11:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-24 14:20 [Qemu-devel] icount mode Wu, Wentong
2019-06-24 15:47 ` Alex Bennée
2019-06-24 20:43 ` Wu, Wentong
2019-06-25 11:57 ` Wu, Wentong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).