Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 1 | /* |
| 2 | * QEMU ICH9 TCO emulation tests |
| 3 | * |
| 4 | * Copyright (c) 2015 Paulo Alcantara <pcacjr@zytor.com> |
| 5 | * |
| 6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| 7 | * See the COPYING file in the top-level directory. |
| 8 | */ |
Markus Armbruster | 452fcdb | 2018-02-01 12:18:39 +0100 | [diff] [blame] | 9 | |
Peter Maydell | 681c28a | 2016-02-08 18:08:51 +0000 | [diff] [blame] | 10 | #include "qemu/osdep.h" |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 11 | |
| 12 | #include "libqtest.h" |
| 13 | #include "libqos/pci.h" |
| 14 | #include "libqos/pci-pc.h" |
Markus Armbruster | 452fcdb | 2018-02-01 12:18:39 +0100 | [diff] [blame] | 15 | #include "qapi/qmp/qdict.h" |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 16 | #include "hw/pci/pci_regs.h" |
| 17 | #include "hw/i386/ich9.h" |
| 18 | #include "hw/acpi/ich9.h" |
| 19 | #include "hw/acpi/tco.h" |
| 20 | |
| 21 | #define RCBA_BASE_ADDR 0xfed1c000 |
| 22 | #define PM_IO_BASE_ADDR 0xb000 |
| 23 | |
| 24 | enum { |
| 25 | TCO_RLD_DEFAULT = 0x0000, |
| 26 | TCO_DAT_IN_DEFAULT = 0x00, |
| 27 | TCO_DAT_OUT_DEFAULT = 0x00, |
| 28 | TCO1_STS_DEFAULT = 0x0000, |
| 29 | TCO2_STS_DEFAULT = 0x0000, |
| 30 | TCO1_CNT_DEFAULT = 0x0000, |
| 31 | TCO2_CNT_DEFAULT = 0x0008, |
| 32 | TCO_MESSAGE1_DEFAULT = 0x00, |
| 33 | TCO_MESSAGE2_DEFAULT = 0x00, |
| 34 | TCO_WDCNT_DEFAULT = 0x00, |
| 35 | TCO_TMR_DEFAULT = 0x0004, |
| 36 | SW_IRQ_GEN_DEFAULT = 0x03, |
| 37 | }; |
| 38 | |
| 39 | #define TCO_SECS_TO_TICKS(secs) (((secs) * 10) / 6) |
| 40 | #define TCO_TICKS_TO_SECS(ticks) (((ticks) * 6) / 10) |
| 41 | |
| 42 | typedef struct { |
| 43 | const char *args; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 44 | bool noreboot; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 45 | QPCIDevice *dev; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 46 | QPCIBar tco_io_bar; |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 47 | QPCIBus *bus; |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 48 | QTestState *qts; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 49 | } TestData; |
| 50 | |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 51 | static void test_end(TestData *d) |
| 52 | { |
| 53 | g_free(d->dev); |
| 54 | qpci_free_pc(d->bus); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 55 | qtest_quit(d->qts); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 56 | } |
| 57 | |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 58 | static void test_init(TestData *d) |
| 59 | { |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 60 | QTestState *qs; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 61 | |
Markus Armbruster | 88b988c | 2018-08-06 08:53:43 +0200 | [diff] [blame] | 62 | qs = qtest_initf("-machine q35 %s %s", |
| 63 | d->noreboot ? "" : "-global ICH9-LPC.noreboot=false", |
| 64 | !d->args ? "" : d->args); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 65 | qtest_irq_intercept_in(qs, "ioapic"); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 66 | |
Emanuele Giuseppe Esposito | 143e6db | 2018-07-19 13:50:27 +0200 | [diff] [blame] | 67 | d->bus = qpci_new_pc(qs, NULL); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 68 | d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00)); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 69 | g_assert(d->dev != NULL); |
| 70 | |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 71 | qpci_device_enable(d->dev); |
| 72 | |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 73 | /* set ACPI PM I/O space base address */ |
Michael S. Tsirkin | c4fc82b | 2015-07-08 10:06:15 +0300 | [diff] [blame] | 74 | qpci_config_writel(d->dev, ICH9_LPC_PMBASE, PM_IO_BASE_ADDR | 0x1); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 75 | /* enable ACPI I/O */ |
Michael S. Tsirkin | c4fc82b | 2015-07-08 10:06:15 +0300 | [diff] [blame] | 76 | qpci_config_writeb(d->dev, ICH9_LPC_ACPI_CTRL, 0x80); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 77 | /* set Root Complex BAR */ |
Michael S. Tsirkin | c4fc82b | 2015-07-08 10:06:15 +0300 | [diff] [blame] | 78 | qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 79 | |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 80 | d->tco_io_bar = qpci_legacy_iomap(d->dev, PM_IO_BASE_ADDR + 0x60); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 81 | d->qts = qs; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | static void stop_tco(const TestData *d) |
| 85 | { |
| 86 | uint32_t val; |
| 87 | |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 88 | val = qpci_io_readw(d->dev, d->tco_io_bar, TCO1_CNT); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 89 | val |= TCO_TMR_HLT; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 90 | qpci_io_writew(d->dev, d->tco_io_bar, TCO1_CNT, val); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 91 | } |
| 92 | |
| 93 | static void start_tco(const TestData *d) |
| 94 | { |
| 95 | uint32_t val; |
| 96 | |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 97 | val = qpci_io_readw(d->dev, d->tco_io_bar, TCO1_CNT); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 98 | val &= ~TCO_TMR_HLT; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 99 | qpci_io_writew(d->dev, d->tco_io_bar, TCO1_CNT, val); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | static void load_tco(const TestData *d) |
| 103 | { |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 104 | qpci_io_writew(d->dev, d->tco_io_bar, TCO_RLD, 4); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | static void set_tco_timeout(const TestData *d, uint16_t ticks) |
| 108 | { |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 109 | qpci_io_writew(d->dev, d->tco_io_bar, TCO_TMR, ticks); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | static void clear_tco_status(const TestData *d) |
| 113 | { |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 114 | qpci_io_writew(d->dev, d->tco_io_bar, TCO1_STS, 0x0008); |
| 115 | qpci_io_writew(d->dev, d->tco_io_bar, TCO2_STS, 0x0002); |
| 116 | qpci_io_writew(d->dev, d->tco_io_bar, TCO2_STS, 0x0004); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 117 | } |
| 118 | |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 119 | static void reset_on_second_timeout(const TestData *td, bool enable) |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 120 | { |
| 121 | uint32_t val; |
| 122 | |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 123 | val = qtest_readl(td->qts, RCBA_BASE_ADDR + ICH9_CC_GCS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 124 | if (enable) { |
| 125 | val &= ~ICH9_CC_GCS_NO_REBOOT; |
| 126 | } else { |
| 127 | val |= ICH9_CC_GCS_NO_REBOOT; |
| 128 | } |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 129 | qtest_writel(td->qts, RCBA_BASE_ADDR + ICH9_CC_GCS, val); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | static void test_tco_defaults(void) |
| 133 | { |
| 134 | TestData d; |
| 135 | |
| 136 | d.args = NULL; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 137 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 138 | test_init(&d); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 139 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_RLD), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 140 | TCO_RLD_DEFAULT); |
| 141 | /* TCO_DAT_IN & TCO_DAT_OUT */ |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 142 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_DAT_IN), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 143 | (TCO_DAT_OUT_DEFAULT << 8) | TCO_DAT_IN_DEFAULT); |
| 144 | /* TCO1_STS & TCO2_STS */ |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 145 | g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_bar, TCO1_STS), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 146 | (TCO2_STS_DEFAULT << 16) | TCO1_STS_DEFAULT); |
| 147 | /* TCO1_CNT & TCO2_CNT */ |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 148 | g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_bar, TCO1_CNT), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 149 | (TCO2_CNT_DEFAULT << 16) | TCO1_CNT_DEFAULT); |
| 150 | /* TCO_MESSAGE1 & TCO_MESSAGE2 */ |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 151 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_MESSAGE1), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 152 | (TCO_MESSAGE2_DEFAULT << 8) | TCO_MESSAGE1_DEFAULT); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 153 | g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_bar, TCO_WDCNT), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 154 | TCO_WDCNT_DEFAULT); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 155 | g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_bar, SW_IRQ_GEN), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 156 | SW_IRQ_GEN_DEFAULT); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 157 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_TMR), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 158 | TCO_TMR_DEFAULT); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 159 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | static void test_tco_timeout(void) |
| 163 | { |
| 164 | TestData d; |
| 165 | const uint16_t ticks = TCO_SECS_TO_TICKS(4); |
| 166 | uint32_t val; |
| 167 | int ret; |
| 168 | |
| 169 | d.args = NULL; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 170 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 171 | test_init(&d); |
| 172 | |
| 173 | stop_tco(&d); |
| 174 | clear_tco_status(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 175 | reset_on_second_timeout(&d, false); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 176 | set_tco_timeout(&d, ticks); |
| 177 | load_tco(&d); |
| 178 | start_tco(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 179 | qtest_clock_step(d.qts, ticks * TCO_TICK_NSEC); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 180 | |
| 181 | /* test first timeout */ |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 182 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 183 | ret = val & TCO_TIMEOUT ? 1 : 0; |
| 184 | g_assert(ret == 1); |
| 185 | |
| 186 | /* test clearing timeout bit */ |
| 187 | val |= TCO_TIMEOUT; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 188 | qpci_io_writew(d.dev, d.tco_io_bar, TCO1_STS, val); |
| 189 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 190 | ret = val & TCO_TIMEOUT ? 1 : 0; |
| 191 | g_assert(ret == 0); |
| 192 | |
| 193 | /* test second timeout */ |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 194 | qtest_clock_step(d.qts, ticks * TCO_TICK_NSEC); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 195 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 196 | ret = val & TCO_TIMEOUT ? 1 : 0; |
| 197 | g_assert(ret == 1); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 198 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO2_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 199 | ret = val & TCO_SECOND_TO_STS ? 1 : 0; |
| 200 | g_assert(ret == 1); |
| 201 | |
| 202 | stop_tco(&d); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 203 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 204 | } |
| 205 | |
| 206 | static void test_tco_max_timeout(void) |
| 207 | { |
| 208 | TestData d; |
| 209 | const uint16_t ticks = 0xffff; |
| 210 | uint32_t val; |
| 211 | int ret; |
| 212 | |
| 213 | d.args = NULL; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 214 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 215 | test_init(&d); |
| 216 | |
| 217 | stop_tco(&d); |
| 218 | clear_tco_status(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 219 | reset_on_second_timeout(&d, false); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 220 | set_tco_timeout(&d, ticks); |
| 221 | load_tco(&d); |
| 222 | start_tco(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 223 | qtest_clock_step(d.qts, ((ticks & TCO_TMR_MASK) - 1) * TCO_TICK_NSEC); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 224 | |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 225 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO_RLD); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 226 | g_assert_cmpint(val & TCO_RLD_MASK, ==, 1); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 227 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 228 | ret = val & TCO_TIMEOUT ? 1 : 0; |
| 229 | g_assert(ret == 0); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 230 | qtest_clock_step(d.qts, TCO_TICK_NSEC); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 231 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 232 | ret = val & TCO_TIMEOUT ? 1 : 0; |
| 233 | g_assert(ret == 1); |
| 234 | |
| 235 | stop_tco(&d); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 236 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 237 | } |
| 238 | |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 239 | static QDict *get_watchdog_action(const TestData *td) |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 240 | { |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 241 | QDict *ev = qtest_qmp_eventwait_ref(td->qts, "WATCHDOG"); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 242 | QDict *data; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 243 | |
| 244 | data = qdict_get_qdict(ev, "data"); |
Marc-André Lureau | cb3e7f0 | 2018-04-19 17:01:43 +0200 | [diff] [blame] | 245 | qobject_ref(data); |
| 246 | qobject_unref(ev); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 247 | return data; |
| 248 | } |
| 249 | |
| 250 | static void test_tco_second_timeout_pause(void) |
| 251 | { |
| 252 | TestData td; |
| 253 | const uint16_t ticks = TCO_SECS_TO_TICKS(32); |
| 254 | QDict *ad; |
| 255 | |
| 256 | td.args = "-watchdog-action pause"; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 257 | td.noreboot = false; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 258 | test_init(&td); |
| 259 | |
| 260 | stop_tco(&td); |
| 261 | clear_tco_status(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 262 | reset_on_second_timeout(&td, true); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 263 | set_tco_timeout(&td, TCO_SECS_TO_TICKS(16)); |
| 264 | load_tco(&td); |
| 265 | start_tco(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 266 | qtest_clock_step(td.qts, ticks * TCO_TICK_NSEC * 2); |
| 267 | ad = get_watchdog_action(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 268 | g_assert(!strcmp(qdict_get_str(ad, "action"), "pause")); |
Marc-André Lureau | cb3e7f0 | 2018-04-19 17:01:43 +0200 | [diff] [blame] | 269 | qobject_unref(ad); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 270 | |
| 271 | stop_tco(&td); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 272 | test_end(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | static void test_tco_second_timeout_reset(void) |
| 276 | { |
| 277 | TestData td; |
| 278 | const uint16_t ticks = TCO_SECS_TO_TICKS(16); |
| 279 | QDict *ad; |
| 280 | |
| 281 | td.args = "-watchdog-action reset"; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 282 | td.noreboot = false; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 283 | test_init(&td); |
| 284 | |
| 285 | stop_tco(&td); |
| 286 | clear_tco_status(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 287 | reset_on_second_timeout(&td, true); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 288 | set_tco_timeout(&td, TCO_SECS_TO_TICKS(16)); |
| 289 | load_tco(&td); |
| 290 | start_tco(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 291 | qtest_clock_step(td.qts, ticks * TCO_TICK_NSEC * 2); |
| 292 | ad = get_watchdog_action(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 293 | g_assert(!strcmp(qdict_get_str(ad, "action"), "reset")); |
Marc-André Lureau | cb3e7f0 | 2018-04-19 17:01:43 +0200 | [diff] [blame] | 294 | qobject_unref(ad); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 295 | |
| 296 | stop_tco(&td); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 297 | test_end(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 298 | } |
| 299 | |
| 300 | static void test_tco_second_timeout_shutdown(void) |
| 301 | { |
| 302 | TestData td; |
| 303 | const uint16_t ticks = TCO_SECS_TO_TICKS(128); |
| 304 | QDict *ad; |
| 305 | |
| 306 | td.args = "-watchdog-action shutdown"; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 307 | td.noreboot = false; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 308 | test_init(&td); |
| 309 | |
| 310 | stop_tco(&td); |
| 311 | clear_tco_status(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 312 | reset_on_second_timeout(&td, true); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 313 | set_tco_timeout(&td, ticks); |
| 314 | load_tco(&td); |
| 315 | start_tco(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 316 | qtest_clock_step(td.qts, ticks * TCO_TICK_NSEC * 2); |
| 317 | ad = get_watchdog_action(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 318 | g_assert(!strcmp(qdict_get_str(ad, "action"), "shutdown")); |
Marc-André Lureau | cb3e7f0 | 2018-04-19 17:01:43 +0200 | [diff] [blame] | 319 | qobject_unref(ad); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 320 | |
| 321 | stop_tco(&td); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 322 | test_end(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | static void test_tco_second_timeout_none(void) |
| 326 | { |
| 327 | TestData td; |
| 328 | const uint16_t ticks = TCO_SECS_TO_TICKS(256); |
| 329 | QDict *ad; |
| 330 | |
| 331 | td.args = "-watchdog-action none"; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 332 | td.noreboot = false; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 333 | test_init(&td); |
| 334 | |
| 335 | stop_tco(&td); |
| 336 | clear_tco_status(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 337 | reset_on_second_timeout(&td, true); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 338 | set_tco_timeout(&td, ticks); |
| 339 | load_tco(&td); |
| 340 | start_tco(&td); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 341 | qtest_clock_step(td.qts, ticks * TCO_TICK_NSEC * 2); |
| 342 | ad = get_watchdog_action(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 343 | g_assert(!strcmp(qdict_get_str(ad, "action"), "none")); |
Marc-André Lureau | cb3e7f0 | 2018-04-19 17:01:43 +0200 | [diff] [blame] | 344 | qobject_unref(ad); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 345 | |
| 346 | stop_tco(&td); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 347 | test_end(&td); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 348 | } |
| 349 | |
| 350 | static void test_tco_ticks_counter(void) |
| 351 | { |
| 352 | TestData d; |
| 353 | uint16_t ticks = TCO_SECS_TO_TICKS(8); |
| 354 | uint16_t rld; |
| 355 | |
| 356 | d.args = NULL; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 357 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 358 | test_init(&d); |
| 359 | |
| 360 | stop_tco(&d); |
| 361 | clear_tco_status(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 362 | reset_on_second_timeout(&d, false); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 363 | set_tco_timeout(&d, ticks); |
| 364 | load_tco(&d); |
| 365 | start_tco(&d); |
| 366 | |
| 367 | do { |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 368 | rld = qpci_io_readw(d.dev, d.tco_io_bar, TCO_RLD) & TCO_RLD_MASK; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 369 | g_assert_cmpint(rld, ==, ticks); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 370 | qtest_clock_step(d.qts, TCO_TICK_NSEC); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 371 | ticks--; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 372 | } while (!(qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS) & TCO_TIMEOUT)); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 373 | |
| 374 | stop_tco(&d); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 375 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 376 | } |
| 377 | |
| 378 | static void test_tco1_control_bits(void) |
| 379 | { |
| 380 | TestData d; |
| 381 | uint16_t val; |
| 382 | |
| 383 | d.args = NULL; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 384 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 385 | test_init(&d); |
| 386 | |
| 387 | val = TCO_LOCK; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 388 | qpci_io_writew(d.dev, d.tco_io_bar, TCO1_CNT, val); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 389 | val &= ~TCO_LOCK; |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 390 | qpci_io_writew(d.dev, d.tco_io_bar, TCO1_CNT, val); |
| 391 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO1_CNT), ==, |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 392 | TCO_LOCK); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 393 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 394 | } |
| 395 | |
| 396 | static void test_tco1_status_bits(void) |
| 397 | { |
| 398 | TestData d; |
| 399 | uint16_t ticks = 8; |
| 400 | uint16_t val; |
| 401 | int ret; |
| 402 | |
| 403 | d.args = NULL; |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 404 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 405 | test_init(&d); |
| 406 | |
| 407 | stop_tco(&d); |
| 408 | clear_tco_status(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 409 | reset_on_second_timeout(&d, false); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 410 | set_tco_timeout(&d, ticks); |
| 411 | load_tco(&d); |
| 412 | start_tco(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 413 | qtest_clock_step(d.qts, ticks * TCO_TICK_NSEC); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 414 | |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 415 | qpci_io_writeb(d.dev, d.tco_io_bar, TCO_DAT_IN, 0); |
| 416 | qpci_io_writeb(d.dev, d.tco_io_bar, TCO_DAT_OUT, 0); |
| 417 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 418 | ret = val & (TCO_TIMEOUT | SW_TCO_SMI | TCO_INT_STS) ? 1 : 0; |
| 419 | g_assert(ret == 1); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 420 | qpci_io_writew(d.dev, d.tco_io_bar, TCO1_STS, val); |
| 421 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS), ==, 0); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 422 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 423 | } |
| 424 | |
| 425 | static void test_tco2_status_bits(void) |
| 426 | { |
| 427 | TestData d; |
| 428 | uint16_t ticks = 8; |
| 429 | uint16_t val; |
| 430 | int ret; |
| 431 | |
Paulo Alcantara | 5add35b | 2015-06-28 14:58:58 -0300 | [diff] [blame] | 432 | d.args = NULL; |
| 433 | d.noreboot = true; |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 434 | test_init(&d); |
| 435 | |
| 436 | stop_tco(&d); |
| 437 | clear_tco_status(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 438 | reset_on_second_timeout(&d, true); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 439 | set_tco_timeout(&d, ticks); |
| 440 | load_tco(&d); |
| 441 | start_tco(&d); |
Thomas Huth | 6bb58d2 | 2019-04-09 10:52:41 +0200 | [diff] [blame] | 442 | qtest_clock_step(d.qts, ticks * TCO_TICK_NSEC * 2); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 443 | |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 444 | val = qpci_io_readw(d.dev, d.tco_io_bar, TCO2_STS); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 445 | ret = val & (TCO_SECOND_TO_STS | TCO_BOOT_STS) ? 1 : 0; |
| 446 | g_assert(ret == 1); |
David Gibson | b4ba67d | 2016-10-24 15:52:06 +1100 | [diff] [blame] | 447 | qpci_io_writew(d.dev, d.tco_io_bar, TCO2_STS, val); |
| 448 | g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO2_STS), ==, 0); |
Marc-André Lureau | 34779e8 | 2017-02-05 20:47:24 +0000 | [diff] [blame] | 449 | test_end(&d); |
Paulo Alcantara | 45dcdb9 | 2015-06-28 14:58:57 -0300 | [diff] [blame] | 450 | } |
| 451 | |
| 452 | int main(int argc, char **argv) |
| 453 | { |
| 454 | g_test_init(&argc, &argv, NULL); |
| 455 | |
| 456 | qtest_add_func("tco/defaults", test_tco_defaults); |
| 457 | qtest_add_func("tco/timeout/no_action", test_tco_timeout); |
| 458 | qtest_add_func("tco/timeout/no_action/max", test_tco_max_timeout); |
| 459 | qtest_add_func("tco/second_timeout/pause", test_tco_second_timeout_pause); |
| 460 | qtest_add_func("tco/second_timeout/reset", test_tco_second_timeout_reset); |
| 461 | qtest_add_func("tco/second_timeout/shutdown", |
| 462 | test_tco_second_timeout_shutdown); |
| 463 | qtest_add_func("tco/second_timeout/none", test_tco_second_timeout_none); |
| 464 | qtest_add_func("tco/counter", test_tco_ticks_counter); |
| 465 | qtest_add_func("tco/tco1_control/bits", test_tco1_control_bits); |
| 466 | qtest_add_func("tco/tco1_status/bits", test_tco1_status_bits); |
| 467 | qtest_add_func("tco/tco2_status/bits", test_tco2_status_bits); |
| 468 | return g_test_run(); |
| 469 | } |