@@ -15,6 +15,7 @@
#define QDEV_CLOCK_H
#include "hw/clock.h"
+#include "hw/qdev-core.h"
/**
* qdev_init_clock_in:
@@ -161,4 +162,13 @@ typedef struct ClockPortInitElem ClockPortInitArray[];
*/
void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks);
+/**
+ * qdev_get_clocklist:
+ * @dev: the device to find clock for
+ * @name: clock name
+ *
+ * Returns: a named clock list entry or NULL if the clock was not found
+ */
+NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name);
+
#endif /* QDEV_CLOCK_H */
@@ -408,4 +408,28 @@ static inline int64_t clock_step(int64_t step)
return qtest_clock_step(global_qtest, step);
}
+/**
+ * qtest_qdev_clock_in_get_hz:
+ * @path: QOM path of a device.
+ * @name: Clock name.
+ *
+ * Returns: device clock frequency in HZ
+ */
+static inline uint64_t dev_clock_in_get_hz(const char *path, const char *name)
+{
+ return qtest_dev_clock_in_get_hz(global_qtest, path, name);
+}
+
+/**
+ * qtest_qdev_clock_out_get_hz:
+ * @path: QOM path of a device.
+ * @name: Clock name.
+ *
+ * Returns: device clock frequency in HZ
+ */
+static inline uint64_t dev_clock_out_get_hz(const char *path, const char *name)
+{
+ return qtest_dev_clock_out_get_hz(global_qtest, path, name);
+}
+
#endif
@@ -1169,4 +1169,26 @@ bool have_qemu_img(void);
*/
bool mkimg(const char *file, const char *fmt, unsigned size_mb);
+/**
+ * qtest_qdev_clock_in_get_hz:
+ * @s: #QTestState instance to operate on.
+ * @path: QOM path of a device.
+ * @name: Clock name.
+ *
+ * Returns: device clock frequency in HZ
+ */
+uint64_t qtest_dev_clock_in_get_hz(QTestState *s, const char *path,
+ const char *name);
+
+/**
+ * qtest_qdev_clock_out_get_hz:
+ * @s: #QTestState instance to operate on.
+ * @path: QOM path of a device.
+ * @name: Clock name.
+ *
+ * Returns: device clock frequency in HZ
+ */
+uint64_t qtest_dev_clock_out_get_hz(QTestState *s, const char *path,
+ const char *name);
+
#endif
@@ -144,7 +144,7 @@ void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks)
}
}
-static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name)
+NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name)
{
NamedClockList *ncl;
@@ -19,6 +19,7 @@
#include "exec/ioport.h"
#include "exec/memory.h"
#include "exec/tswap.h"
+#include "hw/qdev-clock.h"
#include "hw/qdev-core.h"
#include "hw/irq.h"
#include "hw/core/cpu.h"
@@ -245,6 +246,20 @@ static void *qtest_server_send_opaque;
*
* Forcibly set the given interrupt pin to the given level.
*
+ * Device clock frequency
+ * """"""""""""""""""""""
+ *
+ * .. code-block:: none
+ *
+ * > qdev_clock_out_get_hz QOM-PATH CLOCK-NAME
+ * < OK HZ
+ *
+ * .. code-block:: none
+ *
+ * > qdev_clock_in_get_hz QOM-PATH CLOCK-NAME
+ * < OK HZ
+ *
+ * where HZ is the clock frequency in hertz.
*/
static int hex2nib(char ch)
@@ -758,6 +773,42 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
qtest_send_prefix(chr);
qtest_sendf(chr, "OK %"PRIi64"\n",
(int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ } else if (strcmp(words[0], "qdev_clock_in_get_hz") == 0 ||
+ strcmp(words[0], "qdev_clock_out_get_hz") == 0) {
+ bool is_outbound = words[0][11] == 'o';
+ DeviceState *dev;
+ NamedClockList *ncl;
+
+ g_assert(words[1]);
+ g_assert(words[2]);
+
+ dev = DEVICE(object_resolve_path(words[1], NULL));
+ if (!dev) {
+ qtest_send_prefix(chr);
+ qtest_send(chr, "FAIL Unknown device\n");
+ return;
+ }
+
+ ncl = qdev_get_clocklist(dev, words[2]);
+ if (!ncl) {
+ qtest_send_prefix(chr);
+ qtest_send(chr, "FAIL Unknown clock\n");
+ return;
+ }
+
+ if (is_outbound && !ncl->output) {
+ qtest_send_prefix(chr);
+ qtest_send(chr, "FAIL Not an output clock\n");
+ return;
+ }
+
+ if (!is_outbound && ncl->output) {
+ qtest_send_prefix(chr);
+ qtest_send(chr, "FAIL Not an input clock\n");
+ return;
+ }
+
+ qtest_sendf(chr, "OK %u\n", clock_get_hz(ncl->clock));
} else if (process_command_cb && process_command_cb(chr, words)) {
/* Command got consumed by the callback handler */
} else {
@@ -2065,3 +2065,32 @@ bool mkimg(const char *file, const char *fmt, unsigned size_mb)
return ret && !err;
}
+
+static uint64_t qtest_dev_clock_get_hz(QTestState *s, const char *path,
+ const char *name, bool out)
+{
+ gchar **args;
+ int ret;
+ uint64_t value;
+
+ qtest_sendf(s, "qdev_clock_%s_get_hz %s %s\n", out ? "out" : "in",
+ path, name);
+ args = qtest_rsp_args(s, 2);
+ ret = qemu_strtou64(args[1], NULL, 0, &value);
+ g_assert(!ret);
+ g_strfreev(args);
+
+ return value;
+}
+
+uint64_t qtest_dev_clock_out_get_hz(QTestState *s, const char *path,
+ const char *name)
+{
+ return qtest_dev_clock_get_hz(s, path, name, true);
+}
+
+uint64_t qtest_dev_clock_in_get_hz(QTestState *s, const char *path,
+ const char *name)
+{
+ return qtest_dev_clock_get_hz(s, path, name, false);
+}
Add qtest APIs to check the device clock frequency. Signed-off-by: Octavian Purdila <tavip@google.com> --- include/hw/qdev-clock.h | 10 +++++++ tests/qtest/libqtest-single.h | 24 +++++++++++++++++ tests/qtest/libqtest.h | 22 +++++++++++++++ hw/core/qdev-clock.c | 2 +- system/qtest.c | 51 +++++++++++++++++++++++++++++++++++ tests/qtest/libqtest.c | 29 ++++++++++++++++++++ 6 files changed, 137 insertions(+), 1 deletion(-)