From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
To: Andrew Jones <drjones@redhat.com>
Cc: kvm@vger.kernel.org, pbonzini@redhat.com, rkrcmar@redhat.com,
kvm-ppc@vger.kernel.org, lvivier@redhat.com, thuth@redhat.com
Subject: Re: [kvm-unit-tests PATCH V4 4/5] lib/powerpc: Implement generic delay function for use in unit tests
Date: Thu, 18 Aug 2016 14:39:07 +1000 [thread overview]
Message-ID: <1471495147.2138.17.camel@gmail.com> (raw)
In-Reply-To: <20160817130437.e7d25spccbp6e3cv@kamzik.localdomain>
On Wed, 2016-08-17 at 15:04 +0200, Andrew Jones wrote:
> On Wed, Aug 17, 2016 at 04:48:57PM +1000, Suraj Jitindar Singh wrote:
> >
> > It would be nice if we had a generic delay function which could be
> > used
> > in unit tests, add one.
> >
> > Add the variable tb_hz used to store the time base frequency which
> > is read
> > from the device tree on setup.
> >
> > Add functions mdelay, udelay and delay in processor.c to delay for
> > a given
> > number of milliseconds, microseconds and time base ticks
> > respectively.
> >
> > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> > ---
> >
> > Change Log:
> >
> > V2 -> V3:
> > - Add patch to series
> > V3 -> V4:
> > - Reword sleep->delay
> > - Move cpu_relax to asm-generic/barrier.h
> > - Add assert to catch when delay fns called with too large
> > values
> > ---
> > lib/asm-generic/barrier.h | 4 ++++
> > lib/powerpc/asm/processor.h | 19 +++++++++++++++++++
> > lib/powerpc/asm/setup.h | 2 ++
> > lib/powerpc/processor.c | 20 ++++++++++++++++++++
> > lib/powerpc/setup.c | 7 +++++++
> > 5 files changed, 52 insertions(+)
> >
> > diff --git a/lib/asm-generic/barrier.h b/lib/asm-generic/barrier.h
> > index 12ae782..6a990ff 100644
> > --- a/lib/asm-generic/barrier.h
> > +++ b/lib/asm-generic/barrier.h
> > @@ -28,4 +28,8 @@
> > #define smp_wmb() wmb()
> > #endif
> >
> > +#ifndef cpu_relax
> > +#define cpu_relax() asm volatile ("":::"memory")
> > +#endif
> > +
> > #endif /* _ASM_BARRIER_H_ */
> > diff --git a/lib/powerpc/asm/processor.h
> > b/lib/powerpc/asm/processor.h
> > index 09692bd..ac001e1 100644
> > --- a/lib/powerpc/asm/processor.h
> > +++ b/lib/powerpc/asm/processor.h
> > @@ -1,6 +1,7 @@
> > #ifndef _ASMPOWERPC_PROCESSOR_H_
> > #define _ASMPOWERPC_PROCESSOR_H_
> >
> > +#include <libcflat.h>
> > #include <asm/ptrace.h>
> >
> > #ifndef __ASSEMBLY__
> > @@ -8,4 +9,22 @@ void handle_exception(int trap, void
> > (*func)(struct pt_regs *, void *), void *);
> > void do_handle_exception(struct pt_regs *regs);
> > #endif /* __ASSEMBLY__ */
> >
> > +static inline uint64_t get_tb(void)
> > +{
> > + uint64_t tb;
> > +
> > + asm volatile ("mfspr %[tb],268" : [tb] "=r" (tb));
> > +
> > + return tb;
> > +}
> > +
> > +extern void delay(uint64_t cycles);
> > +extern void udelay(uint64_t us);
> > +
> > +static inline void mdelay(uint64_t ms)
> > +{
> > + while (ms--)
> > + udelay(1000);
> > +}
> > +
> > #endif /* _ASMPOWERPC_PROCESSOR_H_ */
> > diff --git a/lib/powerpc/asm/setup.h b/lib/powerpc/asm/setup.h
> > index b1e1e5a..23b4156 100644
> > --- a/lib/powerpc/asm/setup.h
> > +++ b/lib/powerpc/asm/setup.h
> > @@ -11,6 +11,8 @@
> > extern u32 cpus[NR_CPUS];
> > extern int nr_cpus;
> >
> > +extern uint64_t tb_hz;
> > +
> > #define NR_MEM_REGIONS 8
> > #define MR_F_PRIMARY (1U << 0)
> > struct mem_region {
> > diff --git a/lib/powerpc/processor.c b/lib/powerpc/processor.c
> > index a78bc3c..a28f2f0 100644
> > --- a/lib/powerpc/processor.c
> > +++ b/lib/powerpc/processor.c
> > @@ -5,6 +5,8 @@
> > #include <libcflat.h>
> > #include <asm/processor.h>
> > #include <asm/ptrace.h>
> > +#include <asm/setup.h>
> > +#include <asm/barrier.h>
> >
> > static struct {
> > void (*func)(struct pt_regs *, void *data);
> > @@ -36,3 +38,21 @@ void do_handle_exception(struct pt_regs *regs)
> > printf("unhandled cpu exception 0x%lx\n", regs->trap);
> > abort();
> > }
> > +
> > +void delay(uint64_t cycles)
> > +{
> > + uint64_t start = get_tb();
> > + /*
> > + * Pretty unlikely unless your server has been on for, or
> > you want to
> > + * delay for, over 1000 years, but still.
> > + */
> > + assert(cycles < (UINT64_MAX - start));
> > + while ((get_tb() - start) < cycles)
> I don't think the above assert is necessary. As long as the
> subtraction
> (get_tb() - start) produces a uint64_t, then the condition should
> always
> work - per C99. Maybe it should be written as (uint64_t)(get_tb() -
> start)
> to be 100% correct though.
This is to catch the case where the caller passes a ridiculously large
cycles value (e.g. UINT64_MAX - 1) and/or start is sufficiently large
that get_tb() - start will never be >= to cycles because the time-base
counter will overflow and wrap around before that ever becomes true.
This is super unlikely but will avoid an infinite loop in the event
someone does it.
>
> >
> > + cpu_relax();
> > +}
> > +
> > +void udelay(uint64_t us)
> > +{
> > + assert(us < (UINT64_MAX / tb_hz));
> Same comment here. I'm pretty sure (wrap around wraps my head, so I
> could be wrong) that the main concern is maintaining unsigned integer
> subtraction, which the C99 guarantees to wrap modulo 2^N, N being the
> number of bits of the unsigned integer.
This is to catch when the caller tries to sleep for > 36000000000us (10
hrs), which I realise is highly unlikely. But in this case us * tb_hz
will be too big to store in a u64. Thus this won't delay for the
intended time, hence the assert.
>
> >
> > + delay((us * tb_hz) / 1000000);
> > +}
> > diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> > index e3d2afa..65bedf5 100644
> > --- a/lib/powerpc/setup.c
> > +++ b/lib/powerpc/setup.c
> > @@ -24,6 +24,7 @@ extern void setup_args_progname(const char
> > *args);
> >
> > u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
> > int nr_cpus;
> > +uint64_t tb_hz;
> >
> > struct mem_region mem_regions[NR_MEM_REGIONS];
> > phys_addr_t __physical_start, __physical_end;
> > @@ -72,6 +73,12 @@ static void cpu_set(int fdtnode, u32 regval,
> > void *info)
> > data = (u32 *)prop->data;
> > params->dcache_bytes = fdt32_to_cpu(*data);
> >
> > + prop = fdt_get_property(dt_fdt(), fdtnode,
> > + "timebase-frequency",
> > NULL);
> > + assert(prop != NULL);
> > + data = (u32 *)prop->data;
> > + tb_hz = fdt32_to_cpu(*data);
> Arguably the dance I do with cpu_set_params to pass values back to
> cpu_init, where they simply get assigned to globals, is pointless.
> It's
> trying to maintain encapsulation (which I violate for nr_cpus
> anyway...)
> That said, I'd like to see tb_hz either integrate with the
> cpu_set_params
> pattern, or a cleanup patch come before this one, which removes
> cpu_set_params, allowing icache/dcache_bytes setting to match the
> tb_hz
> pattern. I won't hold this series up on that though.
Yeah I see whats happening here, I'll make it match what is done for
i/dcache.
>
> >
> > +
> > read_common_info = true;
> > }
> > }
Thanks
next prev parent reply other threads:[~2016-08-18 4:50 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-17 6:48 [kvm-unit-tests PATCH V4 1/5] scripts/runtime: Add ability to mark test as don't run by default Suraj Jitindar Singh
2016-08-17 6:48 ` [kvm-unit-tests PATCH V4 2/5] lib/powerpc: Add generic decrementer exception handler Suraj Jitindar Singh
2016-08-17 6:48 ` [kvm-unit-tests PATCH V4 3/5] lib/powerpc: Add function to start secondary threads Suraj Jitindar Singh
2016-08-17 7:44 ` Thomas Huth
2016-08-18 3:59 ` Suraj Jitindar Singh
2016-08-17 6:48 ` [kvm-unit-tests PATCH V4 4/5] lib/powerpc: Implement generic delay function for use in unit tests Suraj Jitindar Singh
2016-08-17 8:19 ` Thomas Huth
2016-08-18 4:41 ` Suraj Jitindar Singh
2016-08-17 13:04 ` Andrew Jones
2016-08-18 4:39 ` Suraj Jitindar Singh [this message]
2016-08-18 10:24 ` Andrew Jones
2016-08-19 0:41 ` Suraj Jitindar Singh
2016-08-17 6:48 ` [kvm-unit-tests PATCH V4 5/5] powerpc/tm: Add a test for H_CEDE while tm suspended Suraj Jitindar Singh
2016-08-17 8:31 ` Thomas Huth
2016-08-17 12:11 ` [kvm-unit-tests PATCH V4 1/5] scripts/runtime: Add ability to mark test as don't run by default Andrew Jones
2016-08-17 15:01 ` Radim Krčmář
2016-08-18 4:46 ` Suraj Jitindar Singh
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=1471495147.2138.17.camel@gmail.com \
--to=sjitindarsingh@gmail.com \
--cc=drjones@redhat.com \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
--cc=lvivier@redhat.com \
--cc=pbonzini@redhat.com \
--cc=rkrcmar@redhat.com \
--cc=thuth@redhat.com \
/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