qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation
@ 2015-02-06  3:55 David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 1/9] Generalize QOM publishing of date and time from mc146818rtc.c David Gibson
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

At the moment, the PAPR RTC implementation (actually a paravirt
firmware interface, rather than a normal device) works directly off
host time, and so doesn't respect the options such as clock=vm which
can be specified in the -rtc command line option.  This series
addresses those defects.

The above makes it clearer that the spapr RTC should probably be its
own separate qdev, so this series also implements that.

Finally it moves the code from mc146818rtc for publishing the RTC time
via QOM into generic QOM helpers, and extends the PAPR RTC driver to
export in a similar way.

Changes since v2:
  * We still need the rtc_offset field in sPAPREnvironment to handle
    incoming migrations from older versions, but we no longer send it
    for outgoing migrations.
Changes since v1:
  * Actually create a qdev device for the PAPR RTC
    * Instead of duplicating the QOM publishing code from mc146818, move
        it into a generic helper
	

*** BLURB HERE ***

David Gibson (9):
  Generalize QOM publishing of date and time from mc146818rtc.c
  Add more VMSTATE_*_TEST variants for integers
  pseries: Move sPAPR RTC code into its own file
  pseries: Add more parameter validation in RTAS time of day functions
  pseries: Add spapr_rtc_read() helper function
  pseries: Make RTAS time of day functions respect -rtc options
  pseries: Make the PAPR RTC a qdev device
  pseries: Move rtc_offset into RTC device's state structure
  pseries: Export RTC time via QOM

 hw/ppc/Makefile.objs        |   2 +-
 hw/ppc/spapr.c              |  44 ++++++++-
 hw/ppc/spapr_events.c       |   2 +-
 hw/ppc/spapr_rtas.c         |  49 ----------
 hw/ppc/spapr_rtc.c          | 212 ++++++++++++++++++++++++++++++++++++++++++++
 hw/timer/mc146818rtc.c      |  44 +--------
 include/hw/ppc/spapr.h      |   8 +-
 include/migration/vmstate.h |  15 ++++
 include/qom/object.h        |  14 +++
 qom/object.c                |  79 +++++++++++++++++
 10 files changed, 373 insertions(+), 96 deletions(-)
 create mode 100644 hw/ppc/spapr_rtc.c

-- 
2.1.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 1/9] Generalize QOM publishing of date and time from mc146818rtc.c
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 2/9] Add more VMSTATE_*_TEST variants for integers David Gibson
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

The mc146818rtc driver exposes the current RTC date and time via the "date"
property in QOM (which is also aliased to the machine's "rtc-time"
property).  Currently it uses a custom visitor function rtc_get_date to
do this.

This patch introduces new helpers to the QOM core to expose struct tm
valued properties via a getter function, so that this functionality can be
more easily duplicated in other RTC implementations.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/timer/mc146818rtc.c | 44 ++--------------------------
 include/qom/object.h   | 14 +++++++++
 qom/object.c           | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 41 deletions(-)

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 5a107fa..5db6028 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -831,49 +831,12 @@ static const MemoryRegionOps cmos_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
-                         const char *name, Error **errp)
+static void rtc_get_date(Object *obj, struct tm *current_tm, Error **errp)
 {
-    Error *err = NULL;
     RTCState *s = MC146818_RTC(obj);
-    struct tm current_tm;
 
     rtc_update_time(s);
-    rtc_get_time(s, &current_tm);
-    visit_start_struct(v, NULL, "struct tm", name, 0, &err);
-    if (err) {
-        goto out;
-    }
-    visit_type_int32(v, &current_tm.tm_year, "tm_year", &err);
-    if (err) {
-        goto out_end;
-    }
-    visit_type_int32(v, &current_tm.tm_mon, "tm_mon", &err);
-    if (err) {
-        goto out_end;
-    }
-    visit_type_int32(v, &current_tm.tm_mday, "tm_mday", &err);
-    if (err) {
-        goto out_end;
-    }
-    visit_type_int32(v, &current_tm.tm_hour, "tm_hour", &err);
-    if (err) {
-        goto out_end;
-    }
-    visit_type_int32(v, &current_tm.tm_min, "tm_min", &err);
-    if (err) {
-        goto out_end;
-    }
-    visit_type_int32(v, &current_tm.tm_sec, "tm_sec", &err);
-    if (err) {
-        goto out_end;
-    }
-out_end:
-    error_propagate(errp, err);
-    err = NULL;
-    visit_end_struct(v, errp);
-out:
-    error_propagate(errp, err);
+    rtc_get_time(s, current_tm);
 }
 
 static void rtc_realizefn(DeviceState *dev, Error **errp)
@@ -932,8 +895,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
     qdev_set_legacy_instance_id(dev, base, 3);
     qemu_register_reset(rtc_reset, s);
 
