qemu: aspeed_timer: Use signed muldiv for timer resets
PATCH 1/1 qemu: aspeed_timer: Use signed muldiv for timer resets
If the host decrements the counter register that results in a negative delta. This is then passed to muldiv64 which only handles unsigned numbers resulting in bogus results.
This fix ensures the data being operated on is signed before it is ultimately casted to the final unsigned value.
Test case: kexec a kernel using aspeed_timer and it will freeze on the second bootup when the kernel initializes the timer. With this patch that no longer happens and the timer appears to run OK.
--- hw/timer/aspeed_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/timer/aspeed_timer.c +1 -1
@@ -253,7 +253,7 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,int64_t delta = (int64_t ) value - (int64_t )calculate_ticks (t, now);uint32_t rate =calculate_rate (t); - t->start +=muldiv64 (delta,NANOSECONDS_PER_SECOND , rate); + t->start = (int64_t )t->start + ((__int128_t )delta *NANOSECONDS_PER_SECOND / rate);aspeed_timer_mod (t); }break ;
Signature · 1 line
2.19.1.930.g4563a0d9d0-goog
Hi
Quoted 5 lines · Cédric Le Goater
isn't QEMU using the helpers from :
include/qemu/host-utils.hwhich do about the same ?
Multdiv64 only takes unsigned ints, and while I'm not familiar with the details of how that propagates to the division, it seems to result in nonsensical values for negative inputs.
Before copying this logic here I looked for an equivalent for signed ints but did not find any suitable one, and the expansion seemed simple enough.
You can see more details in
https://github.com/openbmc/qemu/issues/14#issuecomment-437692215.
Quoted 21 lines · Christian Svensson
If the host decrements the counter register that results in a negative delta. This is then passed to muldiv64 which only handles unsigned numbers resulting in bogus results.
This fix ensures the data being operated on is signed before it is ultimately casted to the final unsigned value.
Test case: kexec a kernel using
aspeed_timerand it will freeze on the second bootup when the kernel initializes the timer. With this patch that no longer happens and the timer appears to run OK.Signed-off-by Christian Svensson <[email protected]>--- hw/timer/aspeed_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)hw/timer/aspeed_timer.c +0
-0
hw/timer/aspeed_timer.c static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg, · line 256
Quoted 5 lines
hw/timer/aspeed_timer.c +1
-1@@ -253,7 +253,7 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,int64_t delta = (int64_t ) value - (int64_t )calculate_ticks (t, now);uint32_t rate =calculate_rate (t); - t->start +=muldiv64 (delta,NANOSECONDS_PER_SECOND , rate); + t->start = (int64_t )t->start + ((__int128_t )delta *NANOSECONDS_PER_SECOND / rate);
isn't QEMU using the helpers from :
include/qemu/host-utils.h
which do about the same ?
Thanks,
C.
Quoted 4 lines
hw/timer/aspeed_timer.c +0
-0aspeed_timer_mod (t); }break ;
Quoted 8 lines · Christian Svensson
Hi
Quoted 5 lines · Cédric Le Goater
isn't QEMU using the helpers from :
include/qemu/host-utils.hwhich do about the same ?
Quoted 8 lines
Multdiv64 only takes unsigned ints, and while I'm not familiar with the details of how that propagates to the division, it seems to result in nonsensical values for negative inputs.
Before copying this logic here I looked for an equivalent for signed ints but did not find any suitable one, and the expansion seemed simple enough.You can see more details in
https://github.com/openbmc/qemu/issues/14#issuecomment-437692215.
By inspection the concept of the patch seems okay to me. However, the issue that host-utils.h takes care of in addition to providing helpers is support for those helpers on systems that don't support 128-bit integers. The patch should be sent to the upstream lists, and I don't think we should be breaking qemu-arm-* generally for systems that we might not care about.
Andrew
Quoted 1 line · Andrew Jeffery
By inspection the concept of the patch seems okay to me. However, the
issue
Quoted 1 line
that
host-utils.htakes care of in addition to providing helpers is
support for
Quoted 1 line
those helpers on systems that don't support 128-bit integers. The patch
should
Quoted 2 lines
be sent to the upstream lists, and I don't think we should be breaking qemu-arm-* generally for systems that we might not care about.
Ah, yes - I missed that there were two - one for systems with int128 and one for them
without. Hm, that does complicate things.
Given that we only have one operand that is ever negative, how do you feel about a patch
that goes along the lines of:
if (delta >= 0) {
t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
} else {
t->start = (int64_t)t->start - muldiv64(-delta, NANOSECONDS_PER_SECOND,
rate);
}
That should avoid any issues I think, save us/me from implementing a signed muldiv,
but cost a bit on the readable code side.
Ping. What's left to be done here?
Quoted 32 lines · Christian Svensson
Quoted 1 line · Andrew Jeffery
By inspection the concept of the patch seems okay to me. However, the
issue
Quoted 1 line
that
host-utils.htakes care of in addition to providing helpers issupport for
Quoted 1 line
those helpers on systems that don't support 128-bit integers. The patch
should
Quoted 2 lines
be sent to the upstream lists, and I don't think we should be breaking qemu-arm-* generally for systems that we might not care about.
Ah, yes - I missed that there were two - one for systems with int128 and one for them
without. Hm, that does complicate things.Given that we only have one operand that is ever negative, how do you feel about a patch
that goes along the lines of:if (delta >= 0) {
t->start+=muldiv64(delta, NANOSECONDS_PER_SECOND, rate);} else { t->start = (int64_t)t->start - muldiv64(-delta, NANOSECONDS_PER_SECOND,rate);
}That should avoid any issues I think, save us/me from implementing a signed muldiv,
but cost a bit on the readable code side.
Quoted 1 line · Christian Svensson
Ping. What's left to be done here?
I've taken Cedric's tree and pushed it to openbmc/qemu master, so the patch is there. Did you send it upstream originally? That's where it should go, but that will probably require fixing the issue I pointed out last time.
Andrew
Quoted 35 lines · Christian Svensson
Quoted 33 lines · Andrew Jeffery
Quoted 1 line
By inspection the concept of the patch seems okay to me. However, the
issue
Quoted 1 line
that
host-utils.htakes care of in addition to providing helpers issupport for
Quoted 1 line
those helpers on systems that don't support 128-bit integers. The patch
should
Quoted 2 lines
be sent to the upstream lists, and I don't think we should be breaking qemu-arm-* generally for systems that we might not care about.
Ah, yes - I missed that there were two - one for systems with int128 and one for them
without. Hm, that does complicate things.Given that we only have one operand that is ever negative, how do you feel about a patch
that goes along the lines of:if (delta >= 0) {
t->start+=muldiv64(delta, NANOSECONDS_PER_SECOND, rate);} else { t->start = (int64_t)t->start - muldiv64(-delta, NANOSECONDS_PER_SECOND,rate);
}That should avoid any issues I think, save us/me from implementing a signed muldiv,
but cost a bit on the readable code side.
Quoted 8 lines · On Mon, Jan 14, 2019, 03:14 Andrew Jeffery <[email protected] wrote:
Quoted 1 line · Christian Svensson
Ping. What's left to be done here?
I've taken Cedric's tree and pushed it to openbmc/qemu master, so the patch is there. Did you send it upstream originally? That's where it should go, but that
will probably require fixing the issue I pointed out last time.
Ah, wierd, I swore I checked the repository last week but I must have checked my own fork or something. Thanks for pulling the patch.
As for fixing the issues, any specific concerns with the proposal I replied with back in November?
Thanks,
Quoted 11 lines · Christian Svensson
Quoted 8 lines · On Mon, Jan 14, 2019, 03:14 Andrew Jeffery <[email protected] wrote:
Quoted 1 line · Christian Svensson
Ping. What's left to be done here?
I've taken Cedric's tree and pushed it to openbmc/qemu master, so the patch is there. Did you send it upstream originally? That's where it should go, but that
will probably require fixing the issue I pointed out last time.
Quoted 5 lines
Ah, wierd, I swore I checked the repository last week but I must have checked my own fork or something. Thanks for pulling the patch.
As for fixing the issues, any specific concerns with the proposal I replied with back in November?
Sorry for the late reply here. What was the suggestion? I'll try to find the thread in the mean time.
Andrew