Add interrupt and exception handler register interface. When exception
happens, execute registered exception handler if exists, else report
error.

Signed-off-by: Bibo Mao <[email protected]>
---
 .../kvm/include/loongarch/processor.h         | 14 +++++++++
 .../selftests/kvm/lib/loongarch/processor.c   | 29 +++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h 
b/tools/testing/selftests/kvm/include/loongarch/processor.h
index 374caddfb0db..a18ac7bff303 100644
--- a/tools/testing/selftests/kvm/include/loongarch/processor.h
+++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
@@ -84,6 +84,11 @@
 #define LOONGARCH_CSR_EUEN             0x2
 #define LOONGARCH_CSR_ECFG             0x4
 #define LOONGARCH_CSR_ESTAT            0x5  /* Exception status */
+#define  CSR_ESTAT_EXC_SHIFT           16
+#define  CSR_ESTAT_EXC_WIDTH           6
+#define  CSR_ESTAT_EXC                 (0x3f << CSR_ESTAT_EXC_SHIFT)
+#define    EXCCODE_INT                 0    /* Interrupt */
+#define      INT_TI                    11   /* Timer interrupt*/
 #define LOONGARCH_CSR_ERA              0x6  /* ERA */
 #define LOONGARCH_CSR_BADV             0x7  /* Bad virtual address */
 #define LOONGARCH_CSR_EENTRY           0xc
@@ -133,6 +138,15 @@ struct ex_regs {
 #define PRMD_OFFSET_EXREGS             offsetof(struct ex_regs, prmd)
 #define EXREGS_SIZE                    sizeof(struct ex_regs)
 
+#define VECTOR_NUM                     64
+typedef void(*handler_fn)(struct ex_regs *);
+struct handlers {
+       handler_fn exception_handlers[VECTOR_NUM];
+};
+
+void vm_init_descriptor_tables(struct kvm_vm *vm);
+void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn 
handler);
+
 #else
 #define PC_OFFSET_EXREGS               ((EXREGS_GPRS + 0) * 8)
 #define ESTAT_OFFSET_EXREGS            ((EXREGS_GPRS + 1) * 8)
diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c 
b/tools/testing/selftests/kvm/lib/loongarch/processor.c
index 0ac1abcb71cb..be537c5ff74e 100644
--- a/tools/testing/selftests/kvm/lib/loongarch/processor.c
+++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
@@ -11,6 +11,7 @@
 #define LOONGARCH_GUEST_STACK_VADDR_MIN                0x200000
 
 static vm_paddr_t invalid_pgtable[4];
+static vm_vaddr_t exception_handlers;
 
 static uint64_t virt_pte_index(struct kvm_vm *vm, vm_vaddr_t gva, int level)
 {
@@ -184,6 +185,13 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
 void route_exception(struct ex_regs *regs)
 {
        unsigned long pc, estat, badv;
+       int vector;
+       struct handlers *handlers;
+
+       handlers = (struct handlers *)exception_handlers;
+       vector = (regs->estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
+       if (handlers && handlers->exception_handlers[vector])
+               return handlers->exception_handlers[vector](regs);
 
        pc = regs->pc;
        badv  = regs->badv;
@@ -192,6 +200,27 @@ void route_exception(struct ex_regs *regs)
        while (1) ;
 }
 
+void vm_init_descriptor_tables(struct kvm_vm *vm)
+{
+       void *addr;
+
+       vm->handlers = __vm_vaddr_alloc(vm, sizeof(struct handlers),
+                       LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
+
+       addr = addr_gva2hva(vm, vm->handlers);
+       memset(addr, 0, vm->page_size);
+       exception_handlers = vm->handlers;
+       sync_global_to_guest(vm, exception_handlers);
+}
+
+void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn 
handler)
+{
+       struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
+
+       assert(vector < VECTOR_NUM);
+       handlers->exception_handlers[vector] = handler;
+}
+
 void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
 {
        int i;
-- 
2.39.3


Reply via email to