-    object_property_add(OBJECT(s), "date", "struct tm",
-                        rtc_get_date, NULL, NULL, s, NULL);
+    object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL);
 
     object_property_add_alias(qdev_get_machine(), "rtc-time",
                               OBJECT(s), "date", NULL);
diff --git a/include/qom/object.h b/include/qom/object.h
index 89c3092..ba17146 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1204,6 +1204,20 @@ void object_property_add_bool(Object *obj, const char *name,
                               Error **errp);
 
 /**
+ * object_property_add_tm:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @get: the getter or NULL if the property is write-only.
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add a read-only struct tm valued property using a getter function.
+ * This function will add a property of type 'struct tm'.
+ */
+void object_property_add_tm(Object *obj, const char *name,
+                            void (*get)(Object *, struct tm *, Error **),
+                            Error **errp);
+
+/**
  * object_property_add_uint8_ptr:
  * @obj: the object to add a property to
  * @name: the name of the property
diff --git a/qom/object.c b/qom/object.c
index 1812c73..d167038 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1543,6 +1543,85 @@ void object_property_add_bool(Object *obj, const char *name,
     }
 }
 
+typedef struct TMProperty {
+    void (*get)(Object *, struct tm *, Error **);
+} TMProperty;
+
+static void property_get_tm(Object *obj, Visitor *v, void *opaque,
+                            const char *name, Error **errp)
+{
+    TMProperty *prop = opaque;
+    Error *err = NULL;
+    struct tm value;
+
+    prop->get(obj, &value, &err);
+    if (err) {
+        goto out;
+    }
+
+    visit_start_struct(v, NULL, "struct tm", name, 0, &err);
+    if (err) {
+        goto out;
+    }
+    visit_type_int32(v, &value.tm_year, "tm_year", &err);
+    if (err) {
+        goto out_end;
+    }
+    visit_type_int32(v, &value.tm_mon, "tm_mon", &err);
+    if (err) {
+        goto out_end;
+    }
+    visit_type_int32(v, &value.tm_mday, "tm_mday", &err);
+    if (err) {
+        goto out_end;
+    }
+    visit_type_int32(v, &value.tm_hour, "tm_hour", &err);
+    if (err) {
+        goto out_end;
+    }
+    visit_type_int32(v, &value.tm_min, "tm_min", &err);
+    if (err) {
+        goto out_end;
+    }
+    visit_type_int32(v, &value.tm_sec, "tm_sec", &err);
+    if (err) {
+        goto out_end;
+    }
+out_end:
+    error_propagate(errp, err);
+    err = NULL;
+    visit_end_struct(v, errp);
+out:
+    error_propagate(errp, err);
+
+}
+
+static void property_release_tm(Object *obj, const char *name,
+                                void *opaque)
+{
+    TMProperty *prop = opaque;
+    g_free(prop);
+}
+
+void object_property_add_tm(Object *obj, const char *name,
+                            void (*get)(Object *, struct tm *, Error **),
+                            Error **errp)
+{
+    Error *local_err = NULL;
+    TMProperty *prop = g_malloc0(sizeof(*prop));
+
+    prop->get = get;
+
+    object_property_add(obj, name, "struct tm",
+                        get ? property_get_tm : NULL, NULL,
+                        property_release_tm,
+                        prop, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        g_free(prop);
+    }
+}
+
 static char *qdev_get_type(Object *obj, Error **errp)
 {
     return g_strdup(object_get_typename(obj));
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 2/9] Add more VMSTATE_*_TEST variants for integers
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 1/9] Generalize QOM publishing of date and time from mc146818rtc.c David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 3/9] pseries: Move sPAPR RTC code into its own file David Gibson
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

Currently, vmstate.h includes helper macro variants for 8, 16 and 32-bit
unsigned integers which include a "test" function which can selectively
enable or disable the field's presence in the migration stream.

There aren't similar helpers for 64-bit unsigned integers, or any size of
signed integers.  This patch remedies this.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 include/migration/vmstate.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index fa307a6..790a55c 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -636,6 +636,18 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_INT32_POSITIVE_LE(_f, _s)                             \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
 
+#define VMSTATE_INT8_TEST(_f, _s, _t)                               \
+    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int8, int8_t)
+
+#define VMSTATE_INT16_TEST(_f, _s, _t)                               \
+    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int16, int16_t)
+
+#define VMSTATE_INT32_TEST(_f, _s, _t)                                  \
+    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int32, int32_t)
+
+#define VMSTATE_INT64_TEST(_f, _s, _t)                                  \
+    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int64, int64_t)
+
 #define VMSTATE_UINT8_TEST(_f, _s, _t)                               \
     VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint8, uint8_t)
 
@@ -645,6 +657,9 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT32_TEST(_f, _s, _t)                                  \
     VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t)
 
+#define VMSTATE_UINT64_TEST(_f, _s, _t)                                  \
+    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint64, uint64_t)
+
 
 #define VMSTATE_FLOAT64_V(_f, _s, _v)                                 \
     VMSTATE_SINGLE(_f, _s, _v, vmstate_info_float64, float64)
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 3/9] pseries: Move sPAPR RTC code into its own file
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 1/9] Generalize QOM publishing of date and time from mc146818rtc.c David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 2/9] Add more VMSTATE_*_TEST variants for integers David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 4/9] pseries: Add more parameter validation in RTAS time of day functions David Gibson
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

At the moment the RTAS (firmware/hypervisor) time of day functions are
implemented in spapr_rtas.c along with a bunch of other things.  Since
we're going to be expanding these a bit, move the RTAS RTC related code
out into new file spapr_rtc.c.  Also add its own initialization function,
spapr_rtc_init() called from the main machine init routine.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/Makefile.objs   |  2 +-
 hw/ppc/spapr.c         |  3 ++
 hw/ppc/spapr_rtas.c    | 49 -----------------------------
 hw/ppc/spapr_rtc.c     | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ppc/spapr.h |  1 +
 5 files changed, 88 insertions(+), 50 deletions(-)
 create mode 100644 hw/ppc/spapr_rtc.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 19d9920..437955d 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -3,7 +3,7 @@ obj-y += ppc.o ppc_booke.o
 # IBM pSeries (sPAPR)
 obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
 obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
-obj-$(CONFIG_PSERIES) += spapr_pci.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o
 ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
 obj-y += spapr_pci_vfio.o
 endif
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b560459..e2858d1 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1490,6 +1490,9 @@ static void ppc_spapr_init(MachineState *machine)
     /* Set up EPOW events infrastructure */
     spapr_events_init(spapr);
 
+    /* Set up the RTC RTAS interfaces */
+    spapr_rtc_init();
+
     /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
 
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 2ec2a8e..0f1ae55 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -52,51 +52,6 @@ static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     }
 }
 
-static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                 uint32_t token, uint32_t nargs,
-                                 target_ulong args,
-                                 uint32_t nret, target_ulong rets)
-{
-    struct tm tm;
-
-    if (nret != 8) {
-        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
-        return;
-    }
-
-    qemu_get_timedate(&tm, spapr->rtc_offset);
-
-    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-    rtas_st(rets, 1, tm.tm_year + 1900);
-    rtas_st(rets, 2, tm.tm_mon + 1);
-    rtas_st(rets, 3, tm.tm_mday);
-    rtas_st(rets, 4, tm.tm_hour);
-    rtas_st(rets, 5, tm.tm_min);
-    rtas_st(rets, 6, tm.tm_sec);
-    rtas_st(rets, 7, 0); /* we don't do nanoseconds */
-}
-
-static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                 uint32_t token, uint32_t nargs,
-                                 target_ulong args,
-                                 uint32_t nret, target_ulong rets)
-{
-    struct tm tm;
-
-    tm.tm_year = rtas_ld(args, 0) - 1900;
-    tm.tm_mon = rtas_ld(args, 1) - 1;
-    tm.tm_mday = rtas_ld(args, 2);
-    tm.tm_hour = rtas_ld(args, 3);
-    tm.tm_min = rtas_ld(args, 4);
-    tm.tm_sec = rtas_ld(args, 5);
-
-    /* Just generate a monitor event for the change */
-    qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
-    spapr->rtc_offset = qemu_timedate_diff(&tm);
-
-    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
 static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                            uint32_t token, uint32_t nargs, target_ulong args,
                            uint32_t nret, target_ulong rets)
@@ -400,10 +355,6 @@ static void core_rtas_register_types(void)
 {
     spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
                         rtas_display_character);
-    spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
-                        rtas_get_time_of_day);
-    spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
-                        rtas_set_time_of_day);
     spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
     spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
                         rtas_system_reboot);
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
new file mode 100644
index 0000000..e290ac0
--- /dev/null
+++ b/hw/ppc/spapr_rtc.c
@@ -0,0 +1,83 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * RTAS Real Time Clock
+ *
+ * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
+ * Copyright 2014 David Gibson, Red Hat.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#include "cpu.h"
+#include "hw/ppc/spapr.h"
+#include "qapi-event.h"
+
+static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    if (nret != 8) {
+        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+        return;
+    }
+
+    qemu_get_timedate(&tm, spapr->rtc_offset);
+
+    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+    rtas_st(rets, 1, tm.tm_year + 1900);
+    rtas_st(rets, 2, tm.tm_mon + 1);
+    rtas_st(rets, 3, tm.tm_mday);
+    rtas_st(rets, 4, tm.tm_hour);
+    rtas_st(rets, 5, tm.tm_min);
+    rtas_st(rets, 6, tm.tm_sec);
+    rtas_st(rets, 7, 0); /* we don't do nanoseconds */
+}
+
+static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    tm.tm_year = rtas_ld(args, 0) - 1900;
+    tm.tm_mon = rtas_ld(args, 1) - 1;
+    tm.tm_mday = rtas_ld(args, 2);
+    tm.tm_hour = rtas_ld(args, 3);
+    tm.tm_min = rtas_ld(args, 4);
+    tm.tm_sec = rtas_ld(args, 5);
+
+    /* Just generate a monitor event for the change */
+    qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
+    spapr->rtc_offset = qemu_timedate_diff(&tm);
+
+    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+void spapr_rtc_init(void)
+{
+    spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
+                        rtas_get_time_of_day);
+    spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
+                        rtas_set_time_of_day);
+}
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 716bff4..5e90d88 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -480,5 +480,6 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
                  uint32_t liobn, uint64_t window, uint32_t size);
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
                       sPAPRTCETable *tcet);
+void spapr_rtc_init(void);
 
 #endif /* !defined (__HW_SPAPR_H__) */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 4/9] pseries: Add more parameter validation in RTAS time of day functions
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (2 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 3/9] pseries: Move sPAPR RTC code into its own file David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 5/9] pseries: Add spapr_rtc_read() helper function David Gibson
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

Currently, the RTAS time of day functions only partially validate the
number of parameters they receive and return.  Because of how the
parameters are used, this is unlikely to lead to a crash, but it's messy.

This patch adds the missing checks.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_rtc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index e290ac0..13eeab8 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -36,7 +36,7 @@ static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 {
     struct tm tm;
 
-    if (nret != 8) {
+    if ((nargs != 0) || (nret != 8)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
@@ -60,6 +60,11 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 {
     struct tm tm;
 
+    if ((nargs != 7) || (nret != 1)) {
+        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+        return;
+    }
+
     tm.tm_year = rtas_ld(args, 0) - 1900;
     tm.tm_mon = rtas_ld(args, 1) - 1;
     tm.tm_mday = rtas_ld(args, 2);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 5/9] pseries: Add spapr_rtc_read() helper function
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (3 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 4/9] pseries: Add more parameter validation in RTAS time of day functions David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 6/9] pseries: Make RTAS time of day functions respect -rtc options David Gibson
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

The virtual RTC time is used in two places in the pseries machine.  First
is in the RTAS get-time-of-day function which returns the RTC time to the
guest.  Second is in the spapr events code which is used to timestamp
event messages from the hypervisor to the guest.

Currently both call qemu_get_timedate() directly, but we want to change
that so we can properly handle the various -rtc options.  In preparation,
create a helper function to return the virtual RTC time.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_events.c  |  2 +-
 hw/ppc/spapr_rtc.c     | 13 +++++++++++--
 include/hw/ppc/spapr.h |  1 +
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 1b6157d..80c0266 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -246,7 +246,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
     maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
     /* FIXME: section version, subtype and creator id? */
-    qemu_get_timedate(&tm, spapr->rtc_offset);
+    spapr_rtc_read(spapr, &tm, NULL);
     year = tm.tm_year + 1900;
     maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
                                        | (to_bcd(year % 100) << 16)
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index 13eeab8..793368f 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -29,19 +29,28 @@
 #include "hw/ppc/spapr.h"
 #include "qapi-event.h"
 
+void spapr_rtc_read(sPAPREnvironment *spapr, struct tm *tm, uint32_t *ns)
+{
+    qemu_get_timedate(tm, spapr->rtc_offset);
+    if (ns) {
+        *ns = 0; /* we don't do nanoseconds, yet */
+    }
+}
+
 static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
 {
     struct tm tm;
+    uint32_t ns;
 
     if ((nargs != 0) || (nret != 8)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
 
-    qemu_get_timedate(&tm, spapr->rtc_offset);
+    spapr_rtc_read(spapr, &tm, &ns);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
     rtas_st(rets, 1, tm.tm_year + 1900);
@@ -50,7 +59,7 @@ static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     rtas_st(rets, 4, tm.tm_hour);
     rtas_st(rets, 5, tm.tm_min);
     rtas_st(rets, 6, tm.tm_sec);
-    rtas_st(rets, 7, 0); /* we don't do nanoseconds */
+    rtas_st(rets, 7, ns);
 }
 
 static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 5e90d88..eac25ec 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -481,5 +481,6 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
                       sPAPRTCETable *tcet);
 void spapr_rtc_init(void);
+void spapr_rtc_read(sPAPREnvironment *spapr, struct tm *tm, uint32_t *ns);
 
 #endif /* !defined (__HW_SPAPR_H__) */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 6/9] pseries: Make RTAS time of day functions respect -rtc options
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (4 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 5/9] pseries: Add spapr_rtc_read() helper function David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 7/9] pseries: Make the PAPR RTC a qdev device David Gibson
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

In the 'pseries' machine the real time clock is provided by a
paravirtualized firmware interface rather than a device per se; the RTAS
get-time-of-day and set-time-of-day calls.

Out current implementations of those work directly off host time (with
an offset), not respecting options such as clock=vm which can be
specified in the -rtc command line option.

This patch reworks the RTAS RTC code to respect those options, primarily
by basing them on the qemu_clock_get_ns(rtc_clock) function instead of
directly on qemu_get_timedate() (which essentially handles host time, not
virtual rtc time).

As a bonus, this means our get-time-of-day function now also returns
nanoseconds.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_rtc.c | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index 793368f..d6c7a22 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -26,14 +26,24 @@
  *
  */
 #include "cpu.h"
+#include "sysemu/sysemu.h"
 #include "hw/ppc/spapr.h"
 #include "qapi-event.h"
 
+#define NSEC_PER_SEC    1000000000LL
+
 void spapr_rtc_read(sPAPREnvironment *spapr, struct tm *tm, uint32_t *ns)
 {
-    qemu_get_timedate(tm, spapr->rtc_offset);
+    int64_t host_ns = qemu_clock_get_ns(rtc_clock);
+    time_t guest_s;
+
+    guest_s = host_ns / NSEC_PER_SEC + spapr->rtc_offset;
+
+    if (tm) {
+        gmtime_r(&guest_s, tm);
+    }
     if (ns) {
-        *ns = 0; /* we don't do nanoseconds, yet */
+        *ns = host_ns % NSEC_PER_SEC;
     }
 }
 
@@ -68,6 +78,8 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  uint32_t nret, target_ulong rets)
 {
     struct tm tm;
+    time_t new_s;
+    int64_t host_ns;
 
     if ((nargs != 7) || (nret != 1)) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -81,15 +93,35 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     tm.tm_min = rtas_ld(args, 4);
     tm.tm_sec = rtas_ld(args, 5);
 
-    /* Just generate a monitor event for the change */
+    new_s = mktimegm(&tm);
+    if (new_s == -1) {
+        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+        return;
+    }
+
+    /* Generate a monitor event for the change */
     qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
-    spapr->rtc_offset = qemu_timedate_diff(&tm);
+
+    host_ns = qemu_clock_get_ns(rtc_clock);
+
+    spapr->rtc_offset = new_s - host_ns / NSEC_PER_SEC;
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
 void spapr_rtc_init(void)
 {
+    struct tm tm;
+    time_t host_s;
+    int64_t rtc_ns;
+
+    /* Initialize the RTAS RTC from host time */
+
+    qemu_get_timedate(&tm, 0);
+    host_s = mktimegm(&tm);
+    rtc_ns = qemu_clock_get_ns(rtc_clock);
+    spapr->rtc_offset = host_s - rtc_ns / NSEC_PER_SEC;
+
     spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
                         rtas_get_time_of_day);
     spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 7/9] pseries: Make the PAPR RTC a qdev device
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (5 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 6/9] pseries: Make RTAS time of day functions respect -rtc options David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 8/9] pseries: Move rtc_offset into RTC device's state structure David Gibson
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

