From: Nicholas Piggin <npiggin@gmail.com>
To: Daniel Henrique Barboza <danielhb413@gmail.com>
Cc: "Nicholas Piggin" <npiggin@gmail.com>,
"Cédric Le Goater" <clg@kaod.org>,
"David Gibson" <david@gibson.dropbear.id.au>,
"Greg Kurz" <groug@kaod.org>,
"Harsh Prateek Bora" <harshpb@linux.ibm.com>,
"Pavel Dovgalyuk" <pavel.dovgaluk@ispras.ru>,
"Paolo Bonzini" <pbonzini@redhat.com>,
qemu-ppc@nongnu.org, qemu-devel@nongnu.org
Subject: [PATCH v2 12/19] hw/ppc: Read time only once to perform decrementer write
Date: Tue, 8 Aug 2023 14:19:54 +1000 [thread overview]
Message-ID: <20230808042001.411094-13-npiggin@gmail.com> (raw)
In-Reply-To: <20230808042001.411094-1-npiggin@gmail.com>
Reading the time more than once to perform an operation always increases
complexity and fragility due to introduced deltas. Simplify the
decrementer write by reading the clock once for the operation.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
hw/ppc/ppc.c | 84 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 53 insertions(+), 31 deletions(-)
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index f391acc39e..a0ee064b1d 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -708,13 +708,13 @@ bool ppc_decr_clear_on_delivery(CPUPPCState *env)
return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
}
-static inline int64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+static inline int64_t __cpu_ppc_load_decr(CPUPPCState *env, int64_t now,
+ uint64_t next)
{
ppc_tb_t *tb_env = env->tb_env;
- uint64_t now, n;
+ uint64_t n;
int64_t decr;
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
n = ns_to_tb(tb_env->decr_freq, now);
if (next > n && tb_env->flags & PPC_TIMER_BOOKE) {
decr = 0;
@@ -727,16 +727,12 @@ static inline int64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
return decr;
}
-target_ulong cpu_ppc_load_decr(CPUPPCState *env)
+static target_ulong _cpu_ppc_load_decr(CPUPPCState *env, int64_t now)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t decr;
- if (kvm_enabled()) {
- return env->spr[SPR_DECR];
- }
-
- decr = _cpu_ppc_load_decr(env, tb_env->decr_next);
+ decr = __cpu_ppc_load_decr(env, now, tb_env->decr_next);
/*
* If large decrementer is enabled then the decrementer is signed extened
@@ -750,14 +746,23 @@ target_ulong cpu_ppc_load_decr(CPUPPCState *env)
return (uint32_t) decr;
}
-target_ulong cpu_ppc_load_hdecr(CPUPPCState *env)
+target_ulong cpu_ppc_load_decr(CPUPPCState *env)
+{
+ if (kvm_enabled()) {
+ return env->spr[SPR_DECR];
+ } else {
+ return _cpu_ppc_load_decr(env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ }
+}
+
+static target_ulong _cpu_ppc_load_hdecr(CPUPPCState *env, int64_t now)
{
PowerPCCPU *cpu = env_archcpu(env);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
ppc_tb_t *tb_env = env->tb_env;
uint64_t hdecr;
- hdecr = _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+ hdecr = __cpu_ppc_load_decr(env, now, tb_env->hdecr_next);
/*
* If we have a large decrementer (POWER9 or later) then hdecr is sign
@@ -771,6 +776,11 @@ target_ulong cpu_ppc_load_hdecr(CPUPPCState *env)
return (uint32_t) hdecr;
}
+target_ulong cpu_ppc_load_hdecr(CPUPPCState *env)
+{
+ return _cpu_ppc_load_hdecr(env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+}
+
uint64_t cpu_ppc_load_purr (CPUPPCState *env)
{
ppc_tb_t *tb_env = env->tb_env;
@@ -815,7 +825,7 @@ static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
}
-static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+static void __cpu_ppc_store_decr(PowerPCCPU *cpu, int64_t now, uint64_t *nextp,
QEMUTimer *timer,
void (*raise_excp)(void *),
void (*lower_excp)(PowerPCCPU *),
@@ -824,7 +834,7 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
{
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env = env->tb_env;
- uint64_t now, next;
+ uint64_t next;
int64_t signed_value;
int64_t signed_decr;
@@ -836,18 +846,12 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
trace_ppc_decr_store(nr_bits, decr, value);
- if (kvm_enabled()) {
- /* KVM handles decrementer exceptions, we don't need our own timer */
- return;
- }
-
/*
* Calculate the next decrementer event and set a timer.
* decr_next is in timebase units to keep rounding simple. Note it is
* not adjusted by tb_offset because if TB changes via tb_offset changing,
* decrementer does not change, so not directly comparable with TB.
*/
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
next = ns_to_tb(tb_env->decr_freq, now) + value;
*nextp = next; /* nextp is in timebase units */
@@ -876,12 +880,13 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
timer_mod(timer, tb_to_ns_round_up(tb_env->decr_freq, next));
}
-static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr,
- target_ulong value, int nr_bits)
+static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, int64_t now,
+ target_ulong decr, target_ulong value,
+ int nr_bits)
{
ppc_tb_t *tb_env = cpu->env.tb_env;
- __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
+ __cpu_ppc_store_decr(cpu, now, &tb_env->decr_next, tb_env->decr_timer,
tb_env->decr_timer->cb, &cpu_ppc_decr_lower,
tb_env->flags, decr, value, nr_bits);
}
@@ -890,13 +895,22 @@ void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value)
{
PowerPCCPU *cpu = env_archcpu(env);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ int64_t now;
+ target_ulong decr;
int nr_bits = 32;
+ if (kvm_enabled()) {
+ /* KVM handles decrementer exceptions, we don't need our own timer */
+ return;
+ }
+
if (env->spr[SPR_LPCR] & LPCR_LD) {
nr_bits = pcc->lrg_decr_bits;
}
- _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, nr_bits);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ decr = _cpu_ppc_load_decr(env, now);
+ _cpu_ppc_store_decr(cpu, now, decr, value, nr_bits);
}
static void cpu_ppc_decr_cb(void *opaque)
@@ -906,14 +920,15 @@ static void cpu_ppc_decr_cb(void *opaque)
cpu_ppc_decr_excp(cpu);
}
-static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr,
- target_ulong value, int nr_bits)
+static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, int64_t now,
+ target_ulong hdecr, target_ulong value,
+ int nr_bits)
{
ppc_tb_t *tb_env = cpu->env.tb_env;
if (tb_env->hdecr_timer != NULL) {
/* HDECR (Book3S 64bit) is edge-based, not level like DECR */
- __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
+ __cpu_ppc_store_decr(cpu, now, &tb_env->hdecr_next, tb_env->hdecr_timer,
tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
PPC_DECR_UNDERFLOW_TRIGGERED,
hdecr, value, nr_bits);
@@ -924,9 +939,12 @@ void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value)
{
PowerPCCPU *cpu = env_archcpu(env);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ int64_t now;
+ target_ulong hdecr;
- _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value,
- pcc->lrg_decr_bits);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ hdecr = _cpu_ppc_load_hdecr(env, now);
+ _cpu_ppc_store_hdecr(cpu, now, hdecr, value, pcc->lrg_decr_bits);
}
static void cpu_ppc_hdecr_cb(void *opaque)
@@ -936,12 +954,16 @@ static void cpu_ppc_hdecr_cb(void *opaque)
cpu_ppc_hdecr_excp(cpu);
}
-void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
+static void _cpu_ppc_store_purr(CPUPPCState *env, int64_t now, uint64_t value)
{
ppc_tb_t *tb_env = env->tb_env;
- cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- &tb_env->purr_offset, value);
+ cpu_ppc_store_tb(tb_env, now, &tb_env->purr_offset, value);
+}
+
+void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
+{
+ _cpu_ppc_store_purr(env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), value);
}
static void timebase_save(PPCTimebase *tb)
--
2.40.1
next prev parent reply other threads:[~2023-08-08 4:22 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-08 4:19 [PATCH v2 for-8.2 00/19] ppc: record-replay enablement and fixes Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 01/19] ppc/vhyp: reset exception state when handling vhyp hcall Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 02/19] ppc/vof: Fix missed fields in VOF cleanup Nicholas Piggin
2023-08-17 2:57 ` Alexey Kardashevskiy
2023-08-08 4:19 ` [PATCH v2 03/19] hw/ppc/ppc.c: Tidy over-long lines Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 04/19] hw/ppc: Introduce functions for conversion between timebase and nanoseconds Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 05/19] host-utils: Add muldiv64_round_up Nicholas Piggin
2023-09-01 11:51 ` Cédric Le Goater
2023-09-01 17:02 ` Richard Henderson
2023-09-04 13:07 ` Nicholas Piggin
2023-09-04 13:30 ` Cédric Le Goater
2023-09-05 3:56 ` Nicholas Piggin
2023-09-05 6:48 ` Cédric Le Goater
2023-09-05 9:09 ` Philippe Mathieu-Daudé
2023-09-06 9:21 ` Cédric Le Goater
2023-08-08 4:19 ` [PATCH v2 06/19] hw/ppc: Round up the decrementer interval when converting to ns Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 07/19] hw/ppc: Avoid decrementer rounding errors Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 08/19] target/ppc: Sign-extend large decrementer to 64-bits Nicholas Piggin
2023-09-01 12:25 ` Cédric Le Goater
2023-09-04 13:09 ` Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 09/19] hw/ppc: Always store the decrementer value Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 10/19] target/ppc: Migrate DECR SPR Nicholas Piggin
2023-08-09 12:56 ` Cédric Le Goater
2023-08-10 1:12 ` Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 11/19] hw/ppc: Reset timebase facilities on machine reset Nicholas Piggin
2023-08-08 4:19 ` Nicholas Piggin [this message]
2023-08-08 4:19 ` [PATCH v2 13/19] target/ppc: Fix CPU reservation migration for record-replay Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 14/19] target/ppc: Fix timebase reset with record-replay Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 15/19] spapr: Fix machine reset deadlock from replay-record Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 16/19] spapr: Fix record-replay machine reset consuming too many events Nicholas Piggin
2023-08-08 4:19 ` [PATCH v2 17/19] tests/avocado: boot ppc64 pseries replay-record test to Linux VFS mount Nicholas Piggin
2023-08-08 4:20 ` [PATCH v2 18/19] tests/avocado: reverse-debugging cope with re-executing breakpoints Nicholas Piggin
2023-08-08 4:20 ` [PATCH v2 19/19] tests/avocado: ppc64 reverse debugging tests for pseries and powernv Nicholas Piggin
2023-08-29 16:43 ` [PATCH v2 for-8.2 00/19] ppc: record-replay enablement and fixes Cédric Le Goater
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230808042001.411094-13-npiggin@gmail.com \
--to=npiggin@gmail.com \
--cc=clg@kaod.org \
--cc=danielhb413@gmail.com \
--cc=david@gibson.dropbear.id.au \
--cc=groug@kaod.org \
--cc=harshpb@linux.ibm.com \
--cc=pavel.dovgaluk@ispras.ru \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).