Re: [PATCH v2 3/4] selftests: kvm: Add exception handling to selftests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 09.10.20 13:46, Aaron Lewis wrote:

Add the infrastructure needed to enable exception handling in selftests.
This allows any of the exception and interrupt vectors to be overridden
in the guest.

Signed-off-by: Aaron Lewis <aaronlewis@xxxxxxxxxx>
---

v1 -> v2:

   - Use exception_handlers instead of gs base to pass table to the guest.
   - Move unexpected vector assert to processor.c.

---
  tools/testing/selftests/kvm/Makefile          |  19 ++-
  .../selftests/kvm/include/x86_64/processor.h  |  25 ++++
  tools/testing/selftests/kvm/lib/kvm_util.c    |   5 +
  .../selftests/kvm/lib/kvm_util_internal.h     |   2 +
  .../selftests/kvm/lib/x86_64/handlers.S       |  81 +++++++++++++
  .../selftests/kvm/lib/x86_64/processor.c      | 114 +++++++++++++++++-
  6 files changed, 237 insertions(+), 9 deletions(-)
  create mode 100644 tools/testing/selftests/kvm/lib/x86_64/handlers.S

diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 7ebe71fbca53..aaaf992faf87 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -34,7 +34,7 @@ ifeq ($(ARCH),s390)
  endif

  LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c lib/test_util.c
-LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c
+LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
  LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c
  LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c

@@ -110,14 +110,21 @@ LDFLAGS += -pthread $(no-pie-option) $(pgste-option)
  include ../lib.mk

  STATIC_LIBS := $(OUTPUT)/libkvm.a
-LIBKVM_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM))
-EXTRA_CLEAN += $(LIBKVM_OBJ) $(STATIC_LIBS) cscope.*
+LIBKVM_C := $(filter %.c,$(LIBKVM))
+LIBKVM_S := $(filter %.S,$(LIBKVM))
+LIBKVM_C_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_C))
+LIBKVM_S_OBJ := $(patsubst %.S, $(OUTPUT)/%.o, $(LIBKVM_S))
+EXTRA_CLEAN += $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ) $(STATIC_LIBS) cscope.*
+
+x := $(shell mkdir -p $(sort $(dir $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ))))
+$(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@

-x := $(shell mkdir -p $(sort $(dir $(LIBKVM_OBJ))))
-$(LIBKVM_OBJ): $(OUTPUT)/%.o: %.c
+$(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S
         $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@

-$(OUTPUT)/libkvm.a: $(LIBKVM_OBJ)
+LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ)
+$(OUTPUT)/libkvm.a: $(LIBKVM_OBJS)
         $(AR) crs $@ $^

  x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
index 0a65e7bb5249..b0a43141fbb3 100644
--- a/tools/testing/selftests/kvm/include/x86_64/processor.h
+++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
@@ -36,6 +36,8 @@
  #define X86_CR4_SMAP           (1ul << 21)
  #define X86_CR4_PKE            (1ul << 22)

+#define UNEXPECTED_VECTOR_PORT 0xfff0u
+
  /* General Registers in 64-Bit Mode */
  struct gpr64_regs {
         u64 rax;
@@ -239,6 +241,11 @@ static inline struct desc_ptr get_idt(void)
         return idt;
  }

+static inline void outl(uint16_t port, uint32_t value)
+{
+       __asm__ __volatile__("outl %%eax, %%dx" : : "d"(port), "a"(value));
+}
+
  #define SET_XMM(__var, __xmm) \
         asm volatile("movq %0, %%"#__xmm : : "r"(__var) : #__xmm)

@@ -338,6 +345,24 @@ uint32_t kvm_get_cpuid_max_basic(void);
  uint32_t kvm_get_cpuid_max_extended(void);
  void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits);

+struct ex_regs {
+       uint64_t rax, rcx, rdx, rbx;
+       uint64_t rbp, rsi, rdi;
+       uint64_t r8, r9, r10, r11;
+       uint64_t r12, r13, r14, r15;
+       uint64_t vector;
+       uint64_t error_code;
+       uint64_t rip;
+       uint64_t cs;
+       uint64_t rflags;
+};
+
+void vm_init_descriptor_tables(struct kvm_vm *vm);
+void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid);
+void vm_handle_exception(struct kvm_vm *vm, int vector,
+                       void (*handler)(struct ex_regs *));
+void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid);
+
  /*
   * Basic CPU control in CR0
   */
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 74776ee228f2..ecbb5e4f9ef6 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -1195,6 +1195,11 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid)
         do {
                 rc = ioctl(vcpu->fd, KVM_RUN, NULL);
         } while (rc == -1 && errno == EINTR);
+
+#ifdef __x86_64__
+       assert_on_unhandled_exception(vm, vcpuid);
+#endif

Can we avoid the #ifdef and instead just implement a stub function for the other archs? Then move the prototype the the function to a generic header of course.

Alex



Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879






[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux