diff mbox

[kvm-unit-tests,V3,4/5] lib/powerpc: Implement generic sleep function for use in unit tests

Message ID 1471331895-29887-4-git-send-email-sjitindarsingh@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Suraj Jitindar Singh Aug. 16, 2016, 7:18 a.m. UTC
It would be nice if we had a generic sleep 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 msleep, usleep and sleep in processor.c to sleep 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

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
---
 lib/powerpc/asm/processor.h | 19 +++++++++++++++++++
 lib/powerpc/asm/setup.h     |  2 ++
 lib/powerpc/processor.c     | 13 +++++++++++++
 lib/powerpc/setup.c         | 12 ++++++++++++
 4 files changed, 46 insertions(+)

Comments

Andrew Jones Aug. 16, 2016, 12:41 p.m. UTC | #1
On Tue, Aug 16, 2016 at 05:18:14PM +1000, Suraj Jitindar Singh wrote:
> It would be nice if we had a generic sleep 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 msleep, usleep and sleep in processor.c to sleep for a given
> number of milliseconds, microseconds and time base ticks respectively.

Above you talk about adding *sleep functions, but below you add *delay
functions.

> 
> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> ---
> 
> Change Log:
> 
> V2 -> V3:
> 	- Add patch to series
> 
> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> ---
>  lib/powerpc/asm/processor.h | 19 +++++++++++++++++++
>  lib/powerpc/asm/setup.h     |  2 ++
>  lib/powerpc/processor.c     | 13 +++++++++++++
>  lib/powerpc/setup.c         | 12 ++++++++++++
>  4 files changed, 46 insertions(+)
> 
> diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
> index 09692bd..9554e08 100644
> --- a/lib/powerpc/asm/processor.h
> +++ b/lib/powerpc/asm/processor.h
> @@ -1,11 +1,30 @@
>  #ifndef _ASMPOWERPC_PROCESSOR_H_
>  #define _ASMPOWERPC_PROCESSOR_H_
>  
> +#include <libcflat.h>
>  #include <asm/ptrace.h>
>  
> +#define cpu_relax() asm volatile ("" : : : "memory")

Please add this to lib/asm-generic/barrier.h, then lib/ppc64/asm/barrier.h
will pick it up from there and you'll just need to make sure you include
asm/barrier.h in processor.c

> +
>  #ifndef __ASSEMBLY__
>  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..c84bae5 100644
> --- a/lib/powerpc/processor.c
> +++ b/lib/powerpc/processor.c
> @@ -5,6 +5,7 @@
>  #include <libcflat.h>
>  #include <asm/processor.h>
>  #include <asm/ptrace.h>
> +#include <asm/setup.h>
>  
>  static struct {
>  	void (*func)(struct pt_regs *, void *data);
> @@ -36,3 +37,15 @@ 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();
> +	while((get_tb() - start) < cycles)
> +		cpu_relax();
> +}
> +
> +void udelay(uint64_t us)
> +{
> +	delay((us * tb_hz) / 1000000);
> +}
> diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> index e3d2afa..e7fa525 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;
> @@ -51,6 +52,17 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
>  	}
>  	cpus[cpu] = regval;
>  
> +	/* set timebase frequency */
> +	if (!tb_hz) {

Instead of this condition, can't we tuck this DT parsing into the
if (!read_common_info) block we already have?

> +		const struct fdt_property *prop;
> +		u32 *data;
> +		prop = fdt_get_property(dt_fdt(), fdtnode,
> +					"timebase-frequency", NULL);
> +		assert(prop != NULL);
> +		data = (u32 *)prop->data;
> +		tb_hz = fdt32_to_cpu(*data);
> +	}
> +
>  	/* set exception stack address for this CPU (in SPGR0) */
>  
>  	asm volatile ("mtsprg0 %[addr]" ::
> -- 
> 2.5.5
>

Otherwise looks good to me.

Thanks,
drew
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Huth Aug. 16, 2016, 12:54 p.m. UTC | #2
On 16.08.2016 09:18, Suraj Jitindar Singh wrote:
> It would be nice if we had a generic sleep 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 msleep, usleep and sleep in processor.c to sleep for a given
> number of milliseconds, microseconds and time base ticks respectively.

You finally called them mdelay, udelay and delay instead, so in case you
respin, please adjust the commit message.

> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> ---
> 
> Change Log:
> 
> V2 -> V3:
> 	- Add patch to series
> 
> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> ---
>  lib/powerpc/asm/processor.h | 19 +++++++++++++++++++
>  lib/powerpc/asm/setup.h     |  2 ++
>  lib/powerpc/processor.c     | 13 +++++++++++++
>  lib/powerpc/setup.c         | 12 ++++++++++++
>  4 files changed, 46 insertions(+)
> 
> diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
> index 09692bd..9554e08 100644
> --- a/lib/powerpc/asm/processor.h
> +++ b/lib/powerpc/asm/processor.h
> @@ -1,11 +1,30 @@
>  #ifndef _ASMPOWERPC_PROCESSOR_H_
>  #define _ASMPOWERPC_PROCESSOR_H_
>  
> +#include <libcflat.h>
>  #include <asm/ptrace.h>
>  
> +#define cpu_relax() asm volatile ("" : : : "memory")

I'd maybe add a "nop" instruction in there ... just in case?

>  #ifndef __ASSEMBLY__
>  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..c84bae5 100644
> --- a/lib/powerpc/processor.c
> +++ b/lib/powerpc/processor.c
> @@ -5,6 +5,7 @@
>  #include <libcflat.h>
>  #include <asm/processor.h>
>  #include <asm/ptrace.h>
> +#include <asm/setup.h>
>  
>  static struct {
>  	void (*func)(struct pt_regs *, void *data);
> @@ -36,3 +37,15 @@ 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();
> +	while((get_tb() - start) < cycles)
> +		cpu_relax();

Shouldn't there be some kind of wrap-around detection, like you had it
in v2 for the decrementer based sleep function?

> +}
> +
> +void udelay(uint64_t us)
> +{
> +	delay((us * tb_hz) / 1000000);
> +}
> diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> index e3d2afa..e7fa525 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;
> @@ -51,6 +52,17 @@ static void cpu_set(int fdtnode, u32 regval, void *info)
>  	}
>  	cpus[cpu] = regval;
>  
> +	/* set timebase frequency */
> +	if (!tb_hz) {
> +		const struct fdt_property *prop;
> +		u32 *data;
> +		prop = fdt_get_property(dt_fdt(), fdtnode,
> +					"timebase-frequency", NULL);
> +		assert(prop != NULL);
> +		data = (u32 *)prop->data;
> +		tb_hz = fdt32_to_cpu(*data);

You could short-cut that to fdt32_to_cpu(*(u32 *)prop->data) and get rid
of the "data" variable.

> +	}
> +
>  	/* set exception stack address for this CPU (in SPGR0) */
>  
>  	asm volatile ("mtsprg0 %[addr]" ::
> 

 Thomas

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Suraj Jitindar Singh Aug. 17, 2016, 4:57 a.m. UTC | #3
On Tue, 2016-08-16 at 14:41 +0200, Andrew Jones wrote:
> On Tue, Aug 16, 2016 at 05:18:14PM +1000, Suraj Jitindar Singh wrote:
> > 
> > It would be nice if we had a generic sleep 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 msleep, usleep and sleep in processor.c to sleep for
> > a given
> > number of milliseconds, microseconds and time base ticks
> > respectively.
> Above you talk about adding *sleep functions, but below you add
> *delay
> functions.
Woops
> 
> > 
> > 
> > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> > ---
> > 
> > Change Log:
> > 
> > V2 -> V3:
> > 	- Add patch to series
> > 
> > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> > ---
> >  lib/powerpc/asm/processor.h | 19 +++++++++++++++++++
> >  lib/powerpc/asm/setup.h     |  2 ++
> >  lib/powerpc/processor.c     | 13 +++++++++++++
> >  lib/powerpc/setup.c         | 12 ++++++++++++
> >  4 files changed, 46 insertions(+)
> > 
> > diff --git a/lib/powerpc/asm/processor.h
> > b/lib/powerpc/asm/processor.h
> > index 09692bd..9554e08 100644
> > --- a/lib/powerpc/asm/processor.h
> > +++ b/lib/powerpc/asm/processor.h
> > @@ -1,11 +1,30 @@
> >  #ifndef _ASMPOWERPC_PROCESSOR_H_
> >  #define _ASMPOWERPC_PROCESSOR_H_
> >  
> > +#include <libcflat.h>
> >  #include <asm/ptrace.h>
> >  
> > +#define cpu_relax() asm volatile ("" : : : "memory")
> Please add this to lib/asm-generic/barrier.h, then
> lib/ppc64/asm/barrier.h
> will pick it up from there and you'll just need to make sure you
> include
> asm/barrier.h in processor.c
Will do
> 
> > 
> > +
> >  #ifndef __ASSEMBLY__
> >  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..c84bae5 100644
> > --- a/lib/powerpc/processor.c
> > +++ b/lib/powerpc/processor.c
> > @@ -5,6 +5,7 @@
> >  #include <libcflat.h>
> >  #include <asm/processor.h>
> >  #include <asm/ptrace.h>
> > +#include <asm/setup.h>
> >  
> >  static struct {
> >  	void (*func)(struct pt_regs *, void *data);
> > @@ -36,3 +37,15 @@ 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();
> > +	while((get_tb() - start) < cycles)
> > +		cpu_relax();
> > +}
> > +
> > +void udelay(uint64_t us)
> > +{
> > +	delay((us * tb_hz) / 1000000);
> > +}
> > diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> > index e3d2afa..e7fa525 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;
> > @@ -51,6 +52,17 @@ static void cpu_set(int fdtnode, u32 regval,
> > void *info)
> >  	}
> >  	cpus[cpu] = regval;
> >  
> > +	/* set timebase frequency */
> > +	if (!tb_hz) {
> Instead of this condition, can't we tuck this DT parsing into the
> if (!read_common_info) block we already have?
Didn't read that properly to realise that block is only called once,
I'll move it into there.
> 
> > 
> > +		const struct fdt_property *prop;
> > +		u32 *data;
> > +		prop = fdt_get_property(dt_fdt(), fdtnode,
> > +					"timebase-frequency",
> > NULL);
> > +		assert(prop != NULL);
> > +		data = (u32 *)prop->data;
> > +		tb_hz = fdt32_to_cpu(*data);
> > +	}
> > +
> >  	/* set exception stack address for this CPU (in SPGR0) */
> >  
> >  	asm volatile ("mtsprg0 %[addr]" ::
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Suraj Jitindar Singh Aug. 17, 2016, 5:02 a.m. UTC | #4
On Tue, 2016-08-16 at 14:54 +0200, Thomas Huth wrote:
> On 16.08.2016 09:18, Suraj Jitindar Singh wrote:
> > 
> > It would be nice if we had a generic sleep 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 msleep, usleep and sleep in processor.c to sleep for
> > a given
> > number of milliseconds, microseconds and time base ticks
> > respectively.
> You finally called them mdelay, udelay and delay instead, so in case
> you
> respin, please adjust the commit message.
Woops, I'll fix those
> 
> > 
> > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> > ---
> > 
> > Change Log:
> > 
> > V2 -> V3:
> > 	- Add patch to series
> > 
> > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
> > ---
> >  lib/powerpc/asm/processor.h | 19 +++++++++++++++++++
> >  lib/powerpc/asm/setup.h     |  2 ++
> >  lib/powerpc/processor.c     | 13 +++++++++++++
> >  lib/powerpc/setup.c         | 12 ++++++++++++
> >  4 files changed, 46 insertions(+)
> > 
> > diff --git a/lib/powerpc/asm/processor.h
> > b/lib/powerpc/asm/processor.h
> > index 09692bd..9554e08 100644
> > --- a/lib/powerpc/asm/processor.h
> > +++ b/lib/powerpc/asm/processor.h
> > @@ -1,11 +1,30 @@
> >  #ifndef _ASMPOWERPC_PROCESSOR_H_
> >  #define _ASMPOWERPC_PROCESSOR_H_
> >  
> > +#include <libcflat.h>
> >  #include <asm/ptrace.h>
> >  
> > +#define cpu_relax() asm volatile ("" : : : "memory")
> I'd maybe add a "nop" instruction in there ... just in case?
We don't put the nop in anywhere else or in the kernel. I'm gonna leave
this.
> 
> > 
> >  #ifndef __ASSEMBLY__
> >  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..c84bae5 100644
> > --- a/lib/powerpc/processor.c
> > +++ b/lib/powerpc/processor.c
> > @@ -5,6 +5,7 @@
> >  #include <libcflat.h>
> >  #include <asm/processor.h>
> >  #include <asm/ptrace.h>
> > +#include <asm/setup.h>
> >  
> >  static struct {
> >  	void (*func)(struct pt_regs *, void *data);
> > @@ -36,3 +37,15 @@ 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();
> > +	while((get_tb() - start) < cycles)
> > +		cpu_relax();
> Shouldn't there be some kind of wrap-around detection, like you had
> it
> in v2 for the decrementer based sleep function?
Thanks for catching that, highly unlikely this will overflow (64-bit
for timebase vs 31-bit for decrementer) but probably worth adding a
check to be sure.
> 
> > 
> > +}
> > +
> > +void udelay(uint64_t us)
> > +{
> > +	delay((us * tb_hz) / 1000000);
> > +}
> > diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> > index e3d2afa..e7fa525 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;
> > @@ -51,6 +52,17 @@ static void cpu_set(int fdtnode, u32 regval,
> > void *info)
> >  	}
> >  	cpus[cpu] = regval;
> >  
> > +	/* set timebase frequency */
> > +	if (!tb_hz) {
> > +		const struct fdt_property *prop;
> > +		u32 *data;
> > +		prop = fdt_get_property(dt_fdt(), fdtnode,
> > +					"timebase-frequency",
> > NULL);
> > +		assert(prop != NULL);
> > +		data = (u32 *)prop->data;
> > +		tb_hz = fdt32_to_cpu(*data);
> You could short-cut that to fdt32_to_cpu(*(u32 *)prop->data) and get
> rid
> of the "data" variable.
Moved this into the code block below were those are both already
defined.
> 
> > 
> > +	}
> > +
> >  	/* set exception stack address for this CPU (in SPGR0) */
> >  
> >  	asm volatile ("mtsprg0 %[addr]" ::
> > 
>  Thomas
> 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
index 09692bd..9554e08 100644
--- a/lib/powerpc/asm/processor.h
+++ b/lib/powerpc/asm/processor.h
@@ -1,11 +1,30 @@ 
 #ifndef _ASMPOWERPC_PROCESSOR_H_
 #define _ASMPOWERPC_PROCESSOR_H_
 
+#include <libcflat.h>
 #include <asm/ptrace.h>
 
+#define cpu_relax() asm volatile ("" : : : "memory")
+
 #ifndef __ASSEMBLY__
 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..c84bae5 100644
--- a/lib/powerpc/processor.c
+++ b/lib/powerpc/processor.c
@@ -5,6 +5,7 @@ 
 #include <libcflat.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
+#include <asm/setup.h>
 
 static struct {
 	void (*func)(struct pt_regs *, void *data);
@@ -36,3 +37,15 @@  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();
+	while((get_tb() - start) < cycles)
+		cpu_relax();
+}
+
+void udelay(uint64_t us)
+{
+	delay((us * tb_hz) / 1000000);
+}
diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
index e3d2afa..e7fa525 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;
@@ -51,6 +52,17 @@  static void cpu_set(int fdtnode, u32 regval, void *info)
 	}
 	cpus[cpu] = regval;
 
+	/* set timebase frequency */
+	if (!tb_hz) {
+		const struct fdt_property *prop;
+		u32 *data;
+		prop = fdt_get_property(dt_fdt(), fdtnode,
+					"timebase-frequency", NULL);
+		assert(prop != NULL);
+		data = (u32 *)prop->data;
+		tb_hz = fdt32_to_cpu(*data);
+	}
+
 	/* set exception stack address for this CPU (in SPGR0) */
 
 	asm volatile ("mtsprg0 %[addr]" ::