Introduce a test library to get IRQ numbers and counts. Add utility functions to synchronize global variables between the host and guest to track interrupt reception and readiness. Signed-off-by: David Matlack Signed-off-by: Josh Hilke Co-developed-by: Josh Hilke --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../testing/selftests/kvm/include/irq_util.h | 11 +++ .../testing/selftests/kvm/include/kvm_util.h | 11 +++ tools/testing/selftests/kvm/lib/irq_util.c | 84 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 tools/testing/selftests/kvm/include/irq_util.h create mode 100644 tools/testing/selftests/kvm/lib/irq_util.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm index b3e223f45575..d8f77e181e8e 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -11,6 +11,7 @@ LIBKVM += lib/kvm_util.c LIBKVM += lib/lru_gen_util.c LIBKVM += lib/memstress.c LIBKVM += lib/guest_sprintf.c +LIBKVM += lib/irq_util.c LIBKVM += lib/rbtree.c LIBKVM += lib/sparsebit.c LIBKVM += lib/test_util.c diff --git a/tools/testing/selftests/kvm/include/irq_util.h b/tools/testing/selftests/kvm/include/irq_util.h new file mode 100644 index 000000000000..a5d6b63b30da --- /dev/null +++ b/tools/testing/selftests/kvm/include/irq_util.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_KVM_PROC_UTIL_H +#define SELFTEST_KVM_PROC_UTIL_H + +#include + +int get_irq_number(const char *device_bdf, int msi); +uint64_t get_irq_count(int irq); +uint64_t get_irq_count_by_name(const char *name); + +#endif /* SELFTEST_KVM_PROC_UTIL_H */ diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index 8b39cb919f4f..8be02e7980eb 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -1144,6 +1144,17 @@ vm_adjust_num_guest_pages(enum vm_guest_mode mode, unsigned int num_guest_pages) memcpy(&(g), _p, sizeof(g)); \ }) +#define READ_FROM_GUEST(_vm, _variable) ({ \ + sync_global_from_guest(_vm, _variable); \ + READ_ONCE(_variable); \ +}) + +#define WRITE_TO_GUEST(_vm, _variable, _value) do { \ + WRITE_ONCE(_variable, _value); \ + sync_global_to_guest(_vm, _variable); \ +} while (0) + + /* * Write a global value, but only in the VM's (guest's) domain. Primarily used * for "globals" that hold per-VM values (VMs always duplicate code and global diff --git a/tools/testing/selftests/kvm/lib/irq_util.c b/tools/testing/selftests/kvm/lib/irq_util.c new file mode 100644 index 000000000000..062f6cda23b9 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/irq_util.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "kvm_util.h" +#include "test_util.h" +#include "irq_util.h" + +#include + +static FILE *open_proc_interrupts(void) +{ + FILE *fp; + + fp = fopen("/proc/interrupts", "r"); + TEST_ASSERT(fp, "fopen(/proc/interrupts) failed"); + + return fp; +} + +int get_irq_number(const char *device_bdf, int msi) +{ + char search_string[64]; + char line[4096]; + int irq = -1; + FILE *fp; + + fp = open_proc_interrupts(); + + snprintf(search_string, sizeof(search_string), "vfio-msix[%d]", msi); + + while (fgets(line, sizeof(line), fp)) { + if (strstr(line, device_bdf) && strstr(line, search_string)) { + TEST_ASSERT_EQ(1, sscanf(line, "%d:", &irq)); + break; + } + } + + fclose(fp); + + TEST_ASSERT(irq != -1, "Failed to locate IRQ for %s %s", device_bdf, search_string); + return irq; +} + +static int parse_interrupt_count(char *token) +{ + char *c; + + for (c = token; *c; c++) { + if (!isdigit(*c)) + return 0; + } + + return atoi_non_negative("interrupt count", token); +} + +uint64_t get_irq_count_by_name(const char *name) +{ + uint64_t total_count = 0; + char line[4096]; + FILE *fp; + + fp = open_proc_interrupts(); + + while (fgets(line, sizeof(line), fp)) { + char *token = strtok(line, " "); + + if (strcmp(token, name)) + continue; + + while ((token = strtok(NULL, " "))) + total_count += parse_interrupt_count(token); + + break; + } + + fclose(fp); + return total_count; +} + +uint64_t get_irq_count(int irq) +{ + char search_string[32]; + + snprintf(search_string, sizeof(search_string), "%d:", irq); + return get_irq_count_by_name(search_string); +} -- 2.53.0.1118.gaef5881109-goog