Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: LoongArch: selftests: Add exception handler register interface

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

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Bibo Mao and committed by
Huacai Chen
d84fe2f3 1c5d3a1e

+45
+16
tools/testing/selftests/kvm/include/loongarch/processor.h
··· 84 84 #define LOONGARCH_CSR_EUEN 0x2 85 85 #define LOONGARCH_CSR_ECFG 0x4 86 86 #define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */ 87 + #define CSR_ESTAT_EXC_SHIFT 16 88 + #define CSR_ESTAT_EXC_WIDTH 6 89 + #define CSR_ESTAT_EXC (0x3f << CSR_ESTAT_EXC_SHIFT) 90 + #define EXCCODE_INT 0 /* Interrupt */ 91 + #define INT_TI 11 /* Timer interrupt*/ 87 92 #define LOONGARCH_CSR_ERA 0x6 /* ERA */ 88 93 #define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */ 89 94 #define LOONGARCH_CSR_EENTRY 0xc ··· 159 154 #define BADV_OFFSET_EXREGS offsetof(struct ex_regs, badv) 160 155 #define PRMD_OFFSET_EXREGS offsetof(struct ex_regs, prmd) 161 156 #define EXREGS_SIZE sizeof(struct ex_regs) 157 + 158 + #define VECTOR_NUM 64 159 + 160 + typedef void(*handler_fn)(struct ex_regs *); 161 + 162 + struct handlers { 163 + handler_fn exception_handlers[VECTOR_NUM]; 164 + }; 165 + 166 + void vm_init_descriptor_tables(struct kvm_vm *vm); 167 + void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn handler); 162 168 163 169 static inline void cpu_relax(void) 164 170 {
+29
tools/testing/selftests/kvm/lib/loongarch/processor.c
··· 11 11 #define LOONGARCH_GUEST_STACK_VADDR_MIN 0x200000 12 12 13 13 static vm_paddr_t invalid_pgtable[4]; 14 + static vm_vaddr_t exception_handlers; 14 15 15 16 static uint64_t virt_pte_index(struct kvm_vm *vm, vm_vaddr_t gva, int level) 16 17 { ··· 184 183 185 184 void route_exception(struct ex_regs *regs) 186 185 { 186 + int vector; 187 187 unsigned long pc, estat, badv; 188 + struct handlers *handlers; 189 + 190 + handlers = (struct handlers *)exception_handlers; 191 + vector = (regs->estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT; 192 + if (handlers && handlers->exception_handlers[vector]) 193 + return handlers->exception_handlers[vector](regs); 188 194 189 195 pc = regs->pc; 190 196 badv = regs->badv; 191 197 estat = regs->estat; 192 198 ucall(UCALL_UNHANDLED, 3, pc, estat, badv); 193 199 while (1) ; 200 + } 201 + 202 + void vm_init_descriptor_tables(struct kvm_vm *vm) 203 + { 204 + void *addr; 205 + 206 + vm->handlers = __vm_vaddr_alloc(vm, sizeof(struct handlers), 207 + LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA); 208 + 209 + addr = addr_gva2hva(vm, vm->handlers); 210 + memset(addr, 0, vm->page_size); 211 + exception_handlers = vm->handlers; 212 + sync_global_to_guest(vm, exception_handlers); 213 + } 214 + 215 + void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn handler) 216 + { 217 + struct handlers *handlers = addr_gva2hva(vm, vm->handlers); 218 + 219 + assert(vector < VECTOR_NUM); 220 + handlers->exception_handlers[vector] = handler; 194 221 } 195 222 196 223 uint32_t guest_get_vcpuid(void)