WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [POWERPC][XEN] Synchronize Timebase on al

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [POWERPC][XEN] Synchronize Timebase on all CPUs
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 19 Sep 2006 10:02:35 +0000
Delivery-date: Tue, 19 Sep 2006 03:03:28 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID e20a469dabb42c8731171556f99e076a7981d2bf
# Parent  464acece0dad70663f8658ec555db5564ba126c2
[POWERPC][XEN] Synchronize Timebase on all CPUs

This patch add the necessary support to use
  arch/powerpc/kernel/smp-tbsync.c
from Linux.
Original copyright and author are:
  Copyright (C) 2003 Samuel Rydh (samuel@xxxxxxxxx)

Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
---
 xen/arch/powerpc/Makefile                     |    1 
 xen/arch/powerpc/exceptions.h                 |    1 
 xen/arch/powerpc/setup.c                      |   10 +
 xen/arch/powerpc/smp-tbsync.c                 |  186 ++++++++++++++++++++++++++
 xen/include/asm-powerpc/powerpc64/processor.h |   11 +
 xen/include/asm-powerpc/reg_defs.h            |    4 
 xen/include/asm-powerpc/smp.h                 |    4 
 xen/include/asm-powerpc/time.h                |    9 +
 8 files changed, 223 insertions(+), 3 deletions(-)

diff -r 464acece0dad -r e20a469dabb4 xen/arch/powerpc/Makefile
--- a/xen/arch/powerpc/Makefile Thu Sep 07 02:21:17 2006 -0400
+++ b/xen/arch/powerpc/Makefile Thu Sep 07 02:50:06 2006 -0400
@@ -36,6 +36,7 @@ obj-y += setup.o
 obj-y += setup.o
 obj-y += shadow.o
 obj-y += smp.o
+obj-y += smp-tbsync.o
 obj-y += time.o
 obj-y += usercopy.o
 
diff -r 464acece0dad -r e20a469dabb4 xen/arch/powerpc/exceptions.h
--- a/xen/arch/powerpc/exceptions.h     Thu Sep 07 02:21:17 2006 -0400
+++ b/xen/arch/powerpc/exceptions.h     Thu Sep 07 02:50:06 2006 -0400
@@ -51,4 +51,5 @@ extern char exception_vectors[];
 extern char exception_vectors[];
 extern char exception_vectors_end[];
 extern int spin_start[];
+extern int secondary_cpu_init(int cpuid, unsigned long r4);
 #endif
diff -r 464acece0dad -r e20a469dabb4 xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c  Thu Sep 07 02:21:17 2006 -0400
+++ b/xen/arch/powerpc/setup.c  Thu Sep 07 02:50:06 2006 -0400
@@ -16,6 +16,8 @@
  * Copyright (C) IBM Corp. 2005, 2006
  *
  * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ *          Amos Waterland <apw@xxxxxxxxxx>
+ *          Hollis Blanchard <hollisb@xxxxxxxxxx>
  */
 
 #include <xen/config.h>
@@ -242,16 +244,22 @@ static int kick_secondary_cpus(int maxcp
             break;
         init_parea(cpuid);
         cpu_set(cpuid, cpu_online_map);
+        smp_generic_give_timebase();
+
+        /* wait for it */
+        while (!cpu_online(cpuid))
+            cpu_relax();
     }
 
     return 0;
 }
 
 /* This is the first C code that secondary processors invoke.  */
-int secondary_cpu_init(int cpuid, unsigned long r4);
 int secondary_cpu_init(int cpuid, unsigned long r4)
 {
     cpu_initialize(cpuid);
+    smp_generic_take_timebase();
+    cpu_set(cpuid, cpu_online_map);
     while(1);
 }
 
diff -r 464acece0dad -r e20a469dabb4 
xen/include/asm-powerpc/powerpc64/processor.h
--- a/xen/include/asm-powerpc/powerpc64/processor.h     Thu Sep 07 02:21:17 
2006 -0400
+++ b/xen/include/asm-powerpc/powerpc64/processor.h     Thu Sep 07 02:50:06 
2006 -0400
@@ -91,10 +91,21 @@ static inline unsigned long mftb(void)
     return tb;
 }
 