At present the PAPR RTC isn't a "device" as such - it's accessed only via
firmware/hypervisor calls, and is handled in the sPAPR core code.  This
becomes inconvenient as we extend it in various ways.

This patch makes the PAPR RTC a separate device in the qemu device model.

For now, the only piece of device state - the rtc_offset - is still kept in
the global sPAPREnvironment structure.  That's clearly wrong, but leaving
it to be fixed in a following patch makes for a clearer separation between
the internal re-organization of the device, and the behavioural changes
(because the migration stream format needs to change slightly when the
offset is moved into the device's own state).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr.c         | 10 +++++++++-
 hw/ppc/spapr_events.c  |  2 +-
 hw/ppc/spapr_rtc.c     | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 include/hw/ppc/spapr.h |  7 +++++--
 4 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e2858d1..688adae 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -993,6 +993,14 @@ static void spapr_create_nvram(sPAPREnvironment *spapr)
     spapr->nvram = (struct sPAPRNVRAM *)dev;
 }
 
+static void spapr_rtc_create(sPAPREnvironment *spapr)
+{
+    DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC);
+
+    qdev_init_nofail(dev);
+    spapr->rtc = dev;
+}
+
 /* Returns whether we want to use VGA or not */
 static int spapr_vga_init(PCIBus *pci_bus)
 {
@@ -1491,7 +1499,7 @@ static void ppc_spapr_init(MachineState *machine)
     spapr_events_init(spapr);
 
     /* Set up the RTC RTAS interfaces */
-    spapr_rtc_init();
+    spapr_rtc_create(spapr);
 
     /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 80c0266..283e96b 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -246,7 +246,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
     maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
     /* FIXME: section version, subtype and creator id? */
-    spapr_rtc_read(spapr, &tm, NULL);
+    spapr_rtc_read(spapr->rtc, &tm, NULL);
     year = tm.tm_year + 1900;
     maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
                                        | (to_bcd(year % 100) << 16)
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index d6c7a22..b9f4704 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -30,13 +30,25 @@
 #include "hw/ppc/spapr.h"
 #include "qapi-event.h"
 
+#define SPAPR_RTC(obj) \
+    OBJECT_CHECK(sPAPRRTCState, (obj), TYPE_SPAPR_RTC)
+
+typedef struct sPAPRRTCState sPAPRRTCState;
+struct sPAPRRTCState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+};
+
 #define NSEC_PER_SEC    1000000000LL
 
