[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 15/46] aspeed/timer: Fix behaviour running Linux
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 15/46] aspeed/timer: Fix behaviour running Linux |
Date: |
Mon, 1 Jul 2019 17:39:12 +0100 |
From: Joel Stanley <address@hidden>
The Linux kernel driver was updated in commit 4451d3f59f2a
("clocksource/drivers/fttmr010: Fix set_next_event handler) to fix an
issue observed on hardware:
> RELOAD register is loaded into COUNT register when the aspeed timer
> is enabled, which means the next event may be delayed because timer
> interrupt won't be generated until <0xFFFFFFFF - current_count +
> cycles>.
When running under Qemu, the system appeared "laggy". The guest is now
scheduling timer events too regularly, starving the host of CPU time.
This patch modifies the timer model to attempt to schedule the timer
expiry as the guest requests, but if we have missed the deadline we
re interrupt and try again, which allows the guest to catch up.
Provides expected behaviour with old and new guest code.
Fixes: c04bd47db6b9 ("hw/timer: Add ASPEED timer device model")
Signed-off-by: Joel Stanley <address@hidden>
Signed-off-by: Cédric Le Goater <address@hidden>
Message-id: address@hidden
[clg: - merged a fix from Andrew Jeffery <address@hidden>
"Fire interrupt on failure to meet deadline"
https://lists.ozlabs.org/pipermail/openbmc/2019-January/014641.html
- adapted commit log
- checkpatch fixes ]
Signed-off-by: Cédric Le Goater <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
---
hw/timer/aspeed_timer.c | 57 ++++++++++++++++++++++-------------------
1 file changed, 30 insertions(+), 27 deletions(-)
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
index 2c3a4d0fe77..537f072cf87 100644
--- a/hw/timer/aspeed_timer.c
+++ b/hw/timer/aspeed_timer.c
@@ -109,37 +109,40 @@ static inline uint64_t calculate_time(struct AspeedTimer
*t, uint32_t ticks)
static uint64_t calculate_next(struct AspeedTimer *t)
{
- uint64_t next = 0;
- uint32_t rate = calculate_rate(t);
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ uint64_t next;
- while (!next) {
- /* We don't know the relationship between the values in the match
- * registers, so sort using MAX/MIN/zero. We sort in that order as the
- * timer counts down to zero. */
- uint64_t seq[] = {
- calculate_time(t, MAX(t->match[0], t->match[1])),
- calculate_time(t, MIN(t->match[0], t->match[1])),
- calculate_time(t, 0),
- };
- uint64_t reload_ns;
- uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ /*
+ * We don't know the relationship between the values in the match
+ * registers, so sort using MAX/MIN/zero. We sort in that order as
+ * the timer counts down to zero.
+ */
- if (now < seq[0]) {
- next = seq[0];
- } else if (now < seq[1]) {
- next = seq[1];
- } else if (now < seq[2]) {
- next = seq[2];
- } else if (t->reload) {
- reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate);
- t->start = now - ((now - t->start) % reload_ns);
- } else {
- /* no reload value, return 0 */
- break;
- }
+ next = calculate_time(t, MAX(t->match[0], t->match[1]));
+ if (now < next) {
+ return next;
}
- return next;
+ next = calculate_time(t, MIN(t->match[0], t->match[1]));
+ if (now < next) {
+ return next;
+ }
+
+ next = calculate_time(t, 0);
+ if (now < next) {
+ return next;
+ }
+
+ /* We've missed all deadlines, fire interrupt and try again */
+ timer_del(&t->timer);
+
+ if (timer_overflow_interrupt(t)) {
+ t->level = !t->level;
+ qemu_set_irq(t->irq, t->level);
+ }
+
+ t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ return calculate_time(t, MAX(MAX(t->match[0], t->match[1]), 0));
}
static void aspeed_timer_mod(AspeedTimer *t)
--
2.20.1
- [Qemu-devel] [PULL 19/46] aspeed: remove the "ram" link, (continued)
- [Qemu-devel] [PULL 19/46] aspeed: remove the "ram" link, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 20/46] aspeed: add a RAM memory region container, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 46/46] target/arm: Declare some M-profile functions publicly, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 24/46] aspeed: vic: Add support for legacy register interface, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 02/46] hw/arm/msf2-som: Exit when the cpu is not the expected one, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 38/46] target/arm: Declare get_phys_addr() function publicly, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 37/46] target/arm: Move CPU state dumping routines to cpu.c, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 06/46] pci: designware: Update MSI mapping unconditionally, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 21/46] aspeed/smc: add a 'sdram_base' property, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 11/46] hw: timer: Add ASPEED RTC device, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 15/46] aspeed/timer: Fix behaviour running Linux,
Peter Maydell <=
- [Qemu-devel] [PULL 03/46] hw/arm/virt: Add support for Cortex-A7, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 04/46] i.mx7d: Add no-op/unimplemented APBH DMA module, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 36/46] target/arm: Move the DC ZVA helper into op_helper, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 29/46] target/arm: Makefile cleanup (ARM), Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 05/46] i.mx7d: Add no-op/unimplemented PCIE PHY IP block, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 13/46] aspeed: introduce a configurable number of CPU per machine, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 07/46] pci: designware: Update MSI mapping when MSI address changes, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 42/46] target/arm/vfp_helper: Extract vfp_set_fpscr_from_host(), Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 40/46] target/arm/vfp_helper: Move code around, Peter Maydell, 2019/07/01
- [Qemu-devel] [PULL 35/46] target/arm: Fix coding style issues, Peter Maydell, 2019/07/01