+static inline void mttbl(unsigned low)
+{
+    __asm__ __volatile__ ("mtspr %0, %1" : : "i"(SPRN_TBWL), "r" (low));
+}
+
+static inline void mttbu(unsigned upper)
+{
+    __asm__ __volatile__ ("mtspr %0, %1" : : "i"(SPRN_TBWU), "r" (upper));
+}
+
 static inline void mthdec(unsigned ticks)
 {
     __asm__ __volatile__ ("mtspr %0, %1" : : "i"(SPRN_HDEC), "r" (ticks));
 }
+
 static inline unsigned int mfhdec(void)
 {
     unsigned int val;
diff -r 464acece0dad -r e20a469dabb4 xen/include/asm-powerpc/reg_defs.h
--- a/xen/include/asm-powerpc/reg_defs.h        Thu Sep 07 02:21:17 2006 -0400
+++ b/xen/include/asm-powerpc/reg_defs.h        Thu Sep 07 02:50:06 2006 -0400
@@ -146,10 +146,14 @@
 #define SPRN_DEC    22
 #define SPRN_SRR0   26
 #define SPRN_SRR1   27
+#define SPRN_TBRL   268
+#define SPRN_TBRU   269
 #define SPRN_SPRG0  272
 #define SPRN_SPRG1  273
 #define SPRN_SPRG2  274
 #define SPRN_SPRG3  275
+#define SPRN_TBWL   284
+#define SPRN_TBWU   285
 
 #define SPRN_HSPRG0 304
 #define SPRN_HSPRG1 305
diff -r 464acece0dad -r e20a469dabb4 xen/include/asm-powerpc/smp.h
--- a/xen/include/asm-powerpc/smp.h     Thu Sep 07 02:21:17 2006 -0400
+++ b/xen/include/asm-powerpc/smp.h     Thu Sep 07 02:50:06 2006 -0400
@@ -23,6 +23,7 @@
 
 #include <xen/types.h>
 #include <xen/cpumask.h>
+#include <xen/init.h>
 #include <asm/current.h>
 extern int smp_num_siblings;
 
@@ -32,5 +33,6 @@ extern int smp_num_siblings;
 #define hard_smp_processor_id() raw_smp_processor_id()
 extern cpumask_t cpu_sibling_map[];
 extern cpumask_t cpu_core_map[];
-
+extern void __devinit smp_generic_take_timebase(void);
+extern void __devinit smp_generic_give_timebase(void);
 #endif
diff -r 464acece0dad -r e20a469dabb4 xen/include/asm-powerpc/time.h
--- a/xen/include/asm-powerpc/time.h    Thu Sep 07 02:21:17 2006 -0400
+++ b/xen/include/asm-powerpc/time.h    Thu Sep 07 02:50:06 2006 -0400
@@ -16,7 +16,7 @@
  * Copyright (C) IBM Corp. 2005, 2006
  *
  * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
- *          Hollis Blanchard <jimix@xxxxxxxxxxxxxx>
+ *          Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
  */
 
 #ifndef _ASM_TIME_H_
@@ -54,6 +54,13 @@ static inline u64 get_timebase(void)
     return s;
 }
 
