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....@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...@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