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