mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-27 03:49:57 -04:00
KVM: riscv: selftests: Add exception handling support
Add the infrastructure for guest exception handling in riscv selftests. Customized handlers can be enabled by vm_install_exception_handler(vector) or vm_install_interrupt_handler(). The code is inspired from that of x86/arm64. Signed-off-by: Haibo Xu <haibo1.xu@intel.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
|
||||
#define DEFAULT_RISCV_GUEST_STACK_VADDR_MIN 0xac0000
|
||||
|
||||
static vm_vaddr_t exception_handlers;
|
||||
|
||||
static uint64_t page_align(struct kvm_vm *vm, uint64_t v)
|
||||
{
|
||||
return (v + vm->page_size) & ~(vm->page_size - 1);
|
||||
@@ -364,8 +366,75 @@ void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void kvm_exit_unexpected_exception(int vector, int ec)
|
||||
{
|
||||
ucall(UCALL_UNHANDLED, 2, vector, ec);
|
||||
}
|
||||
|
||||
void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct ucall uc;
|
||||
|
||||
if (get_ucall(vcpu, &uc) == UCALL_UNHANDLED) {
|
||||
TEST_FAIL("Unexpected exception (vector:0x%lx, ec:0x%lx)",
|
||||
uc.args[0], uc.args[1]);
|
||||
}
|
||||
}
|
||||
|
||||
struct handlers {
|
||||
exception_handler_fn exception_handlers[NR_VECTORS][NR_EXCEPTIONS];
|
||||
};
|
||||
|
||||
void route_exception(struct ex_regs *regs)
|
||||
{
|
||||
struct handlers *handlers = (struct handlers *)exception_handlers;
|
||||
int vector = 0, ec;
|
||||
|
||||
ec = regs->cause & ~CAUSE_IRQ_FLAG;
|
||||
if (ec >= NR_EXCEPTIONS)
|
||||
goto unexpected_exception;
|
||||
|
||||
/* Use the same handler for all the interrupts */
|
||||
if (regs->cause & CAUSE_IRQ_FLAG) {
|
||||
vector = 1;
|
||||
ec = 0;
|
||||
}
|
||||
|
||||
if (handlers && handlers->exception_handlers[vector][ec])
|
||||
return handlers->exception_handlers[vector][ec](regs);
|
||||
|
||||
unexpected_exception:
|
||||
return kvm_exit_unexpected_exception(vector, ec);
|
||||
}
|
||||
|
||||
void vcpu_init_vector_tables(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
extern char exception_vectors;
|
||||
|
||||
vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(stvec), (unsigned long)&exception_vectors);
|
||||
}
|
||||
|
||||
void vm_init_vector_tables(struct kvm_vm *vm)
|
||||
{
|
||||
vm->handlers = __vm_vaddr_alloc(vm, sizeof(struct handlers),
|
||||
vm->page_size, MEM_REGION_DATA);
|
||||
|
||||
*(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
|
||||
}
|
||||
|
||||
void vm_install_exception_handler(struct kvm_vm *vm, int vector, exception_handler_fn handler)
|
||||
{
|
||||
struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
|
||||
|
||||
assert(vector < NR_EXCEPTIONS);
|
||||
handlers->exception_handlers[0][vector] = handler;
|
||||
}
|
||||
|
||||
void vm_install_interrupt_handler(struct kvm_vm *vm, exception_handler_fn handler)
|
||||
{
|
||||
struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
|
||||
|
||||
handlers->exception_handlers[1][0] = handler;
|
||||
}
|
||||
|
||||
struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
|
||||
|
||||
Reference in New Issue
Block a user