Commit d84fe2f3 authored by Bibo Mao's avatar Bibo Mao Committed by Huacai Chen
Browse files

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: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 1c5d3a1e
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -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
@@ -155,6 +160,17 @@ 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);

static inline void cpu_relax(void)
{
	asm volatile("nop" ::: "memory");
+29 −0
Original line number Diff line number Diff line
@@ -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)
{
@@ -183,7 +184,14 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)

void route_exception(struct ex_regs *regs)
{
	int vector;
	unsigned long pc, estat, badv;
	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;
}

uint32_t guest_get_vcpuid(void)
{
	return csr_read(LOONGARCH_CSR_CPUID);