+static inline void set_timebase(unsigned upper, unsigned lower)
+{
+    mttbl(0);
+    mttbu(upper);
+    mttbl(lower);
+}
+
 typedef u64 cycles_t;
 static inline cycles_t get_cycles(void)
 {
diff -r 464acece0dad -r e20a469dabb4 xen/arch/powerpc/smp-tbsync.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/smp-tbsync.c     Thu Sep 07 02:50:06 2006 -0400
@@ -0,0 +1,186 @@
+/*
+ * Smp timebase synchronization for ppc.
+ *
+ * Copyright (C) 2003 Samuel Rydh (samuel@xxxxxxxxx)
+ *
+ */
+/* XXX Xen hacks ... */
+#define get_tb() get_timebase()
+#define set_tb(u,l) set_timebase(u,l)
+#define kmalloc(s,f) xmalloc_bytes(s);
+#define kfree(p) xfree(p)
+#define abs(x) ({                              \
+               int __x = (x);                  \
+               (__x < 0) ? -__x : __x;         \
+       })
+
+#include <xen/kernel.h>
+#include <xen/sched.h>
+#include <xen/smp.h>
+#ifndef __XEN__ 
+#include <linux/unistd.h>
+#endif
+#include <xen/init.h>
+#include <asm/atomic.h>
+#include <asm/smp.h>
+#include <asm/time.h>
+
+
+/* don't mess with IRQs */
+#define local_irq_enable()
+#define local_irq_disable()
+
+#define NUM_ITER               300
+
+enum {
+       kExit=0, kSetAndTest, kTest
+};
+
+static struct {
+       volatile u64            tb;
+       volatile u64            mark;
+       volatile int            cmd;
+       volatile int            handshake;
+       int                     filler[2];
+
+       volatile int            ack;
+       int                     filler2[7];
+
+       volatile int            race_result;
+} *tbsync;
+
+static volatile int            running;
+
+static void __devinit enter_contest(u64 mark, long add)
+{
+       while (get_tb() < mark)
+               tbsync->race_result = add;
+}
+
+void __devinit smp_generic_take_timebase(void)
+{
+       int cmd;
+       u64 tb;
+
+       local_irq_disable();
+       while (!running)
+               barrier();
+       rmb();
+
+       for (;;) {
+               tbsync->ack = 1;
+               while (!tbsync->handshake)
+                       barrier();
+               rmb();
+
+               cmd = tbsync->cmd;
+               tb = tbsync->tb;
+               mb();
+               tbsync->ack = 0;
+               if (cmd == kExit)
+                       break;
+
+               while (tbsync->handshake)
+                       barrier();
+               if (cmd == kSetAndTest)
+                       set_tb(tb >> 32, tb & 0xfffffffful);
+               enter_contest(tbsync->mark, -1);
+       }
+       local_irq_enable();
+}
+
+static int __devinit start_contest(int cmd, long offset, int num)
+{
+       int i, score=0;
+       u64 tb;
+       long mark;
+
+       tbsync->cmd = cmd;
+
+       local_irq_disable();
+       for (i = -3; i < num; ) {
+               tb = get_tb() + 400;
+               tbsync->tb = tb + offset;
+               tbsync->mark = mark = tb + 400;
+
+               wmb();
+
+               tbsync->handshake = 1;
+               while (tbsync->ack)
+                       barrier();
+
+               while (get_tb() <= tb)
+                       barrier();
+               tbsync->handshake = 0;
+               enter_contest(mark, 1);
+
+               while (!tbsync->ack)
+                       barrier();
+
+               if (i++ > 0)
+                       score += tbsync->race_result;
+       }
+       local_irq_enable();
+       return score;
+}
+
+void __devinit smp_generic_give_timebase(void)
+{
+       int i, score, score2, old, min=0, max=5000, offset=1000;
+
+       printk("Synchronizing timebase\n");
+
+       /* if this fails then this kernel won't work anyway... */
+       tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL );
+       memset( tbsync, 0, sizeof(*tbsync) );
+       mb();
+       running = 1;
+
+       while (!tbsync->ack)
+               barrier();
+
+       printk("Got ack\n");
+
+       /* binary search */
+       for (old = -1; old != offset ; offset = (min+max) / 2) {
+               score = start_contest(kSetAndTest, offset, NUM_ITER);
+
+               printk("score %d, offset %d\n", score, offset );
+
+               if( score > 0 )
+                       max = offset;
+               else
+                       min = offset;
+               old = offset;
+       }
+       score = start_contest(kSetAndTest, min, NUM_ITER);
+       score2 = start_contest(kSetAndTest, max, NUM_ITER);
+
+       printk("Min %d (score %d), Max %d (score %d)\n",
+              min, score, max, score2);
+       score = abs(score);
+       score2 = abs(score2);
+       offset = (score < score2) ? min : max;
+
+       /* guard against inaccurate mttb */
+       for (i = 0; i < 10; i++) {
+               start_contest(kSetAndTest, offset, NUM_ITER/10);
+
+               if ((score2 = start_contest(kTest, offset, NUM_ITER)) < 0)
+                       score2 = -score2;
+               if (score2 <= score || score2 < 20)
+                       break;
+       }
+       printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
+
+       /* exiting */
+       tbsync->cmd = kExit;
+       wmb();
+       tbsync->handshake = 1;
+       while (tbsync->ack)
+               barrier();
+       tbsync->handshake = 0;
+       kfree(tbsync);
+       tbsync = NULL;
+       running = 0;
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [POWERPC][XEN] Synchronize Timebase on all CPUs, Xen patchbot-unstable <=