-void spapr_rtc_read(sPAPREnvironment *spapr, struct tm *tm, uint32_t *ns)
+void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns)
 {
+    sPAPRRTCState *rtc = SPAPR_RTC(dev);
     int64_t host_ns = qemu_clock_get_ns(rtc_clock);
     time_t guest_s;
 
+    assert(rtc);
+
     guest_s = host_ns / NSEC_PER_SEC + spapr->rtc_offset;
 
     if (tm) {
@@ -60,7 +72,12 @@ static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
         return;
     }
 
-    spapr_rtc_read(spapr, &tm, &ns);
+    if (!spapr->rtc) {
+        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+        return;
+    }
+
+    spapr_rtc_read(spapr->rtc, &tm, &ns);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
     rtas_st(rets, 1, tm.tm_year + 1900);
@@ -86,6 +103,11 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
         return;
     }
 
+    if (!spapr->rtc) {
+        rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+        return;
+    }
+
     tm.tm_year = rtas_ld(args, 0) - 1900;
     tm.tm_mon = rtas_ld(args, 1) - 1;
     tm.tm_mday = rtas_ld(args, 2);
@@ -109,7 +131,7 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-void spapr_rtc_init(void)
+static void spapr_rtc_realize(DeviceState *dev, Error **errp)
 {
     struct tm tm;
     time_t host_s;
@@ -121,9 +143,30 @@ void spapr_rtc_init(void)
     host_s = mktimegm(&tm);
     rtc_ns = qemu_clock_get_ns(rtc_clock);
     spapr->rtc_offset = host_s - rtc_ns / NSEC_PER_SEC;
+}
+
+static void spapr_rtc_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = spapr_rtc_realize;
 
     spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
                         rtas_get_time_of_day);
     spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
                         rtas_set_time_of_day);
 }
+
+static const TypeInfo spapr_rtc_info = {
+    .name          = TYPE_SPAPR_RTC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(sPAPRRTCState),
+    .class_size = sizeof(XICSStateClass),
+    .class_init    = spapr_rtc_class_init,
+};
+
+static void spapr_rtc_register_types(void)
+{
+    type_register_static(&spapr_rtc_info);
+}
+type_init(spapr_rtc_register_types)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index eac25ec..9a7bf36 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -15,6 +15,7 @@ typedef struct sPAPREnvironment {
     QLIST_HEAD(, sPAPRPHBState) phbs;
     struct sPAPRNVRAM *nvram;
     XICSState *icp;
+    DeviceState *rtc;
 
     hwaddr ram_limit;
     void *htab;
@@ -480,7 +481,9 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
                  uint32_t liobn, uint64_t window, uint32_t size);
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
                       sPAPRTCETable *tcet);
