All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ian Campbell <Ian.Campbell@citrix.com>
To: xen-devel@lists.xen.org
Subject: [PATCH incomplete] xen: arm: wallclock support (incomplete, needs work/refactoring)
Date: Tue, 21 Oct 2014 15:07:50 +0100	[thread overview]
Message-ID: <1413900470.23337.47.camel@citrix.com> (raw)
In-Reply-To: <1413888616.23337.22.camel@citrix.com>

[-- Attachment #1: Type: text/plain, Size: 894 bytes --]

On Tue, 2014-10-21 at 11:50 +0100, Ian Campbell wrote:
> > +/* Wall-clock time is not currently available on ARM, so this is always zero for now:
> > + * http://secure-web.cisco.com/1riZQA377dZLKCo5tuoXAK4khWPPIvJePpjzLaQORhQEDB_kQWnA4fzAgRlX09RiW8tAnBtxXwom3oU37PxptJvdEgqAEvbJAHz9mB8G4h6XwnaDr9bcSh1o32Mldi1w6uBD_3Bf3fOL4m9UHxTUsdzkhF1wAMQEQej0ALt0lZHQ/http%3A%2F%2Fwiki.xenproject.org%2Fwiki%2FXen_ARM_TODO#Expose_Wallclock_time_to_guests
> 
> I have some slightly hacky patches for this, I really should dust them
> off and submit them...

Since that doesn't seem likely to happen soon rather than let them rot
in my tree here are the two patches (one for Xen, one for Linux). IMO
they need a fair bit of refactoring (e.g. to make useful bits of the x86
support common/generic) and other code cleanup etc.

Maybe someone would like to pick them up, or else I'll get to it
eventually.

Ian.

[-- Attachment #2: xen.patch --]
[-- Type: text/x-patch, Size: 6762 bytes --]

From 8290927257600951622d416c9e76ab9042c4d47d Mon Sep 17 00:00:00 2001
From: Ian Campbell <ian.campbell@citrix.com>
Date: Tue, 5 Aug 2014 11:10:54 +0100
Subject: [PATCH] xen: arm: support platform_hypercalls for XENPF_settime

Very WIP. Needs proper refactoring of x86 stuff etc.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/Makefile   |    1 +
 xen/arch/arm/domain.c   |    4 +++
 xen/arch/arm/time.c     |   63 ++++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/traps.c    |    1 +
 xen/include/xsm/dummy.h |   12 ++++-----
 xen/include/xsm/xsm.h   |   13 +++++-----
 6 files changed, 81 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index c13206f..f08187e 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -34,6 +34,7 @@ obj-y += hvm.o
 obj-y += device.o
 obj-y += decode.o
 obj-y += processor.o
+obj-y += platform_hypercall.o
 
 #obj-bin-y += ....o
 
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 2b53931..a48adfc 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -630,6 +630,7 @@ static int is_guest_pv64_psr(uint32_t psr)
 int arch_set_info_guest(
     struct vcpu *v, vcpu_guest_context_u c)
 {
+    struct domain *d = v->domain;
     struct vcpu_guest_context *ctxt = c.nat;
     struct vcpu_guest_core_regs *regs = &c.nat->user_regs;
 
@@ -667,6 +668,9 @@ int arch_set_info_guest(
     v->arch.ttbr1 = ctxt->ttbr1;
     v->arch.ttbcr = ctxt->ttbcr;
 
+    if ( v->vcpu_id == 0 )
+        update_domain_wallclock_time(d);
+
     v->is_initialised = 1;
 
     if ( ctxt->flags & VGCF_online )
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index a6436f1..e271530 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -35,6 +35,7 @@
 #include <asm/vgic.h>
 #include <asm/cpufeature.h>
 #include <asm/platform.h>
+#include <asm/div64.h>
 
 uint64_t __read_mostly boot_count;
 
@@ -217,13 +218,73 @@ void update_vcpu_system_time(struct vcpu *v)
 
 void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds)
 {
+    printk("dom%d time offset %"PRId32"\n", d->domain_id, time_offset_seconds);
     d->time_offset_seconds = time_offset_seconds;
     /* XXX update guest visible wallclock time */
 }
 
