2015-01-20 13:36 GMT+00:00 Paolo Bonzini <pbonz...@redhat.com>: > > > On 08/01/2015 19:38, Frediano Ziglio wrote: >> Test behaviour of timers and interrupts related to timeouts. >> >> Signed-off-by: Frediano Ziglio <fredd...@gmail.com> >> --- >> tests/Makefile | 2 +- >> tests/rtl8139-test.c | 181 >> +++++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 182 insertions(+), 1 deletion(-) >> >> This patch was derived from a test I did while implementing timer in >> rtl8139 code. Now that there is support for integrated testing I converted >> it. The test was tested on a real NIC. >> >> As if it's the first test I wrote I don't know if syntax and details are >> fine. For instance should I remove nop test? Should I split my test? > > Respectively, no and if you want. > > Reviewed-by: Paolo Bonzini <pbonz...@redhat.com> > > As the last person who touched the rtl8139 timer code, I'm glad I didn't > break anything. :) > > Paolo >
Hi, sorry I didn't get everything. Was my patch/test fine or should I change something? I saw you posted a patch for timer. Was your patch tested with my code and you find some problems or was my patch that had some problems? Regards, Frediano >> >> Changed from v2: >> - style (variable declaration, Perl script not able to spot it) >> >> Changed from v1: >> - style >> >> diff --git a/tests/Makefile b/tests/Makefile >> index e4ddb6a..8858407 100644 >> --- a/tests/Makefile >> +++ b/tests/Makefile >> @@ -320,7 +320,7 @@ tests/tmp105-test$(EXESUF): tests/tmp105-test.o >> $(libqos-omap-obj-y) >> tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) >> tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) >> tests/e1000-test$(EXESUF): tests/e1000-test.o >> -tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o >> +tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o $(libqos-pc-obj-y) >> tests/pcnet-test$(EXESUF): tests/pcnet-test.o >> tests/eepro100-test$(EXESUF): tests/eepro100-test.o >> tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o >> diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c >> index f6a1be3..4e0bf02 100644 >> --- a/tests/rtl8139-test.c >> +++ b/tests/rtl8139-test.c >> @@ -10,19 +10,200 @@ >> #include <glib.h> >> #include <string.h> >> #include "libqtest.h" >> +#include "libqos/pci-pc.h" >> #include "qemu/osdep.h" >> +#include "qemu-common.h" >> >> /* Tests only initialization so far. TODO: Replace with functional tests */ >> static void nop(void) >> { >> } >> >> +#define CLK 33000000 >> +#define NS_PER_SEC 1000000000ULL >> + >> +static QPCIBus *pcibus; >> +static QPCIDevice *dev; >> +static void *dev_base; >> + >> +static void save_fn(QPCIDevice *dev, int devfn, void *data) >> +{ >> + QPCIDevice **pdev = (QPCIDevice **) data; >> + >> + *pdev = dev; >> +} >> + >> +static QPCIDevice *get_device(void) >> +{ >> + QPCIDevice *dev; >> + >> + pcibus = qpci_init_pc(); >> + qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev); >> + g_assert(dev != NULL); >> + >> + return dev; >> +} >> + >> +#define PORT(name, len, val) \ >> +static unsigned __attribute__((unused)) in_##name(void) \ >> +{ \ >> + unsigned res = qpci_io_read##len(dev, dev_base+(val)); \ >> + g_test_message("*%s -> %x\n", #name, res); \ >> + return res; \ >> +} \ >> +static void out_##name(unsigned v) \ >> +{ \ >> + g_test_message("%x -> *%s\n", v, #name); \ >> + qpci_io_write##len(dev, dev_base+(val), v); \ >> +} >> + >> +PORT(Timer, l, 0x48) >> +PORT(IntrMask, w, 0x3c) >> +PORT(IntrStatus, w, 0x3E) >> +PORT(TimerInt, l, 0x54) >> + >> +#define fatal(...) do { g_test_message(__VA_ARGS__); g_assert(0); } while >> (0) >> + >> +static void test_timer(void) >> +{ >> + const unsigned from = 0.95 * CLK; >> + const unsigned to = 1.6 * CLK; >> + unsigned prev, curr, next; >> + unsigned cnt, diff; >> + >> + out_IntrMask(0); >> + >> + in_IntrStatus(); >> + in_Timer(); >> + in_Timer(); >> + >> + /* Test 1. test counter continue and continue */ >> + out_TimerInt(0); /* disable timer */ >> + out_IntrStatus(0x4000); >> + out_Timer(12345); /* reset timer to 0 */ >> + curr = in_Timer(); >> + if (curr > 0.1 * CLK) { >> + fatal("time too big %u\n", curr); >> + } >> + for (cnt = 0; ; ) { >> + clock_step(1 * NS_PER_SEC); >> + prev = curr; >> + curr = in_Timer(); >> + >> + /* test skip is in a specific range */ >> + diff = (curr-prev) & 0xffffffffu; >> + if (diff < from || diff > to) { >> + fatal("Invalid diff %u (%u-%u)\n", diff, from, to); >> + } >> + if (curr < prev && ++cnt == 3) { >> + break; >> + } >> + } >> + >> + /* Test 2. Check we didn't get an interrupt with TimerInt == 0 */ >> + if (in_IntrStatus() & 0x4000) { >> + fatal("got an interrupt\n"); >> + } >> + >> + /* Test 3. Setting TimerInt to 1 and Timer to 0 get interrupt */ >> + out_TimerInt(1); >> + out_Timer(0); >> + clock_step(40); >> + if ((in_IntrStatus() & 0x4000) == 0) { >> + fatal("we should have an interrupt here!\n"); >> + } >> + >> + /* Test 3. Check acknowledge */ >> + out_IntrStatus(0x4000); >> + if (in_IntrStatus() & 0x4000) { >> + fatal("got an interrupt\n"); >> + } >> + >> + /* Test. Status set after Timer reset */ >> + out_Timer(0); >> + out_TimerInt(0); >> + out_IntrStatus(0x4000); >> + curr = in_Timer(); >> + out_TimerInt(curr + 0.5 * CLK); >> + clock_step(1 * NS_PER_SEC); >> + out_Timer(0); >> + if ((in_IntrStatus() & 0x4000) == 0) { >> + fatal("we should have an interrupt here!\n"); >> + } >> + >> + /* Test. Status set after TimerInt reset */ >> + out_Timer(0); >> + out_TimerInt(0); >> + out_IntrStatus(0x4000); >> + curr = in_Timer(); >> + out_TimerInt(curr + 0.5 * CLK); >> + clock_step(1 * NS_PER_SEC); >> + out_TimerInt(0); >> + if ((in_IntrStatus() & 0x4000) == 0) { >> + fatal("we should have an interrupt here!\n"); >> + } >> + >> + /* Test 4. Increment TimerInt we should see an interrupt */ >> + curr = in_Timer(); >> + next = curr + 5.0 * CLK; >> + out_TimerInt(next); >> + for (cnt = 0; ; ) { >> + clock_step(1 * NS_PER_SEC); >> + prev = curr; >> + curr = in_Timer(); >> + diff = (curr-prev) & 0xffffffffu; >> + if (diff < from || diff > to) { >> + fatal("Invalid diff %u (%u-%u)\n", diff, from, to); >> + } >> + if (cnt < 3 && curr > next) { >> + if ((in_IntrStatus() & 0x4000) == 0) { >> + fatal("we should have an interrupt here!\n"); >> + } >> + out_IntrStatus(0x4000); >> + next = curr + 5.0 * CLK; >> + out_TimerInt(next); >> + if (++cnt == 3) { >> + out_TimerInt(1); >> + } >> + /* Test 5. Second time we pass from 0 should see an interrupt */ >> + } else if (cnt >= 3 && curr < prev) { >> + /* here we should have an interrupt */ >> + if ((in_IntrStatus() & 0x4000) == 0) { >> + fatal("we should have an interrupt here!\n"); >> + } >> + out_IntrStatus(0x4000); >> + if (++cnt == 5) { >> + break; >> + } >> + } >> + } >> + >> + g_test_message("Everythink is ok!\n"); >> +} >> + >> + >> +static void test_init(void) >> +{ >> + uint64_t barsize; >> + >> + dev = get_device(); >> + >> + dev_base = qpci_iomap(dev, 0, &barsize); >> + >> + g_assert(dev_base != NULL); >> + >> + qpci_device_enable(dev); >> + >> + test_timer(); >> +} >> + >> int main(int argc, char **argv) >> { >> int ret; >> >> g_test_init(&argc, &argv, NULL); >> qtest_add_func("/rtl8139/nop", nop); >> + qtest_add_func("/rtl8139/timer", test_init); >> >> qtest_start("-device rtl8139"); >> ret = g_test_run(); >>