-void spapr_rtc_init(void);
-void spapr_rtc_read(sPAPREnvironment *spapr, struct tm *tm, uint32_t *ns);
+
+#define TYPE_SPAPR_RTC "spapr-rtc"
+
+void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns);
 
 #endif /* !defined (__HW_SPAPR_H__) */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 8/9] pseries: Move rtc_offset into RTC device's state structure
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (6 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 7/9] pseries: Make the PAPR RTC a qdev device David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 9/9] pseries: Export RTC time via QOM David Gibson
  2015-02-09 21:47 ` [Qemu-devel] [Qemu-ppc] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation Alexander Graf
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

The initial creation of the PAPR RTC qdev class left a wart - the rtc's
offset was left in the sPAPREnvironment structure, accessed via a global.

This patch moves it into the RTC device's own state structure, were it
belongs.  This requires a small change to the migration stream format.  In
order to handle incoming streams from older versions, we also need to
retain the rtc_offset field in the sPAPREnvironment structure, so that it
can be loaded into via the vmsd, then pushed into the RTC device.

Since we're changing the migration format, this also takes the opportunity
to:

  * Change the rtc offset from a value in seconds to a value in
    nanoseconds, allowing nanosecond offsets between host and guest
    rtc time, if desired.

  * Remove both the already unused "next_irq" field and now unused
    "rtc_offset" field from the new version of the spapr migration
    stream

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr.c         | 30 +++++++++++++++++++++++++++---
 hw/ppc/spapr_rtc.c     | 41 +++++++++++++++++++++++++++++++++++++----
 include/hw/ppc/spapr.h |  3 ++-
 3 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 688adae..2264802 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1018,15 +1018,39 @@ static int spapr_vga_init(PCIBus *pci_bus)
     }
 }
 
+static int spapr_post_load(void *opaque, int version_id)
+{
+    sPAPREnvironment *spapr = (sPAPREnvironment *)opaque;
+    int err = 0;
+
+    /* In earlier versions, there was no seperate qdev for the PAPR
+     * RTC, so the RTC offset was stored directly in sPAPREnvironment.
+     * So when migrating from those versions, poke the incoming offset
+     * value into the RTC device */
+    if (version_id < 3) {
+        err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset);
+    }
+
+    return err;
+}
+
+static bool version_before_3(void *opaque, int version_id)
+{
+    return version_id < 3;
+}
+
 static const VMStateDescription vmstate_spapr = {
     .name = "spapr",
-    .version_id = 2,
+    .version_id = 3,
     .minimum_version_id = 1,
+    .post_load = spapr_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UNUSED(4), /* used to be @next_irq */
+        /* used to be @next_irq */
+        VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
 
         /* RTC offset */
-        VMSTATE_UINT64(rtc_offset, sPAPREnvironment),
+        VMSTATE_UINT64_TEST(rtc_offset, sPAPREnvironment, version_before_3),
+
         VMSTATE_PPC_TIMEBASE_V(tb, sPAPREnvironment, 2),
         VMSTATE_END_OF_LIST()
     },
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index b9f4704..5ad0823 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -37,6 +37,7 @@ typedef struct sPAPRRTCState sPAPRRTCState;
 struct sPAPRRTCState {
     /*< private >*/
     SysBusDevice parent_obj;
+    int64_t ns_offset;
 };
 
 #define NSEC_PER_SEC    1000000000LL
@@ -45,20 +46,37 @@ void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns)
 {
     sPAPRRTCState *rtc = SPAPR_RTC(dev);
     int64_t host_ns = qemu_clock_get_ns(rtc_clock);
+    int64_t guest_ns;
     time_t guest_s;
 
     assert(rtc);
 
-    guest_s = host_ns / NSEC_PER_SEC + spapr->rtc_offset;
+    guest_ns = host_ns + rtc->ns_offset;
+    guest_s = guest_ns / NSEC_PER_SEC;
 
     if (tm) {
         gmtime_r(&guest_s, tm);
     }
     if (ns) {
-        *ns = host_ns % NSEC_PER_SEC;
+        *ns = guest_ns;
     }
 }
 
+int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset)
+{
+    sPAPRRTCState *rtc;
+
+    if (!dev) {
+        return -ENODEV;
+    }
+
+    rtc = SPAPR_RTC(dev);
+
+    rtc->ns_offset = legacy_offset * NSEC_PER_SEC;
+
+    return 0;
+}
+
 static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
@@ -94,6 +112,7 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
 {
+    sPAPRRTCState *rtc;
     struct tm tm;
     time_t new_s;
     int64_t host_ns;
@@ -124,15 +143,18 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     /* Generate a monitor event for the change */
     qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
 
+    rtc = SPAPR_RTC(spapr->rtc);
+
     host_ns = qemu_clock_get_ns(rtc_clock);
 
-    spapr->rtc_offset = new_s - host_ns / NSEC_PER_SEC;
+    rtc->ns_offset = (new_s * NSEC_PER_SEC) - host_ns;
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
 static void spapr_rtc_realize(DeviceState *dev, Error **errp)
 {
+    sPAPRRTCState *rtc = SPAPR_RTC(dev);
     struct tm tm;
     time_t host_s;
     int64_t rtc_ns;
@@ -142,14 +164,25 @@ static void spapr_rtc_realize(DeviceState *dev, Error **errp)
     qemu_get_timedate(&tm, 0);
     host_s = mktimegm(&tm);
     rtc_ns = qemu_clock_get_ns(rtc_clock);
-    spapr->rtc_offset = host_s - rtc_ns / NSEC_PER_SEC;
+    rtc->ns_offset = host_s * NSEC_PER_SEC - rtc_ns;
 }
 
+static const VMStateDescription vmstate_spapr_rtc = {
+    .name = "spapr/rtc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT64(ns_offset, sPAPRRTCState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 static void spapr_rtc_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     dc->realize = spapr_rtc_realize;
+    dc->vmsd = &vmstate_spapr_rtc;
 
     spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
                         rtas_get_time_of_day);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 9a7bf36..6a4f982 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -27,7 +27,7 @@ typedef struct sPAPREnvironment {
     void *rtas_blob;
     void *fdt_skel;
     target_ulong entry_point;
-    uint64_t rtc_offset;
+    uint64_t rtc_offset; /* Now used only during incoming migration */
     struct PPCTimebase tb;
     bool has_graphics;
 
@@ -485,5 +485,6 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
 #define TYPE_SPAPR_RTC "spapr-rtc"
 
 void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns);
+int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset);
 
 #endif /* !defined (__HW_SPAPR_H__) */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCHv3 9/9] pseries: Export RTC time via QOM
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (7 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 8/9] pseries: Move rtc_offset into RTC device's state structure David Gibson
@ 2015-02-06  3:55 ` David Gibson
  2015-02-09 21:47 ` [Qemu-devel] [Qemu-ppc] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation Alexander Graf
  9 siblings, 0 replies; 11+ messages in thread
From: David Gibson @ 2015-02-06  3:55 UTC (permalink / raw)
  To: agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel, David Gibson

On x86, the guest's RTC can be read with QMP, either from the RTC device's
"date" property or via the "rtc-time" property on the machine (which is an
alias to the former).  This is set up in the mc146818rtc driver, and
doesn't work on other targets.

This patch adds a similar "date" property to the pseries machine's RTAS RTC
and adds a compatible alias to the machine.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr.c     | 3 +++
 hw/ppc/spapr_rtc.c | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 2264802..e6623e1 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -999,6 +999,9 @@ static void spapr_rtc_create(sPAPREnvironment *spapr)
 
     qdev_init_nofail(dev);
     spapr->rtc = dev;
+
+    object_property_add_alias(qdev_get_machine(), "rtc-time",
+                              OBJECT(spapr->rtc), "date", NULL);
 }
 
 /* Returns whether we want to use VGA or not */
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index 5ad0823..83eb7c1 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -152,6 +152,11 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
+static void spapr_rtc_qom_date(Object *obj, struct tm *current_tm, Error **errp)
+{
+    spapr_rtc_read(DEVICE(obj), current_tm, NULL);
+}
+
 static void spapr_rtc_realize(DeviceState *dev, Error **errp)
 {
     sPAPRRTCState *rtc = SPAPR_RTC(dev);
@@ -165,6 +170,8 @@ static void spapr_rtc_realize(DeviceState *dev, Error **errp)
     host_s = mktimegm(&tm);
     rtc_ns = qemu_clock_get_ns(rtc_clock);
     rtc->ns_offset = host_s * NSEC_PER_SEC - rtc_ns;
+
+    object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date, NULL);
 }
 
 static const VMStateDescription vmstate_spapr_rtc = {
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation
  2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
                   ` (8 preceding siblings ...)
  2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 9/9] pseries: Export RTC time via QOM David Gibson
