qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [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).