+static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
+static DEFINE_SPINLOCK(wc_lock);
+
+/* Explicitly OR with 1 just in case version number gets out of sync. */
+#define version_update_begin(v) (((v)+1)|1)
+#define version_update_end(v)   ((v)+1)
+
+void update_domain_wallclock_time(struct domain *d)
+{
+    uint32_t *wc_version;
+
+    spin_lock(&wc_lock);
+
+    wc_version = &shared_info(d, wc_version);
+    *wc_version = version_update_begin(*wc_version);
+    wmb();
+
+    shared_info(d, wc_sec)  = wc_sec + d->time_offset_seconds;
+    shared_info(d, wc_nsec) = wc_nsec;
+
+    wmb();
+    *wc_version = version_update_end(*wc_version);
+
+    spin_unlock(&wc_lock);
+}
+
+/* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
+/* XXX refactor x86 */
+void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
+{
+    u64 x;
+    u32 y;
+    struct domain *d;
+
+    x = SECONDS(secs) + (u64)nsecs - system_time_base;
+    y = do_div(x, 1000000000);
+
+    spin_lock(&wc_lock);
+    wc_sec  = x;
+    wc_nsec = y;
+    spin_unlock(&wc_lock);
+
+    rcu_read_lock(&domlist_read_lock);
+    for_each_domain ( d )
+        update_domain_wallclock_time(d);
+    rcu_read_unlock(&domlist_read_lock);
+}
+
 struct tm wallclock_time(uint64_t *ns)
 {
-    return (struct tm) { 0 };
+    uint64_t seconds, nsec;
+
+    if ( !wc_sec )
+        return (struct tm) { 0 };
+
+    seconds = NOW() + SECONDS(wc_sec) + wc_nsec;
+    nsec = do_div(seconds, 1000000000);
+
+    if ( ns )
+        *ns = nsec;
+
+    return gmtime(seconds);
 }
 
 /*
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 76a9586..227b4e2 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1035,6 +1035,7 @@ static arm_hypercall_t arm_hypercall_table[] = {
     HYPERCALL(grant_table_op, 3),
     HYPERCALL(multicall, 2),
     HYPERCALL_ARM(vcpu_op, 3),
+    HYPERCALL(platform_op, 1),
 };
 
 typedef int (*arm_psci_fn_t)(uint32_t, register_t);
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index c5aa316..2cc145c 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -507,6 +507,12 @@ static XSM_INLINE int xsm_hvm_param_nested(XSM_DEFAULT_ARG struct domain *d)
     return xsm_default_action(action, current->domain, d);
 }
 
+static XSM_INLINE int xsm_platform_op(XSM_DEFAULT_ARG uint32_t op)
+{
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
+}
+
 #ifdef CONFIG_X86
 static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID)
 {
@@ -574,12 +580,6 @@ static XSM_INLINE int xsm_apic(XSM_DEFAULT_ARG struct domain *d, int cmd)
     return xsm_default_action(action, d, NULL);
 }
 
-static XSM_INLINE int xsm_platform_op(XSM_DEFAULT_ARG uint32_t op)
-{
-    XSM_ASSERT_ACTION(XSM_PRIV);
-    return xsm_default_action(action, current->domain, NULL);
-}
-
 static XSM_INLINE int xsm_machine_memory_map(XSM_DEFAULT_VOID)
 {
     XSM_ASSERT_ACTION(XSM_PRIV);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index a85045d..7752b37 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -140,6 +140,8 @@ struct xsm_operations {
     int (*hvm_control) (struct domain *d, unsigned long op);
     int (*hvm_param_nested) (struct domain *d);
 
+    int (*platform_op) (uint32_t cmd);
+
 #ifdef CONFIG_X86
     int (*do_mca) (void);
     int (*shadow_control) (struct domain *d, uint32_t op);
@@ -153,7 +155,6 @@ struct xsm_operations {
     int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
     int (*apic) (struct domain *d, int cmd);
     int (*memtype) (uint32_t access);
-    int (*platform_op) (uint32_t cmd);
     int (*machine_memory_map) (void);
     int (*domain_memory_map) (struct domain *d);
 #define XSM_MMU_UPDATE_READ      1
@@ -534,6 +535,11 @@ static inline int xsm_hvm_param_nested (xsm_default_t def, struct domain *d)
     return xsm_ops->hvm_param_nested(d);
 }
 
+static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
+{
+    return xsm_ops->platform_op(op);
+}
+
 #ifdef CONFIG_X86
 static inline int xsm_do_mca(xsm_default_t def)
 {
@@ -595,11 +601,6 @@ static inline int xsm_memtype (xsm_default_t def, uint32_t access)
     return xsm_ops->memtype(access);
 }
 
-static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
-{
-    return xsm_ops->platform_op(op);
-}
-
 static inline int xsm_machine_memory_map(xsm_default_t def)
 {
     return xsm_ops->machine_memory_map();
-- 
1.7.10.4


[-- Attachment #3: linux.patch --]
[-- Type: text/x-patch, Size: 6848 bytes --]

From 1284ba2380b32bf62789b738dbac4d99da463ea1 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ian.campbell@citrix.com>
Date: Tue, 5 Aug 2014 15:23:23 +0100
Subject: [PATCH] Wallclock time support. Needs much refactoring etc

---
 arch/arm/include/asm/xen/hypercall.h |    9 +++
 arch/arm/xen/enlighten.c             |  121 ++++++++++++++++++++++++++++++++++
 arch/arm/xen/hypercall.S             |    4 +-
 3 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
index 712b50e..055399a 100644
--- a/arch/arm/include/asm/xen/hypercall.h
+++ b/arch/arm/include/asm/xen/hypercall.h
@@ -35,6 +35,7 @@
 
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
+#include <xen/interface/platform.h>
 
 long privcmd_call(unsigned call, unsigned long a1,
 		unsigned long a2, unsigned long a3,
@@ -49,6 +50,14 @@ int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
 int HYPERVISOR_physdev_op(int cmd, void *arg);
 int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
 int HYPERVISOR_tmem_op(void *arg);
+int HYPERVISOR_dom0_op_raw(struct xen_platform_op *platform_op);
+static inline int
+HYPERVISOR_dom0_op(struct xen_platform_op *platform_op)
+{
+        platform_op->interface_version = XENPF_INTERFACE_VERSION;
+        return HYPERVISOR_dom0_op_raw(platform_op);
+}
+
 int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr);
 
 static inline int
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 1e63243..0364987 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -11,6 +11,7 @@
 #include <xen/xenbus.h>
 #include <xen/page.h>
 #include <xen/interface/sched.h>
+#include <xen/interface/platform.h>
 #include <xen/xen-ops.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -24,6 +25,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
+#include <linux/pvclock_gtod.h>
 
 #include <linux/mm.h>
 
@@ -219,6 +221,122 @@ static irqreturn_t xen_arm_callback(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+unsigned long xen_clocksource_read(void)
+{
+	unsigned long val = 0;
+	/* XXX arch timer? Error handling etc etc */
+	if (read_current_timer(&val) < 0)
+		printk("read_current_timer failed?\n");
+	return val;
+}
+
+void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
+                            struct pvclock_vcpu_time_info *vcpu_time,
+                            struct timespec *ts)
+{
+        u32 version;
+        u64 delta;
+        struct timespec now;
+
+        /* get wallclock at system boot */
+        do {
+                version = wall_clock->version;
+                rmb();          /* fetch version before time */
+                now.tv_sec  = wall_clock->sec;
+                now.tv_nsec = wall_clock->nsec;
+                rmb();          /* fetch time before checking version */
+        } while ((wall_clock->version & 1) || (version != wall_clock->version));
+
+        //delta = pvclock_clocksource_read(vcpu_time);    /* time since system boot */
+	delta = xen_clocksource_read();
+        delta += now.tv_sec * (u64)NSEC_PER_SEC + now.tv_nsec;
+
+        now.tv_nsec = do_div(delta, NSEC_PER_SEC);
+        now.tv_sec = delta;
+
+        set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
+}
+
+static void xen_read_wallclock(struct timespec *ts)
+{
+	struct shared_info *s = HYPERVISOR_shared_info;
+	struct pvclock_wall_clock *wall_clock = &(s->wc);
+        struct pvclock_vcpu_time_info *vcpu_time;
+
+	vcpu_time = &get_cpu_var(xen_vcpu)->time;
+	pvclock_read_wallclock(wall_clock, vcpu_time, ts);
+	put_cpu_var(xen_vcpu);
+}
+
+/* Parts could be common with x86? */
+static int xen_pvclock_gtod_notify(struct notifier_block *nb,
+				   unsigned long was_set, void *priv)
+{
+	/* Protected by the calling core code serialization */
+	static struct timespec next_sync;
+
+	struct xen_platform_op op;
+	struct timespec now;
+
+	now = __current_kernel_time();
+
+	/*
+	 * We only take the expensive HV call when the clock was set
+	 * or when the 11 minutes RTC synchronization time elapsed.
+	 */
+	if (!was_set && timespec_compare(&now, &next_sync) < 0)
+		return NOTIFY_OK;
+
+	op.cmd = XENPF_settime;
+	op.u.settime.secs = now.tv_sec;
+	op.u.settime.nsecs = now.tv_nsec;
+	op.u.settime.system_time = xen_clocksource_read();
+	printk("GTOD: Setting to %ld.%ld at %lld\n",
+	       (long)op.u.settime.secs,
+	       (long)op.u.settime.nsecs,
+	       (long long)op.u.settime.system_time);
+	(void)HYPERVISOR_dom0_op(&op);
+
+	/*
+	 * Move the next drift compensation time 11 minutes
+	 * ahead. That's emulating the sync_cmos_clock() update for
+	 * the hardware RTC.
+	 */
+	next_sync = now;
+	next_sync.tv_sec += 11 * 60;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block xen_pvclock_gtod_notifier = {
+	.notifier_call = xen_pvclock_gtod_notify,
+};
+
+static void __init xen_time_init(void)
+{
+	//int cpu = smp_processor_id();
+	struct timespec tp;
+
+	/* Set initial system time with full resolution */
+	xen_read_wallclock(&tp);
+	do_settimeofday(&tp);
+
+	printk("INITIAL TIME %ld.%ld\n",
+	       (long)tp.tv_sec,
+	       (long)tp.tv_nsec);
+	{
+		struct shared_info *s = HYPERVISOR_shared_info;
+		struct pvclock_wall_clock *wall_clock = &(s->wc);
+		struct pvclock_vcpu_time_info *vcpu_time;
+		printk("SHARED INFO TIME %ld.%ld\n",
+		       (long)wall_clock->sec,
+		       (long)wall_clock->nsec);
+	}
+
+	if (xen_initial_domain())
+		pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
+}
+
 /*
  * see Documentation/devicetree/bindings/arm/xen.txt for the
  * documentation of the Xen Device Tree format.
@@ -323,6 +441,8 @@ static int __init xen_guest_init(void)
 
 	register_cpu_notifier(&xen_cpu_notifier);
 
+	xen_time_init();
+
 	return 0;
 }
 early_initcall(xen_guest_init);
@@ -359,4 +479,5 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_tmem_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_multicall);
+EXPORT_SYMBOL_GPL(HYPERVISOR_dom0_op_raw);
 EXPORT_SYMBOL_GPL(privcmd_call);
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
index 44e3a5f..d3bf35e 100644
--- a/arch/arm/xen/hypercall.S
+++ b/arch/arm/xen/hypercall.S
@@ -78,7 +78,6 @@ ENTRY(HYPERVISOR_##hypercall)			\
 ENDPROC(HYPERVISOR_##hypercall)
 
                 .text
-
 HYPERCALL2(xen_version);
 HYPERCALL3(console_io);
 HYPERCALL3(grant_table_op);
@@ -91,6 +90,9 @@ HYPERCALL3(vcpu_op);
 HYPERCALL1(tmem_op);
 HYPERCALL2(multicall);
 
+#define __HYPERVISOR_dom0_op_raw __HYPERVISOR_dom0_op /* Hack to allow setting interface version from C wrapper */
+HYPERCALL1(dom0_op_raw);/*XXX legacy name for what is now platform_op, used by x86 too*/
+
 ENTRY(privcmd_call)
 	stmdb sp!, {r4}
 	mov r12, r0
-- 
1.7.10.4


[-- Attachment #4: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

  reply	other threads:[~2014-10-21 14:07 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-03  9:20 [PATCH ARM v8 0/4] mini-os: initial ARM support Thomas Leonard
2014-10-03  9:20 ` [PATCH ARM v8 1/4] mini-os: arm: time Thomas Leonard
2014-10-21 10:50   ` Ian Campbell
2014-10-21 14:07     ` Ian Campbell [this message]
2014-10-26  9:51     ` Thomas Leonard
2014-10-27 10:34       ` Ian Campbell
2014-11-13 16:29         ` Thomas Leonard
2014-11-14 10:29           ` Ian Campbell
2014-11-19 20:57             ` Konrad Rzeszutek Wilk
2015-01-08 15:52     ` Ian Campbell
2015-01-08 15:58       ` Thomas Leonard
2015-01-08 16:04         ` Ian Campbell
2014-10-03  9:20 ` [PATCH ARM v8 2/4] mini-os: arm: interrupt controller Thomas Leonard
2014-10-21 11:00   ` Ian Campbell
2014-10-21 14:26     ` Julien Grall
2014-10-21 15:16       ` Ian Campbell
2014-10-21 15:22         ` Julien Grall
2014-10-21 15:35           ` Ian Campbell
2014-10-21 16:03             ` Julien Grall
2014-10-21 18:14               ` Anil Madhavapeddy
2014-10-21 19:18                 ` Ian Campbell
2014-10-21 21:54     ` Samuel Thibault
2014-10-22  9:03       ` Ian Campbell
2014-10-22 13:06         ` Julien Grall
2014-10-22 13:14           ` Samuel Thibault
2014-10-28 15:15           ` Thomas Leonard
2014-10-28 15:25             ` Julien Grall
2014-10-28 15:43               ` Thomas Leonard
2014-10-28 15:51                 ` Julien Grall
2014-11-14 10:22                   ` Thomas Leonard
2014-11-14 11:33                     ` Julien Grall
2014-11-14 11:42                       ` Ian Campbell
2014-11-14 11:48                         ` Julien Grall
2014-11-14 12:01                           ` Ian Campbell
2014-10-03  9:20 ` [PATCH ARM v8 3/4] mini-os: arm: build system Thomas Leonard
2014-10-21 11:44   ` Ian Campbell
2014-10-21 21:50     ` Samuel Thibault
2014-10-22  9:01       ` Ian Campbell
2014-10-22  9:59         ` Samuel Thibault
2014-10-26  9:46       ` Thomas Leonard
2014-10-26  9:55         ` Samuel Thibault
2014-10-26 10:25           ` Thomas Leonard
2014-11-17 11:42             ` Thomas Leonard
2014-11-17 11:45               ` Ian Campbell
2014-11-17 11:47               ` Andrew Cooper
2014-11-17 11:47               ` Samuel Thibault
2014-10-03  9:20 ` [PATCH ARM v8 4/4] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard

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=1413900470.23337.47.camel@citrix.com \
    --to=ian.campbell@citrix.com \
    --cc=xen-devel@lists.xen.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.