@ 2015-02-09 21:47 ` Alexander Graf
  9 siblings, 0 replies; 11+ messages in thread
From: Alexander Graf @ 2015-02-09 21:47 UTC (permalink / raw)
  To: David Gibson, agraf, aik, mdroth
  Cc: amit.shah, pbonzini, qemu-ppc, qemu-devel



On 06.02.15 04:55, David Gibson wrote:
> At the moment, the PAPR RTC implementation (actually a paravirt
> firmware interface, rather than a normal device) works directly off
> host time, and so doesn't respect the options such as clock=vm which
> can be specified in the -rtc command line option.  This series
> addresses those defects.
> 
> The above makes it clearer that the spapr RTC should probably be its
> own separate qdev, so this series also implements that.
> 
> Finally it moves the code from mc146818rtc for publishing the RTC time
> via QOM into generic QOM helpers, and extends the PAPR RTC driver to
> export in a similar way.
> 
> Changes since v2:
>   * We still need the rtc_offset field in sPAPREnvironment to handle
>     incoming migrations from older versions, but we no longer send it
>     for outgoing migrations.
> Changes since v1:
>   * Actually create a qdev device for the PAPR RTC
>     * Instead of duplicating the QOM publishing code from mc146818, move
>         it into a generic helper
> 

Thanks, applied to ppc-next.


Alex

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-02-09 21:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-06  3:55 [Qemu-devel] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 1/9] Generalize QOM publishing of date and time from mc146818rtc.c David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 2/9] Add more VMSTATE_*_TEST variants for integers David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 3/9] pseries: Move sPAPR RTC code into its own file David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 4/9] pseries: Add more parameter validation in RTAS time of day functions David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 5/9] pseries: Add spapr_rtc_read() helper function David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 6/9] pseries: Make RTAS time of day functions respect -rtc options David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 7/9] pseries: Make the PAPR RTC a qdev device David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 8/9] pseries: Move rtc_offset into RTC device's state structure David Gibson
2015-02-06  3:55 ` [Qemu-devel] [PATCHv3 9/9] pseries: Export RTC time via QOM David Gibson
2015-02-09 21:47 ` [Qemu-devel] [Qemu-ppc] [PATCHv3 0/9] pseries: Fix and extend PAPR RTC implementation Alexander Graf

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).