FRET-qemu/tests/qtest/npcm7xx_watchdog_timer-test.c
Romain Malmain 7c3c7877d8 Update to QEMU 9.0.0 (#67)
* Update to QEMU v9.0.0

---------

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Zheyu Ma <zheyuma97@gmail.com>
Signed-off-by: Ido Plat <ido.plat@ibm.com>
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Signed-off-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Signed-off-by: Gregory Price <gregory.price@memverge.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Lorenz Brun <lorenz@brun.one>
Signed-off-by: Yao Xingtao <yaoxt.fnst@fujitsu.com>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Joonas Kankaala <joonas.a.kankaala@gmail.com>
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
Signed-off-by: Oleg Sviridov <oleg.sviridov@red-soft.ru>
Signed-off-by: Artem Chernyshev <artem.chernyshev@red-soft.ru>
Signed-off-by: Yajun Wu <yajunw@nvidia.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Signed-off-by: Lei Wang <lei4.wang@intel.com>
Signed-off-by: Wei Wang <wei.w.wang@intel.com>
Signed-off-by: Martin Hundebøll <martin@geanix.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Signed-off-by: Wafer <wafer@jaguarmicro.com>
Signed-off-by: Yuxue Liu <yuxue.liu@jaguarmicro.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
Signed-off-by: Zack Buhman <zack@buhman.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Yuquan Wang wangyuquan1236@phytium.com.cn
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Cindy Lu <lulu@redhat.com>
Co-authored-by: Peter Maydell <peter.maydell@linaro.org>
Co-authored-by: Fabiano Rosas <farosas@suse.de>
Co-authored-by: Peter Xu <peterx@redhat.com>
Co-authored-by: Thomas Huth <thuth@redhat.com>
Co-authored-by: Cédric Le Goater <clg@redhat.com>
Co-authored-by: Zheyu Ma <zheyuma97@gmail.com>
Co-authored-by: Ido Plat <ido.plat@ibm.com>
Co-authored-by: Ilya Leoshkevich <iii@linux.ibm.com>
Co-authored-by: Markus Armbruster <armbru@redhat.com>
Co-authored-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
Co-authored-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Co-authored-by: David Hildenbrand <david@redhat.com>
Co-authored-by: Kevin Wolf <kwolf@redhat.com>
Co-authored-by: Stefan Reiter <s.reiter@proxmox.com>
Co-authored-by: Fiona Ebner <f.ebner@proxmox.com>
Co-authored-by: Gregory Price <gregory.price@memverge.com>
Co-authored-by: Lorenz Brun <lorenz@brun.one>
Co-authored-by: Yao Xingtao <yaoxt.fnst@fujitsu.com>
Co-authored-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Co-authored-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Co-authored-by: BALATON Zoltan <balaton@eik.bme.hu>
Co-authored-by: Igor Mammedov <imammedo@redhat.com>
Co-authored-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Co-authored-by: Richard Henderson <richard.henderson@linaro.org>
Co-authored-by: Sven Schnelle <svens@stackframe.org>
Co-authored-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Co-authored-by: Helge Deller <deller@kernel.org>
Co-authored-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Co-authored-by: Benjamin Gray <bgray@linux.ibm.com>
Co-authored-by: Nicholas Piggin <npiggin@gmail.com>
Co-authored-by: Avihai Horon <avihaih@nvidia.com>
Co-authored-by: Michael Tokarev <mjt@tls.msk.ru>
Co-authored-by: Joonas Kankaala <joonas.a.kankaala@gmail.com>
Co-authored-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
Co-authored-by: Stefan Weil <sw@weilnetz.de>
Co-authored-by: Dayu Liu <liu.dayu@zte.com.cn>
Co-authored-by: Zhao Liu <zhao1.liu@intel.com>
Co-authored-by: Glenn Miles <milesg@linux.vnet.ibm.com>
Co-authored-by: Artem Chernyshev <artem.chernyshev@red-soft.ru>
Co-authored-by: Yajun Wu <yajunw@nvidia.com>
Co-authored-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Co-authored-by: Pierre-Clément Tosi <ptosi@google.com>
Co-authored-by: Wei Wang <wei.w.wang@intel.com>
Co-authored-by: Martin Hundebøll <martin@geanix.com>
Co-authored-by: Michael S. Tsirkin <mst@redhat.com>
Co-authored-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Co-authored-by: Wafer <wafer@jaguarmicro.com>
Co-authored-by: lyx634449800 <yuxue.liu@jaguarmicro.com>
Co-authored-by: Gerd Hoffmann <kraxel@redhat.com>
Co-authored-by: Nguyen Dinh Phi <phind.uet@gmail.com>
Co-authored-by: Zack Buhman <zack@buhman.org>
Co-authored-by: Keith Packard <keithp@keithp.com>
Co-authored-by: Yuquan Wang <wangyuquan1236@phytium.com.cn>
Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Co-authored-by: Cindy Lu <lulu@redhat.com>
2024-05-01 16:10:20 +02:00

323 lines
10 KiB
C

/*
* QTests for Nuvoton NPCM7xx Timer Watchdog Modules.
*
* Copyright 2020 Google LLC
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "qemu/osdep.h"
#include "qemu/timer.h"
#include "libqtest.h"
#include "qapi/qmp/qdict.h"
#define WTCR_OFFSET 0x1c
#define REF_HZ (25000000)
/* WTCR bit fields */
#define WTCLK(rv) ((rv) << 10)
#define WTE BIT(7)
#define WTIE BIT(6)
#define WTIS(rv) ((rv) << 4)
#define WTIF BIT(3)
#define WTRF BIT(2)
#define WTRE BIT(1)
#define WTR BIT(0)
typedef struct Watchdog {
int irq;
uint64_t base_addr;
} Watchdog;
static const Watchdog watchdog_list[] = {
{
.irq = 47,
.base_addr = 0xf0008000
},
{
.irq = 48,
.base_addr = 0xf0009000
},
{
.irq = 49,
.base_addr = 0xf000a000
}
};
static int watchdog_index(const Watchdog *wd)
{
ptrdiff_t diff = wd - watchdog_list;
g_assert(diff >= 0 && diff < ARRAY_SIZE(watchdog_list));
return diff;
}
static uint32_t watchdog_read_wtcr(QTestState *qts, const Watchdog *wd)
{
return qtest_readl(qts, wd->base_addr + WTCR_OFFSET);
}
static void watchdog_write_wtcr(QTestState *qts, const Watchdog *wd,
uint32_t value)
{
qtest_writel(qts, wd->base_addr + WTCR_OFFSET, value);
}
static uint32_t watchdog_prescaler(QTestState *qts, const Watchdog *wd)
{
switch (extract32(watchdog_read_wtcr(qts, wd), 10, 2)) {
case 0:
return 1;
case 1:
return 256;
case 2:
return 2048;
case 3:
return 65536;
default:
g_assert_not_reached();
}
}
static QDict *get_watchdog_action(QTestState *qts)
{
QDict *ev = qtest_qmp_eventwait_ref(qts, "WATCHDOG");
QDict *data;
data = qdict_get_qdict(ev, "data");
qobject_ref(data);
qobject_unref(ev);
return data;
}
#define RESET_CYCLES 1024
static uint32_t watchdog_interrupt_cycles(QTestState *qts, const Watchdog *wd)
{
uint32_t wtis = extract32(watchdog_read_wtcr(qts, wd), 4, 2);
return 1 << (14 + 2 * wtis);
}
static int64_t watchdog_calculate_steps(uint32_t count, uint32_t prescale)
{
return (NANOSECONDS_PER_SECOND / REF_HZ) * count * prescale;
}
static int64_t watchdog_interrupt_steps(QTestState *qts, const Watchdog *wd)
{
return watchdog_calculate_steps(watchdog_interrupt_cycles(qts, wd),
watchdog_prescaler(qts, wd));
}
/* Check wtcr can be reset to default value */
static void test_init(gconstpointer watchdog)
{
const Watchdog *wd = watchdog;
QTestState *qts = qtest_init("-machine quanta-gsj");
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd, WTCLK(1) | WTRF | WTIF | WTR);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1));
qtest_quit(qts);
}
/* Check a watchdog can generate interrupt and reset actions */
static void test_reset_action(gconstpointer watchdog)
{
const Watchdog *wd = watchdog;
QTestState *qts = qtest_init("-machine quanta-gsj");
QDict *ad;
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd,
WTCLK(0) | WTE | WTRF | WTRE | WTIF | WTIE | WTR);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
WTCLK(0) | WTE | WTRE | WTIE);
/* Check a watchdog can generate an interrupt */
qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
WTCLK(0) | WTE | WTIF | WTIE | WTRE);
g_assert_true(qtest_get_irq(qts, wd->irq));
/* Check a watchdog can generate a reset signal */
qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
watchdog_prescaler(qts, wd)));
ad = get_watchdog_action(qts);
/* The signal is a reset signal */
g_assert_false(strcmp(qdict_get_str(ad, "action"), "reset"));
qobject_unref(ad);
qtest_qmp_eventwait(qts, "RESET");
/*
* Make sure WTCR is reset to default except for WTRF bit which shouldn't
* be reset.
*/
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1) | WTRF);
qtest_quit(qts);
}
/* Check a watchdog works with all possible WTCLK prescalers and WTIS cycles */
static void test_prescaler(gconstpointer watchdog)
{
const Watchdog *wd = watchdog;
int inc = g_test_quick() ? 3 : 1;
for (int wtclk = 0; wtclk < 4; wtclk += inc) {
for (int wtis = 0; wtis < 4; wtis += inc) {
QTestState *qts = qtest_init("-machine quanta-gsj");
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd,
WTCLK(wtclk) | WTE | WTIF | WTIS(wtis) | WTIE | WTR);
/*
* The interrupt doesn't fire until watchdog_interrupt_steps()
* cycles passed
*/
qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd) - 1);
g_assert_false(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_false(qtest_get_irq(qts, wd->irq));
qtest_clock_step(qts, 1);
g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_true(qtest_get_irq(qts, wd->irq));
qtest_quit(qts);
}
}
}
/*
* Check a watchdog doesn't fire if corresponding flags (WTIE and WTRE) are not
* set.
*/
static void test_enabling_flags(gconstpointer watchdog)
{
const Watchdog *wd = watchdog;
QTestState *qts;
QDict *rsp;
/* Neither WTIE or WTRE is set, no interrupt or reset should happen */
qts = qtest_init("-machine quanta-gsj");
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRF | WTR);
qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_false(qtest_get_irq(qts, wd->irq));
qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
watchdog_prescaler(qts, wd)));
g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF);
qtest_quit(qts);
/* Only WTIE is set, interrupt is triggered but reset should not happen */
qts = qtest_init("-machine quanta-gsj");
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR);
qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_true(qtest_get_irq(qts, wd->irq));
qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
watchdog_prescaler(qts, wd)));
g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF);
qtest_quit(qts);
/* Only WTRE is set, interrupt is triggered but reset should not happen */
qts = qtest_init("-machine quanta-gsj");
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRE | WTRF | WTR);
qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
g_assert_false(qtest_get_irq(qts, wd->irq));
qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
watchdog_prescaler(qts, wd)));
rsp = get_watchdog_action(qts);
g_assert_false(strcmp(qdict_get_str(rsp, "action"), "reset"));
qobject_unref(rsp);
qtest_qmp_eventwait(qts, "RESET");
qtest_quit(qts);
/*
* The case when both flags are set is already tested in
* test_reset_action().
*/
}
/* Check a watchdog can pause and resume by setting WTE bits */
static void test_pause(gconstpointer watchdog)
{
const Watchdog *wd = watchdog;
QTestState *qts;
int64_t remaining_steps, steps;
qts = qtest_init("-machine quanta-gsj");
qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR);
remaining_steps = watchdog_interrupt_steps(qts, wd);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE);
/* Run for half of the execution period. */
steps = remaining_steps / 2;
remaining_steps -= steps;
qtest_clock_step(qts, steps);
/* Pause the watchdog */
watchdog_write_wtcr(qts, wd, WTCLK(0) | WTIE);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE);
/* Run for a long period of time, the watchdog shouldn't fire */
qtest_clock_step(qts, steps << 4);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE);
g_assert_false(qtest_get_irq(qts, wd->irq));
/* Resume the watchdog */
watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIE);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE);
/* Run for the reset of the execution period, the watchdog should fire */
qtest_clock_step(qts, remaining_steps);
g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
WTCLK(0) | WTE | WTIF | WTIE);
g_assert_true(qtest_get_irq(qts, wd->irq));
qtest_quit(qts);
}
static void watchdog_add_test(const char *name, const Watchdog* wd,
GTestDataFunc fn)
{
g_autofree char *full_name = g_strdup_printf(
"npcm7xx_watchdog_timer[%d]/%s", watchdog_index(wd), name);
qtest_add_data_func(full_name, wd, fn);
}
#define add_test(name, td) watchdog_add_test(#name, td, test_##name)
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
g_test_set_nonfatal_assertions();
for (int i = 0; i < ARRAY_SIZE(watchdog_list); ++i) {
const Watchdog *wd = &watchdog_list[i];
add_test(init, wd);
add_test(reset_action, wd);
add_test(prescaler, wd);
add_test(enabling_flags, wd);
add_test(pause, wd);
}
return g_test_run();
}