* [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time @ 2018-11-27 21:07 Bijan Mottahedeh 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically Bijan Mottahedeh ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: Bijan Mottahedeh @ 2018-11-27 21:07 UTC (permalink / raw) To: qemu-devel; +Cc: kvmarm v1 -> v2: - Call the asm code only for kvm and always use the default value for TCG. This patch series address two Qemu issues: - improper system clock frequency initialization - lack of pause (virtsh suspend) time accounting A simple test to reproduce the problem executes one or more instances of the following command in the guest: dd if=/dev/zero of=/dev/null & and then pauses and resumes the guest after a certain delay: virsh suspend <guest> # pauses the guest sleep 120 virsh resume <guest> After the guest is resumed, there are soft lockup warning messages displayed on the console. A comparison with x86 shows that hwclock and date values diverge after the above pause and resume sequence for x86 but remain the same for Arm. Patch 1 intializes the system clock frequency in Qemu similar to the kernel. Patch 2 accumulates the total guest pause time in QEMU and adjusts the virtual offset counter accordingly before the guest is resumed. The patches have been tested on an Ampere system. With the patches the time behavior is the same as x86 and the soft lockup messages go away. Clock Frequency Initialization ============================== Arm v8 provides the virtual counter (cntvct), virtual counter offset (cntvoff), and counter frequency (cntfrq) registers for guest time management. Linux Arm platform code initializes the system clock frequency from cntrfq_el0 register and sets the value into a statically created device tree (DT) node. It is not clear why the timer device node is created with TIMER_OF_DECLARE(). The DT passed from Qemu to the kernel does not contain a timer node. drivers/clocksource/arm_arch_timer.c: static inline u32 arch_timer_get_cntfrq(void) { return read_sysreg(cntfrq_el0); } rate = arch_timer_get_cntfrq(); arch_timer_of_configure_rate(rate, np); /* * For historical reasons, when probing with DT we use whichever (non-zero) * rate was probed first, and don't verify that others match. If the first node * probed has a clock-frequency property, this overrides the HW register. */ static void arch_timer_of_configure_rate(u32 rate, struct device_node *np) { ... if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { arch_timer_rate = rate; ... } TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); Linux then initializes the clock frequency to 50MHZ. Qemu however hard codes the clock frequency to 62.5MHZ. target/arm/cpu.h: /* Scale factor for generic timers, ie number of ns per tick. * This gives a 62.5MHz timer. */ #define GTIMER_SCALE 16 The suggested fix is to follow the kernel's arch_timer_get_cntfrq() approach in order to set system_clock_scale to match the kernel's idea of clock-frequency, rather than using a hard-coded value. Ultimately, it seems that Qemu should construct the timer DT node and pass the actual clock frequency value to the kernel that way but that brings up an interface and backward compatibility considerations. Furthermore, the implications for ACPI method of probing is not clear. Pause Time Accounting ===================== Linux registers two clock sources, a platform-independent jiffies clocksource and a Arm-specific arch_sys_counter; the read interface for the latter reads the virtual counter register: static struct clocksource clocksource_jiffies = { .name = "jiffies", .rating = 1, /* lowest valid rating*/ .read = jiffies_read, .mask = CLOCKSOURCE_MASK(32), .mult = TICK_NSEC << JIFFIES_SHIFT, /* details above */ .shift = JIFFIES_SHIFT, .max_cycles = 10, }; static struct clocksource clocksource_counter = { .name = "arch_sys_counter", .rating = 400, .read = arch_counter_read, .mask = CLOCKSOURCE_MASK(56), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; arch_counter_read() -> arch_timer_read_counter() -> arch_counter_get_cntvct() -> arch_timer_reg_read_stable(cntvct_el0) The virtual counter offset register is set from: kvm_timer_vcpu_load() -> set_cntvoff() The counter is zeroed from: kvm_timer_vcpu_put() -> set_cntvoff() /* * The kernel may decide to run userspace after calling vcpu_put, so * we reset cntvoff to 0 to ensure a consistent read between user * accesses to the virtual counter and kernel access to the physical * counter of non-VHE case. For VHE, the virtual counter uses a fixed * virtual offset of zero, so no need to zero CNTVOFF_EL2 register. */ if (!has_vhe()) set_cntvoff(0); The virtual counter offset is not modified anywhere however to account for pause time. The suggested fix is to add pause time accounting to Qemu. One potential issue is whether modifying the virtual counter offset breaks any assumptions, e.g., see the kvm_timer_vcpu_put() comment above. hwclock vs. date ================ The hwclock on the ends up in drivers/rtc/rtc-pl031.c Real Time Clock interface for ARM AMBA PrimeCell 031 RTC ioctl("/dev/rtc", RTC_RD_TIME, ...) -> rtc_dev_ioctl() -> rtc_read_time() -> __rtc_read_time() -> pl031_read_time() The date command reads time from from a vdso page updated as follows: irq_enter() -> tick_irq_enter() -> tick_nohz_irq_enter() -> tick_nohz_update_jiffies() -> tick_do_update_jiffies64() -> tick_do_update_jiffies64() -> update_wall_time() -> timekeeping_advance() -> timekeeping_update() -> update_vsyscall(struct timekeepr *tk) The struct timekeeper uses the Arm platform clocksource_counter noted above: (gdb) p tk->tkr_mono $4 = {clock = 0xffff0000097ddad0 <clocksource_counter>, mask = 72057594037927935, cycle_last = 271809294296, mult = 335544320, shift = 24, xtime_nsec = 3456106496000000, base = 5435795172160, base_real = 1539126455000000000} This would explain why without any pause time accounting, the both hwclock and date command show the same time after the guest is resume from a pause, e.g. with the following sequence: virsh suspend <guest> sleep <seconds> virsh resume <guest> Bijan Mottahedeh (2): arm/virt: Initialize generic timer scale factor dynamically arm/virt: Account for guest pause time hw/arm/virt.c | 17 +++++++++++++++++ hw/intc/arm_gicv3_kvm.c | 39 +++++++++++++++++++++++++++++++++++++++ target/arm/cpu.h | 3 +++ target/arm/helper.c | 19 ++++++++++++++++--- target/arm/internals.h | 8 ++++++-- target/arm/kvm64.c | 1 + 6 files changed, 82 insertions(+), 5 deletions(-) -- 1.8.3.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically 2018-11-27 21:07 [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time Bijan Mottahedeh @ 2018-11-27 21:07 ` Bijan Mottahedeh 2019-09-23 18:36 ` Masayoshi Mizuma 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 2/2] arm/virt: Account for guest pause time Bijan Mottahedeh 2018-11-29 14:40 ` [Qemu-devel] [RFC QEMU v2 0/2] " no-reply 2 siblings, 1 reply; 5+ messages in thread From: Bijan Mottahedeh @ 2018-11-27 21:07 UTC (permalink / raw) To: qemu-devel; +Cc: kvmarm Initialize the generic timer scale factor based on the counter frequency register cntfrq_el0, and default to the current static value if necessary. Always use the default value for TCG. Signed-off-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com> --- hw/arm/virt.c | 17 +++++++++++++++++ target/arm/helper.c | 19 ++++++++++++++++--- target/arm/internals.h | 8 ++++++-- target/arm/kvm64.c | 1 + 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 281ddcd..792d223 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -59,6 +59,7 @@ #include "qapi/visitor.h" #include "standard-headers/linux/input.h" #include "hw/arm/smmuv3.h" +#include "target/arm/internals.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -1710,6 +1711,21 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, return NULL; } +static void set_system_clock_scale(void) +{ + unsigned long cntfrq_el0 = 0; + +#ifdef CONFIG_KVM + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); +#endif + + if (cntfrq_el0 == 0) { + cntfrq_el0 = GTIMER_SCALE_DEF; + } + + system_clock_scale = NANOSECONDS_PER_SECOND / (int)cntfrq_el0; +} + static void virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1736,6 +1752,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) assert(!mc->get_hotplug_handler); mc->get_hotplug_handler = virt_machine_get_hotplug_handler; hc->plug = virt_machine_device_plug_cb; + set_system_clock_scale(); } static const TypeInfo virt_machine_info = { diff --git a/target/arm/helper.c b/target/arm/helper.c index 66afb08..6330586 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -18,6 +18,7 @@ #include "sysemu/kvm.h" #include "fpu/softfloat.h" #include "qemu/range.h" +#include "hw/arm/arm.h" #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ @@ -1614,6 +1615,18 @@ static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } +static void gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + assert(GTIMER_SCALE); + assert(ri->fieldoffset); + + if (cpreg_field_is_64bit(ri)) { + CPREG_FIELD64(env, ri) = NANOSECONDS_PER_SECOND / GTIMER_SCALE; + } else { + CPREG_FIELD32(env, ri) = NANOSECONDS_PER_SECOND / GTIMER_SCALE; + } +} + static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx, bool isread) { @@ -1709,7 +1722,7 @@ static CPAccessResult gt_stimer_access(CPUARMState *env, } } -static uint64_t gt_get_countervalue(CPUARMState *env) +uint64_t gt_get_countervalue(CPUARMState *env) { return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE; } @@ -1996,7 +2009,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access, .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), - .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE, + .resetfn = gt_cntfrq_reset, }, /* overall control: mostly access permissions */ { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH, @@ -2187,7 +2200,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, .type = ARM_CP_CONST, .access = PL0_R /* no PL1_RW in linux-user */, .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), - .resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE, + .resetfn = gt_cntfrq_reset, }, { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2, diff --git a/target/arm/internals.h b/target/arm/internals.h index dc93577..b66a1fa 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -52,9 +52,13 @@ static inline bool excp_is_internal(int excp) } /* Scale factor for generic timers, ie number of ns per tick. - * This gives a 62.5MHz timer. + * Calculated dynamically based on CNTFRQ with a default value + * that gives a 62.5MHZ timer. */ -#define GTIMER_SCALE 16 +#define GTIMER_SCALE system_clock_scale +#define GTIMER_SCALE_DEF 16 + +uint64_t gt_get_countervalue(CPUARMState *); /* Bit definitions for the v7M CONTROL register */ FIELD(V7M_CONTROL, NPRIV, 0, 1) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index e0b8246..5d1c394 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -485,6 +485,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) set_feature(&features, ARM_FEATURE_NEON); set_feature(&features, ARM_FEATURE_AARCH64); set_feature(&features, ARM_FEATURE_PMU); + set_feature(&features, ARM_FEATURE_GENERIC_TIMER); ahcf->features = features; -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically Bijan Mottahedeh @ 2019-09-23 18:36 ` Masayoshi Mizuma 0 siblings, 0 replies; 5+ messages in thread From: Masayoshi Mizuma @ 2019-09-23 18:36 UTC (permalink / raw) To: Bijan Mottahedeh; +Cc: qemu-devel, kvmarm Hi, This issue remains on the latest qemu, right? Let me add some comments for the patch. On Tue, Nov 27, 2018 at 01:07:16PM -0800, Bijan Mottahedeh wrote: > Initialize the generic timer scale factor based on the counter frequency > register cntfrq_el0, and default to the current static value if necessary. > Always use the default value for TCG. > > Signed-off-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com> > --- > hw/arm/virt.c | 17 +++++++++++++++++ > target/arm/helper.c | 19 ++++++++++++++++--- > target/arm/internals.h | 8 ++++++-- > target/arm/kvm64.c | 1 + > 4 files changed, 40 insertions(+), 5 deletions(-) > > diff --git a/hw/arm/virt.c b/hw/arm/virt.c > index 281ddcd..792d223 100644 > --- a/hw/arm/virt.c > +++ b/hw/arm/virt.c > @@ -59,6 +59,7 @@ > #include "qapi/visitor.h" > #include "standard-headers/linux/input.h" > #include "hw/arm/smmuv3.h" > +#include "target/arm/internals.h" > > #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ > static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ > @@ -1710,6 +1711,21 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, > return NULL; > } > > +static void set_system_clock_scale(void) > +{ > + unsigned long cntfrq_el0 = 0; > + > +#ifdef CONFIG_KVM > + asm volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq_el0)); > +#endif > + > + if (cntfrq_el0 == 0) { > + cntfrq_el0 = GTIMER_SCALE_DEF; > + } > + > + system_clock_scale = NANOSECONDS_PER_SECOND / (int)cntfrq_el0; > +} > + > static void virt_machine_class_init(ObjectClass *oc, void *data) > { > MachineClass *mc = MACHINE_CLASS(oc); > @@ -1736,6 +1752,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) > assert(!mc->get_hotplug_handler); > mc->get_hotplug_handler = virt_machine_get_hotplug_handler; > hc->plug = virt_machine_device_plug_cb; > + set_system_clock_scale(); > } > > static const TypeInfo virt_machine_info = { > diff --git a/target/arm/helper.c b/target/arm/helper.c > index 66afb08..6330586 100644 > --- a/target/arm/helper.c > +++ b/target/arm/helper.c > @@ -18,6 +18,7 @@ > #include "sysemu/kvm.h" > #include "fpu/softfloat.h" > #include "qemu/range.h" > +#include "hw/arm/arm.h" arm.h is renamed to boot.h, so: #include "hw/arm/boot.h" > > #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ > > @@ -1614,6 +1615,18 @@ static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri, > return CP_ACCESS_OK; > } > > +static void gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *ri) > +{ > + assert(GTIMER_SCALE); > + assert(ri->fieldoffset); > + > + if (cpreg_field_is_64bit(ri)) { > + CPREG_FIELD64(env, ri) = NANOSECONDS_PER_SECOND / GTIMER_SCALE; > + } else { > + CPREG_FIELD32(env, ri) = NANOSECONDS_PER_SECOND / GTIMER_SCALE; > + } > +} > + > static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx, > bool isread) > { > @@ -1709,7 +1722,7 @@ static CPAccessResult gt_stimer_access(CPUARMState *env, > } > } > > -static uint64_t gt_get_countervalue(CPUARMState *env) > +uint64_t gt_get_countervalue(CPUARMState *env) > { > return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE; > } > @@ -1996,7 +2009,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { > .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, > .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access, > .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), > - .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE, > + .resetfn = gt_cntfrq_reset, Build error is here on the target aarch64-linux-user, like as: /home/foo/qemu/target/arm/helper.c:2901:18: error: 'gt_cntfrq_reset' undeclared here (not in a function); did you mean 'g_timer_reset'? .resetfn = gt_cntfrq_reset, ^~~~~~~~~~~~~~~ The issue doesn't affect to aarch64-linux-user, right? If so: #ifdef CONFIG_LINUX_USER .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE, #else .resetfn = gt_cntfrq_reset, #endif > }, > /* overall control: mostly access permissions */ > { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH, > @@ -2187,7 +2200,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { > .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, > .type = ARM_CP_CONST, .access = PL0_R /* no PL1_RW in linux-user */, > .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), > - .resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE, > + .resetfn = gt_cntfrq_reset, Same as above. > }, > { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64, > .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2, > diff --git a/target/arm/internals.h b/target/arm/internals.h > index dc93577..b66a1fa 100644 > --- a/target/arm/internals.h > +++ b/target/arm/internals.h > @@ -52,9 +52,13 @@ static inline bool excp_is_internal(int excp) > } > > /* Scale factor for generic timers, ie number of ns per tick. > - * This gives a 62.5MHz timer. > + * Calculated dynamically based on CNTFRQ with a default value > + * that gives a 62.5MHZ timer. > */ > -#define GTIMER_SCALE 16 > +#define GTIMER_SCALE system_clock_scale > +#define GTIMER_SCALE_DEF 16 I think extern for system_clock_scale should be added here, otherwise the build error happens. If the issue doesn't affect to aarch64-linux-user, how about the following? #ifndef CONFIG_LINUX_USER extern int system_clock_scale; #define GTIMER_SCALE system_clock_scale #define GTIMER_SCALE_DEF 16 #else #define GTIMER_SCALE 16 #endif > + > +uint64_t gt_get_countervalue(CPUARMState *); > > /* Bit definitions for the v7M CONTROL register */ > FIELD(V7M_CONTROL, NPRIV, 0, 1) > diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c > index e0b8246..5d1c394 100644 > --- a/target/arm/kvm64.c > +++ b/target/arm/kvm64.c > @@ -485,6 +485,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) > set_feature(&features, ARM_FEATURE_NEON); > set_feature(&features, ARM_FEATURE_AARCH64); > set_feature(&features, ARM_FEATURE_PMU); > + set_feature(&features, ARM_FEATURE_GENERIC_TIMER); > > ahcf->features = features; Thanks, Masa ^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [RFC QEMU v2 2/2] arm/virt: Account for guest pause time 2018-11-27 21:07 [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time Bijan Mottahedeh 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically Bijan Mottahedeh @ 2018-11-27 21:07 ` Bijan Mottahedeh 2018-11-29 14:40 ` [Qemu-devel] [RFC QEMU v2 0/2] " no-reply 2 siblings, 0 replies; 5+ messages in thread From: Bijan Mottahedeh @ 2018-11-27 21:07 UTC (permalink / raw) To: qemu-devel; +Cc: kvmarm Accumulate the total guest pause time and update the virtual counter offset register accordingly in order to account for that time before resuming the guest. Signed-off-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com> --- hw/intc/arm_gicv3_kvm.c | 39 +++++++++++++++++++++++++++++++++++++++ target/arm/cpu.h | 3 +++ 2 files changed, 42 insertions(+) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 1e11200..aabd508 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -30,6 +30,7 @@ #include "gicv3_internal.h" #include "vgic_common.h" #include "migration/blocker.h" +#include "target/arm/internals.h" #ifdef DEBUG_GICV3_KVM #define DPRINTF(fmt, ...) \ @@ -745,9 +746,38 @@ static void vm_change_state_handler(void *opaque, int running, { GICv3State *s = (GICv3State *)opaque; Error *err = NULL; + CPUState *cpu; + CPUARMState *env; + struct kvm_one_reg reg; int ret; + uint64_t cnt; if (running) { + CPU_FOREACH(cpu) { + + env = (CPUARMState *)(cpu->env_ptr); + + if (!env->pause_start) { + continue; + } + + /* + * Accumulate the total pause time and set the + * counter virtual offset accordingly. + */ + cnt = gt_get_countervalue(env); + env->pause_total += (cnt - env->pause_start); + env->cp15.cntvoff_el2 = cnt - env->pause_total; + + env->pause_start = 0; /* clear for next pause */ + reg.id = KVM_REG_ARM_TIMER_CNT; + reg.addr = (uintptr_t) &env->cp15.cntvoff_el2; + ret = kvm_vcpu_ioctl(cpu, KVM_SET_ONE_REG, ®); + if (ret) { + error_report("Set virtual counter offset failed: %d", ret); + abort(); + } + } return; } @@ -760,6 +790,15 @@ static void vm_change_state_handler(void *opaque, int running, if (ret < 0 && ret != -EFAULT) { abort(); } + + CPU_FOREACH(cpu) { + /* + * Record the current pause start time. + */ + env = (CPUARMState *)(cpu->env_ptr); + cnt = gt_get_countervalue(env); + env->pause_start = cnt; + } } diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e310ffc..bd0a56e 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -602,6 +602,9 @@ typedef struct CPUARMState { struct CPUBreakpoint *cpu_breakpoint[16]; struct CPUWatchpoint *cpu_watchpoint[16]; + uint64_t pause_start; /* start time of last pause */ + uint64_t pause_total; /* total pause time */ + /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time 2018-11-27 21:07 [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time Bijan Mottahedeh 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically Bijan Mottahedeh 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 2/2] arm/virt: Account for guest pause time Bijan Mottahedeh @ 2018-11-29 14:40 ` no-reply 2 siblings, 0 replies; 5+ messages in thread From: no-reply @ 2018-11-29 14:40 UTC (permalink / raw) To: bijan.mottahedeh; +Cc: famz, qemu-devel, kvmarm Hi, This series seems to have some coding style problems. See output below for more information: Type: series Subject: [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time Message-id: 1543352837-21529-1-git-send-email-bijan.mottahedeh@oracle.com === TEST SCRIPT BEGIN === #!/bin/bash BASE=base n=1 total=$(git log --oneline $BASE.. | wc -l) failed=0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..." if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then failed=1 echo fi n=$((n+1)) done exit $failed === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' bf7b6dc arm/virt: Account for guest pause time 21423f4 arm/virt: Initialize generic timer scale factor dynamically === OUTPUT BEGIN === Checking PATCH 1/2: arm/virt: Initialize generic timer scale factor dynamically... ERROR: exactly one space required after that #ifdef #33: FILE: hw/arm/virt.c:1757: +#ifdef CONFIG_KVM total: 1 errors, 0 warnings, 106 lines checked Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Checking PATCH 2/2: arm/virt: Account for guest pause time... === OUTPUT END === Test command exited with code: 1 --- Email generated automatically by Patchew [http://patchew.org/]. Please send your feedback to patchew-devel@redhat.com ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-09-23 18:38 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-11-27 21:07 [Qemu-devel] [RFC QEMU v2 0/2] arm/virt: Account for guest pause time Bijan Mottahedeh 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 1/2] arm/virt: Initialize generic timer scale factor dynamically Bijan Mottahedeh 2019-09-23 18:36 ` Masayoshi Mizuma 2018-11-27 21:07 ` [Qemu-devel] [RFC QEMU v2 2/2] arm/virt: Account for guest pause time Bijan Mottahedeh 2018-11-29 14:40 ` [Qemu-devel] [RFC QEMU v2 0/2] " no-reply
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).