From patchwork Fri Apr 23 04:03:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12219531 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52D8EC433ED for ; Fri, 23 Apr 2021 04:04:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 28B5161425 for ; Fri, 23 Apr 2021 04:04:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231542AbhDWEEk (ORCPT ); Fri, 23 Apr 2021 00:04:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229717AbhDWEEj (ORCPT ); Fri, 23 Apr 2021 00:04:39 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 40462C061574 for ; Thu, 22 Apr 2021 21:04:02 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id s34-20020a252d620000b02904e34d3a48abso22632819ybe.13 for ; Thu, 22 Apr 2021 21:04:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=YiVwtBVL/pOUXDA1kClnzHrI3XyPs8Rvvwwd0LrXoL4=; b=AkvMQr2HAbsRNL2vcxQ6E6RhfJu1qrPwlp1Q9SPuVbUfiTxzVIX06FZhzYs2Pgqu5V YE2zv+wuUCxKbWLsFgmnIMmnZz04ZXTTXYF8/x41miMA8kcSlio3KSYik7FbfITE0y2A KrcIofSeRqOMdwZTkJW6z0znihMokgEf7V17Plrp8fJRAPuS4lKt21VxcnbgMEsulhsv s2pBPNNgTS+0UphTDjJtF8U5mdP+AF72iM0PUmkKyLc3ksyCj/bkVw9JYzj+xqggU1lD yDFsEya/21cZJdgUC3LG2MheUkmlQbbkCCNLTM/8xmoIuYODjc2uIzHIpd7GQ9/DpxfD wumQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=YiVwtBVL/pOUXDA1kClnzHrI3XyPs8Rvvwwd0LrXoL4=; b=CGjTxZJYWwyeGaCNh9v0T2kVYFH1GqcWOEA5v+MVyl5eemU/vRlW1WlRkSpR53ZIWp 5jGfVZBaC23XOugxSP2xC5bF0jlFjVXd4oXnly1mhECpmEtFa4+5TO1qPkkcIyK9UpbI 4gwYoM0LTuVee6YjdttzMuPY8QQLUE+SSvbk7c2FIsOdrPlkGbr6oDxVC4yI2+us3o5s KKDWpRXsXqv1l/ttuTo4nFe5QyL3Yc9XHfq4kw4sZ3tVp3UKPkawnhLGxq80NfLsB6T5 TKD54SUBMyP7lu0Ic0dsqf8Ug8W1KoTyu9A9n+KsAOkgalWikZjBnhj9ONnXKFQtOyBA Z5gQ== X-Gm-Message-State: AOAM532dcuvF459G9eW+rf2vettDnBHIOnm3fgOvksiQ6bvLav4QxKij hovTlfoJMDOkSFZMryYKYJ2Z2QgKVjR4ddYcAfcQhfE4gErOR6+dM4tR7FXzp4k08x/LIISdyeH EEUYal/sB7telXxXW7zfidXUeZpx2BzFzL8rqhdH8slTw1VVG5ZE+l4dFzaodKsI= X-Google-Smtp-Source: ABdhPJyFCWJFP9wUa3EEhaotFzFlHuSo2vPOiQWFas8rbajb6F+czhSpzglPQ3wUJRlNwXJKTz71oqDQPLlbQQ== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a25:9085:: with SMTP id t5mr1887813ybl.26.1619150641488; Thu, 22 Apr 2021 21:04:01 -0700 (PDT) Date: Thu, 22 Apr 2021 21:03:49 -0700 In-Reply-To: <20210423040351.1132218-1-ricarkol@google.com> Message-Id: <20210423040351.1132218-2-ricarkol@google.com> Mime-Version: 1.0 References: <20210423040351.1132218-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.498.g6c1eba8ee3d-goog Subject: [PATCH 1/3] KVM: selftests: Add exception handling support for aarch64 From: Ricardo Koller To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: pbonzini@redhat.com, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com, eric.auger@redhat.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add the infrastructure needed to enable exception handling in aarch64 selftests. The exception handling defaults to an unhandled-exception handler which aborts the test, just like x86. These handlers can be overridden by calling vm_handle_exception with a (vector, error-code) tuple. The unhandled exception reporting from the guest is done using the new ucall UCALL_UNHANDLED. Signed-off-by: Ricardo Koller --- tools/testing/selftests/kvm/Makefile | 2 +- .../selftests/kvm/include/aarch64/processor.h | 69 ++++++++++++ .../testing/selftests/kvm/include/kvm_util.h | 1 + .../selftests/kvm/lib/aarch64/handlers.S | 104 ++++++++++++++++++ .../selftests/kvm/lib/aarch64/processor.c | 56 ++++++++++ 5 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/kvm/lib/aarch64/handlers.S diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 4e548d7ab0ab..618c5903f478 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -35,7 +35,7 @@ endif LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c lib/test_util.c lib/guest_modes.c lib/perf_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 lib/x86_64/handlers.S -LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c +LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handlers.S LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index b7fa0c8551db..5c902ad95c35 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -8,6 +8,7 @@ #define SELFTEST_KVM_PROCESSOR_H #include "kvm_util.h" +#include #define ARM64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ @@ -18,6 +19,7 @@ #define MAIR_EL1 3, 0, 10, 2, 0 #define TTBR0_EL1 3, 0, 2, 0, 0 #define SCTLR_EL1 3, 0, 1, 0, 0 +#define VBAR_EL1 3, 0, 12, 0, 0 /* * Default MAIR @@ -56,4 +58,71 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, int vcpuid, struct kvm_vcpu_init *ini void aarch64_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_vcpu_init *init, void *guest_code); +struct ex_regs { + u64 pc; + u64 pstate; + u64 sp; + u64 lr; + u64 regs[31]; +}; + +#define VECTOR_NUM 16 + +enum { + VECTOR_SYNC_EL1_SP0, + VECTOR_IRQ_EL1_SP0, + VECTOR_FIQ_EL1_SP0, + VECTOR_ERROR_EL1_SP0, + + VECTOR_SYNC_EL1, + VECTOR_IRQ_EL1, + VECTOR_FIQ_EL1, + VECTOR_ERROR_EL1, + + VECTOR_SYNC_EL0_64, + VECTOR_IRQ_EL0_64, + VECTOR_FIQ_EL0_64, + VECTOR_ERROR_EL0_64, + + VECTOR_SYNC_EL0_32, + VECTOR_IRQ_EL0_32, + VECTOR_FIQ_EL0_32, + VECTOR_ERROR_EL0_32, +}; + +/* Some common EC (Exception classes) */ +#define ESR_EC_ILLEGAL_INS 0x0e +#define ESR_EC_SVC64 0x15 +#define ESR_EC_IABORT_EL1 0x21 +#define ESR_EC_DABORT_EL1 0x25 +#define ESR_EC_SERROR 0x2f +#define ESR_EC_HW_BP_EL1 0x31 +#define ESR_EC_SSTEP_EL1 0x33 +#define ESR_EC_WP_EL1 0x35 +#define ESR_EC_BRK_INS 0x3C + +#define ESR_EC_NUM 64 + +#define ESR_EC_SHIFT 26 +#define ESR_EC_MASK 0x3f + +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, int ec, + void (*handler)(struct ex_regs *)); + +#define SPSR_D (1 << 9) +#define SPSR_SS (1 << 21) + +#define write_sysreg(reg, val) \ +({ \ + asm volatile("msr "__stringify(reg)", %0" : : "r"(val)); \ +}) + +#define read_sysreg(reg) \ +({ u64 val; \ + asm volatile("mrs %0, "__stringify(reg) : "=r"(val) : : "memory");\ + val; \ +}) + #endif /* SELFTEST_KVM_PROCESSOR_H */ diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index bea4644d645d..7880929ea548 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -347,6 +347,7 @@ enum { UCALL_SYNC, UCALL_ABORT, UCALL_DONE, + UCALL_UNHANDLED, }; #define UCALL_MAX_ARGS 6 diff --git a/tools/testing/selftests/kvm/lib/aarch64/handlers.S b/tools/testing/selftests/kvm/lib/aarch64/handlers.S new file mode 100644 index 000000000000..c920679b87c0 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/aarch64/handlers.S @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +.macro save_registers, el + stp x28, x29, [sp, #-16]! + stp x26, x27, [sp, #-16]! + stp x24, x25, [sp, #-16]! + stp x22, x23, [sp, #-16]! + stp x20, x21, [sp, #-16]! + stp x18, x19, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x4, x5, [sp, #-16]! + stp x2, x3, [sp, #-16]! + stp x0, x1, [sp, #-16]! + + .if \el == 0 + mrs x1, sp_el0 + .else + mov x1, sp + .endif + stp x1, lr, [sp, #-16]! /* SP, LR */ + + mrs x1, elr_el1 + mrs x2, spsr_el1 + stp x1, x2, [sp, #-16]! /* PC, PSTATE */ +.endm + +.macro restore_registers, el + ldp x1, x2, [sp], #16 /* PC, PSTATE */ + msr elr_el1, x1 + msr spsr_el1, x2 + + ldp x1, lr, [sp], #16 /* SP, LR */ + .if \el == 0 + msr sp_el0, x1 + .endif + + ldp x0, x1, [sp], #16 + ldp x2, x3, [sp], #16 + ldp x4, x5, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x18, x19, [sp], #16 + ldp x20, x21, [sp], #16 + ldp x22, x23, [sp], #16 + ldp x24, x25, [sp], #16 + ldp x26, x27, [sp], #16 + ldp x28, x29, [sp], #16 + + eret +.endm + +.pushsection ".entry.text", "ax" +.balign 0x800 +.global vectors +vectors: +.popsection + +/* + * Build an exception handler for vector and append a jump to it into + * vectors (while making sure that it's 0x80 aligned). + */ +.macro HANDLER, el, label, vector +handler\()\vector: + save_registers \el + mov x0, sp + mov x1, \vector + bl route_exception + restore_registers \el + +.pushsection ".entry.text", "ax" +.balign 0x80 + b handler\()\vector +.popsection +.endm + +.global ex_handler_code +ex_handler_code: + HANDLER 1, sync, 0 // Synchronous EL1t + HANDLER 1, irq, 1 // IRQ EL1t + HANDLER 1, fiq, 2 // FIQ EL1t + HANDLER 1, error, 3 // Error EL1t + + HANDLER 1, sync, 4 // Synchronous EL1h + HANDLER 1, irq, 5 // IRQ EL1h + HANDLER 1, fiq, 6 // FIQ EL1h + HANDLER 1, error, 7 // Error EL1h + + HANDLER 0, sync, 8 // Synchronous 64-bit EL0 + HANDLER 0, irq, 9 // IRQ 64-bit EL0 + HANDLER 0, fiq, 10 // FIQ 64-bit EL0 + HANDLER 0, error, 11 // Error 64-bit EL0 + + HANDLER 0, sync, 12 // Synchronous 32-bit EL0 + HANDLER 0, irq, 13 // IRQ 32-bit EL0 + HANDLER 0, fiq, 14 // FIQ 32-bit EL0 + HANDLER 0, error, 15 // Error 32-bit EL0 diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c index cee92d477dc0..286305b561d8 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/processor.c +++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c @@ -6,6 +6,7 @@ */ #include +#include #include "kvm_util.h" #include "../kvm_util_internal.h" @@ -14,6 +15,8 @@ #define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000 #define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN 0xac0000 +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); @@ -336,4 +339,57 @@ void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...) void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid) { + struct ucall uc; + + if (get_ucall(vm, vcpuid, &uc) == UCALL_UNHANDLED) { + TEST_ASSERT(false, + "Unexpected exception guest (vector:0x%lx, ec:0x%lx)", + uc.args[0], uc.args[1]); + } +} + +void kvm_exit_unexpected_vector(int vector, uint64_t ec) +{ + ucall(UCALL_UNHANDLED, 2, vector, ec); +} + +#define HANDLERS_IDX(_vector, _ec) ((_vector * ESR_EC_NUM) + _ec) + +void vm_init_descriptor_tables(struct kvm_vm *vm) +{ + vm->handlers = vm_vaddr_alloc(vm, + VECTOR_NUM * ESR_EC_NUM * sizeof(void *), + vm->page_size, 0, 0); + *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers; +} + +void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid) +{ + extern char vectors; + + set_reg(vm, vcpuid, ARM64_SYS_REG(VBAR_EL1), (uint64_t)&vectors); +} + +void route_exception(struct ex_regs *regs, int vector) +{ + typedef void(*handler)(struct ex_regs *); + uint64_t esr = read_sysreg(esr_el1); + uint64_t ec = (esr >> ESR_EC_SHIFT) & ESR_EC_MASK; + + handler *handlers = (handler *)exception_handlers; + + if (handlers && handlers[HANDLERS_IDX(vector, ec)]) + handlers[HANDLERS_IDX(vector, ec)](regs); + else + kvm_exit_unexpected_vector(vector, ec); +} + +void vm_handle_exception(struct kvm_vm *vm, int vector, int ec, + void (*handler)(struct ex_regs *)) +{ + vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers); + + assert(vector < VECTOR_NUM); + assert(ec < ESR_EC_NUM); + handlers[HANDLERS_IDX(vector, ec)] = (vm_vaddr_t)handler; } From patchwork Fri Apr 23 04:03:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12219535 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F69CC43461 for ; Fri, 23 Apr 2021 04:04:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2D8976144A for ; Fri, 23 Apr 2021 04:04:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231991AbhDWEEl (ORCPT ); Fri, 23 Apr 2021 00:04:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46086 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229454AbhDWEEj (ORCPT ); Fri, 23 Apr 2021 00:04:39 -0400 Received: from mail-qv1-xf49.google.com (mail-qv1-xf49.google.com [IPv6:2607:f8b0:4864:20::f49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 14CACC06138B for ; Thu, 22 Apr 2021 21:04:04 -0700 (PDT) Received: by mail-qv1-xf49.google.com with SMTP id e20-20020ad442b40000b029019aa511c767so17431347qvr.18 for ; Thu, 22 Apr 2021 21:04:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=4m81bHDjNSYt8zyq7LAtxG+mCmVoRicU2Z2tDQr+ANM=; b=ttEE2LvX/oBOTyaItyie2MpN9k35zMGBT9kYzRLn6/yhgUNmTRWR0aFHCpI6fHgd3F 08zo2151/XNwSlluoE0oBdiD7Y8/+z6cAQ18Yo9y8f46D5gYvbU80nwGr9vLQkR6qO0j Iinlq9sxx/EhDKRrLXACBUGFuKA6Ht3b+m5U8LTpoZ4eTJL9/c09Qo1Oohntq/2RZwpy CS4e4S2/sRo5BUf4+EhY1uxEwjZA2f1043bXJ+8/uUp/WrMiY3hMquIL87SUGvkvg3jA FRBVYo43I5e9JjbLNbX1xiQaRypGoYZ+2a/Z8uSuikiabbpCChm2j9AHtmSCG2WtQxPb 6r2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=4m81bHDjNSYt8zyq7LAtxG+mCmVoRicU2Z2tDQr+ANM=; b=oci+3Wr4GNSsh7JOsGHwBTmUjNObXYGaIf+VXc1bL4TJJqI2L1otw5m+QWuEmJU8/a U+Ieh9fBISdL2UeyIIvMYyC0vsRELFgkt+dmn+yuiGxTYH9xmQcVPVwjTutC7zcdgvJr Fm8LqM/1O0Af1rlVbltPnUXWj4r462GP4lwraBKUbmykxAv2Q+gJPJy26xrdqU5tMstk 9cRs4j+arhRDpncjfGpvOUCsa4m9qLvDAE1qs+LH0dVQaOKPFAoNGk5lwJHApeA2xz1e mxySenDgZT63sf81dyCSpRR10uoUrA8XYvB++fHbNNwdN7sQNsI+HmgE3vDtaAjFWq+0 N2CQ== X-Gm-Message-State: AOAM531l/KSM4Hd+Fwz0XAnTWNHfPVKbyJTgXMMElNLUQo4Y4YrATSm8 j8Kx6NG3yeAzLvaq3YUeeD28kvvI52m0XBM03TZtfEomJfgrPKJZwZP1zxe920xP3h/qdXm7rZX KLmDxSnnI1WdUAsSKayUcr9VpCN+y/8T25usXPiI0lwv3LxTAW2Z1JMoxrKwzqR8= X-Google-Smtp-Source: ABdhPJy0W1d+0aHxqXIC8gNvLBk4iBpruGH9i2h9ef6ZmM2tZEAUMtw2hDW8UkCZZy4LMWcL2OYUZDnC2zXQwg== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a05:6214:849:: with SMTP id dg9mr2286252qvb.30.1619150642934; Thu, 22 Apr 2021 21:04:02 -0700 (PDT) Date: Thu, 22 Apr 2021 21:03:50 -0700 In-Reply-To: <20210423040351.1132218-1-ricarkol@google.com> Message-Id: <20210423040351.1132218-3-ricarkol@google.com> Mime-Version: 1.0 References: <20210423040351.1132218-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.498.g6c1eba8ee3d-goog Subject: [PATCH 2/3] KVM: selftests: Add aarch64/debug-exceptions test From: Ricardo Koller To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: pbonzini@redhat.com, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com, eric.auger@redhat.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Covers fundamental tests for debug exceptions. The guest installs and handle its debug exceptions itself, without KVM_SET_GUEST_DEBUG. Signed-off-by: Ricardo Koller --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/aarch64/debug-exceptions.c | 250 ++++++++++++++++++ .../selftests/kvm/include/aarch64/processor.h | 17 ++ 4 files changed, 269 insertions(+) create mode 100644 tools/testing/selftests/kvm/aarch64/debug-exceptions.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index e65d5572aefc..f09ed908422b 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only +/aarch64/debug-exceptions /aarch64/get-reg-list /aarch64/get-reg-list-sve /aarch64/vgic_init diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 618c5903f478..2f92442c0cc9 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -73,6 +73,7 @@ TEST_GEN_PROGS_x86_64 += memslot_modification_stress_test TEST_GEN_PROGS_x86_64 += set_memory_region_test TEST_GEN_PROGS_x86_64 += steal_time +TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list-sve TEST_GEN_PROGS_aarch64 += aarch64/vgic_init diff --git a/tools/testing/selftests/kvm/aarch64/debug-exceptions.c b/tools/testing/selftests/kvm/aarch64/debug-exceptions.c new file mode 100644 index 000000000000..18e8de2711d3 --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/debug-exceptions.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE /* for program_invocation_short_name */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define VCPU_ID 0 + +extern unsigned char sw_bp, hw_bp, bp_svc, bp_brk, hw_wp, ss_start; +static volatile uint64_t sw_bp_addr, hw_bp_addr; +static volatile uint64_t wp_addr, wp_data_addr; +static volatile uint64_t svc_addr; +static volatile uint64_t ss_addr[4], ss_idx; +#define CAST_TO_PC(v) ((uint64_t)&(v)) + +static void reset_debug_state(void) +{ + asm volatile("msr daifset, #8"); + + write_sysreg(osdlr_el1, 0); + write_sysreg(oslar_el1, 0); + asm volatile("isb" : : : "memory"); + + write_sysreg(mdscr_el1, 0); + /* This test only uses the first bp and wp slot. */ + write_sysreg(dbgbvr0_el1, 0); + write_sysreg(dbgbcr0_el1, 0); + write_sysreg(dbgwcr0_el1, 0); + write_sysreg(dbgwvr0_el1, 0); + asm volatile("isb" : : : "memory"); +} + +static void install_wp(uint64_t addr) +{ + uint32_t wcr; + uint32_t mdscr; + + wcr = DBGWCR_LEN8 | DBGWCR_RD | DBGWCR_WR | DBGWCR_EL1 | DBGWCR_E; + write_sysreg(dbgwcr0_el1, wcr); + write_sysreg(dbgwvr0_el1, addr); + asm volatile("isb" : : : "memory"); + + asm volatile("msr daifclr, #8"); + + mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE; + write_sysreg(mdscr_el1, mdscr); +} + +static void install_hw_bp(uint64_t addr) +{ + uint32_t bcr; + uint32_t mdscr; + + bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E; + write_sysreg(dbgbcr0_el1, bcr); + write_sysreg(dbgbvr0_el1, addr); + asm volatile("isb" : : : "memory"); + + asm volatile("msr daifclr, #8"); + + mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE; + write_sysreg(mdscr_el1, mdscr); +} + +static void install_ss(void) +{ + uint32_t mdscr; + + asm volatile("msr daifclr, #8"); + + mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_SS; + write_sysreg(mdscr_el1, mdscr); +} + +static volatile char write_data; + +#define GUEST_ASSERT_EQ(arg1, arg2) \ + GUEST_ASSERT_2((arg1) == (arg2), (arg1), (arg2)) + +static void guest_code(void) +{ + GUEST_SYNC(0); + + /* Software-breakpoint */ + asm volatile("sw_bp: brk #0"); + GUEST_ASSERT_EQ(sw_bp_addr, CAST_TO_PC(sw_bp)); + + GUEST_SYNC(1); + + /* Hardware-breakpoint */ + reset_debug_state(); + install_hw_bp(CAST_TO_PC(hw_bp)); + asm volatile("hw_bp: nop"); + GUEST_ASSERT_EQ(hw_bp_addr, CAST_TO_PC(hw_bp)); + + GUEST_SYNC(2); + + /* Hardware-breakpoint + svc */ + reset_debug_state(); + install_hw_bp(CAST_TO_PC(bp_svc)); + asm volatile("bp_svc: svc #0"); + GUEST_ASSERT_EQ(hw_bp_addr, CAST_TO_PC(bp_svc)); + GUEST_ASSERT_EQ(svc_addr, CAST_TO_PC(bp_svc) + 4); + + GUEST_SYNC(3); + + /* Hardware-breakpoint + software-breakpoint */ + reset_debug_state(); + install_hw_bp(CAST_TO_PC(bp_brk)); + asm volatile("bp_brk: brk #0"); + GUEST_ASSERT_EQ(sw_bp_addr, CAST_TO_PC(bp_brk)); + GUEST_ASSERT_EQ(hw_bp_addr, CAST_TO_PC(bp_brk)); + + GUEST_SYNC(4); + + /* Watchpoint */ + reset_debug_state(); + install_wp(CAST_TO_PC(write_data)); + write_data = 'x'; + GUEST_ASSERT_EQ(write_data, 'x'); + GUEST_ASSERT_EQ(wp_data_addr, CAST_TO_PC(write_data)); + + GUEST_SYNC(5); + + /* Single-step */ + reset_debug_state(); + install_ss(); + ss_idx = 0; + asm volatile("ss_start:\n" + "mrs x0, esr_el1\n" + "add x0, x0, #1\n" + "msr daifset, #8\n" + : : : "x0"); + GUEST_ASSERT_EQ(ss_addr[0], CAST_TO_PC(ss_start)); + GUEST_ASSERT_EQ(ss_addr[1], CAST_TO_PC(ss_start) + 4); + GUEST_ASSERT_EQ(ss_addr[2], CAST_TO_PC(ss_start) + 8); + + GUEST_DONE(); +} + +static void guest_sw_bp_handler(struct ex_regs *regs) +{ + sw_bp_addr = regs->pc; + regs->pc += 4; +} + +static void guest_hw_bp_handler(struct ex_regs *regs) +{ + hw_bp_addr = regs->pc; + regs->pstate |= SPSR_D; +} + +static void guest_wp_handler(struct ex_regs *regs) +{ + wp_data_addr = read_sysreg(far_el1); + wp_addr = regs->pc; + regs->pstate |= SPSR_D; +} + +static void guest_ss_handler(struct ex_regs *regs) +{ + GUEST_ASSERT_1(ss_idx < 4, ss_idx); + ss_addr[ss_idx++] = regs->pc; + regs->pstate |= SPSR_SS; +} + +static void guest_svc_handler(struct ex_regs *regs) +{ + svc_addr = regs->pc; +} + +static int debug_version(struct kvm_vm *vm) +{ + uint64_t id_aa64dfr0; + + get_reg(vm, VCPU_ID, ARM64_SYS_REG(ID_AA64DFR0_EL1), &id_aa64dfr0); + return id_aa64dfr0 & 0xf; +} + +int main(int argc, char *argv[]) +{ + struct kvm_vm *vm; + struct ucall uc; + int stage; + int ret; + + vm = vm_create_default(VCPU_ID, 0, guest_code); + ucall_init(vm, NULL); + + vm_init_descriptor_tables(vm); + vcpu_init_descriptor_tables(vm, VCPU_ID); + + if (debug_version(vm) < 6) { + print_skip("Armv8 debug architecture not supported."); + kvm_vm_free(vm); + exit(KSFT_SKIP); + } + + vm_handle_exception(vm, VECTOR_SYNC_EL1, + ESR_EC_BRK_INS, guest_sw_bp_handler); + vm_handle_exception(vm, VECTOR_SYNC_EL1, + ESR_EC_HW_BP_EL1, guest_hw_bp_handler); + vm_handle_exception(vm, VECTOR_SYNC_EL1, + ESR_EC_WP_EL1, guest_wp_handler); + vm_handle_exception(vm, VECTOR_SYNC_EL1, + ESR_EC_SSTEP_EL1, guest_ss_handler); + vm_handle_exception(vm, VECTOR_SYNC_EL1, + ESR_EC_SVC64, guest_svc_handler); + + for (stage = 0; stage < 7; stage++) { + ret = _vcpu_run(vm, VCPU_ID); + + TEST_ASSERT(ret == 0, "vcpu_run failed: %d\n", ret); + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_SYNC: + TEST_ASSERT(uc.args[1] == stage, + "Stage %d: Unexpected sync ucall, got %lx", + stage, (ulong)uc.args[1]); + + break; + case UCALL_ABORT: + TEST_FAIL("%s at %s:%ld\n\tvalues: %#lx, %#lx", + (const char *)uc.args[0], + __FILE__, uc.args[1], uc.args[2], uc.args[3]); + break; + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } + +done: + kvm_vm_free(vm); + return 0; +} diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h index 5c902ad95c35..eee69b92e01e 100644 --- a/tools/testing/selftests/kvm/include/aarch64/processor.h +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h @@ -21,6 +21,8 @@ #define SCTLR_EL1 3, 0, 1, 0, 0 #define VBAR_EL1 3, 0, 12, 0, 0 +#define ID_AA64DFR0_EL1 3, 0, 0, 5, 0 + /* * Default MAIR * index attribute @@ -125,4 +127,19 @@ void vm_handle_exception(struct kvm_vm *vm, int vector, int ec, val; \ }) +#define MDSCR_KDE (1 << 13) +#define MDSCR_MDE (1 << 15) +#define MDSCR_SS (1 << 0) + +#define DBGBCR_LEN8 (0xff << 5) +#define DBGBCR_EXEC (0x0 << 3) +#define DBGBCR_EL1 (0x1 << 1) +#define DBGBCR_E (0x1 << 0) + +#define DBGWCR_LEN8 (0xff << 5) +#define DBGWCR_RD (0x1 << 3) +#define DBGWCR_WR (0x2 << 3) +#define DBGWCR_EL1 (0x1 << 1) +#define DBGWCR_E (0x1 << 0) + #endif /* SELFTEST_KVM_PROCESSOR_H */ From patchwork Fri Apr 23 04:03:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Koller X-Patchwork-Id: 12219533 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5AEACC43462 for ; Fri, 23 Apr 2021 04:04:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3C80E61452 for ; Fri, 23 Apr 2021 04:04:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232124AbhDWEEm (ORCPT ); Fri, 23 Apr 2021 00:04:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46090 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230437AbhDWEEl (ORCPT ); Fri, 23 Apr 2021 00:04:41 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 63E78C061574 for ; Thu, 22 Apr 2021 21:04:05 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id o187-20020a2528c40000b02904e567b4bf7eso22784371ybo.10 for ; Thu, 22 Apr 2021 21:04:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=pLr79XnV8jmiBhfuyZ12keZz7+PeIzV/RdJo7lz5a20=; b=TDeHItoYGUinQ5QfVFpTL9KILDA55Eqn4P65h4cPvtOkm4/Hmqrls8C4Slk0v6F4IT NqJ9cYJ2KSsFs1KHdlBIPWaV8rmRK4hrMa6Y/a1MYl7ey3n9kLbbbTM0q1nTAmx4ScLs bIdv46WvetYgzKQ4j7cVx4LDhLZZ0lGm2vypeBBIXERpx31lAA7DitsO3LB+IehHp2Fb CLp8sB8rxT38ZjW5CwKCZ1azBOXZ3YrFckKxETy1NBIheZJPE2zsEZGQM18srrJ1yF6F Z3Akj1ATZnFuOu7DXPqdyAeuxC636MRHtXxDfsv5LnAKcA1PibKrADuGZwSbdH5hWb+v 5r1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=pLr79XnV8jmiBhfuyZ12keZz7+PeIzV/RdJo7lz5a20=; b=lXMO/ZJ8NV86aPJYJeS/jOiJpdO2SCzaJ+Jx9dC+twwtENMbqW3n7xU0vcF2eUDIoB GgpIZEX54ypQ4NaMDu0xe8n3vlEGABv91wRUl917kMwEu0WFBllK88oomw2/8q64Qr5u fyUx859GCG3Oehp2eNuYFs3gcNY2q4G/BdyvBPJFl7y1bWVCnkGZR3jc7x8IkjGKAVA7 NQeP2j2OAddfh4/G469JGD/zEQgXUvEA8RWcngM6DHdNIPqOpmox2LhVY0RI/SPt9w9V Rk3JMsiB2UO7Z5jf4surazmhIM8cd5om02A5wju3+JiXdKRo5/F0czrFIBNbvEvkJp7U oUeg== X-Gm-Message-State: AOAM533bUmDK131rzRzybnuUuBG4v3bi/SSIP7Z442jXRLRbNPx9DO9F 23ioIC7fF8EgYKQmUr+urb5lt71X3LclAcRdFCDdWbpqI5b10OCIqzI9df6W03kVyErhOO7s9VK HpP6AlE4sEq3/FiJi1oOB8Lk9R+JzcSRnlsbFJSnynwWFKdgy7q4p5f/ZK4J/mR8= X-Google-Smtp-Source: ABdhPJzhqbqtTQPQkUA/D6mJDIS4i1hcyAOurGPF5ymBCTAppBaYCTEgyxXu+iOrn6eJPsYb2pQgCNtory3+JQ== X-Received: from ricarkol2.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:62fe]) (user=ricarkol job=sendgmr) by 2002:a25:bad0:: with SMTP id a16mr2733788ybk.441.1619150644548; Thu, 22 Apr 2021 21:04:04 -0700 (PDT) Date: Thu, 22 Apr 2021 21:03:51 -0700 In-Reply-To: <20210423040351.1132218-1-ricarkol@google.com> Message-Id: <20210423040351.1132218-4-ricarkol@google.com> Mime-Version: 1.0 References: <20210423040351.1132218-1-ricarkol@google.com> X-Mailer: git-send-email 2.31.1.498.g6c1eba8ee3d-goog Subject: [PATCH 3/3] KVM: selftests: Use a ucall for x86 unhandled vector reporting From: Ricardo Koller To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: pbonzini@redhat.com, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com, eric.auger@redhat.com, Ricardo Koller Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org x86 reports unhandled vectors using port IO at a specific port number, which is replicating what ucall already does for x86. Aarch64, on the other hand, reports unhandled vector exceptions with a ucall using a recently added UCALL_UNHANDLED ucall type. Replace the x86 unhandled vector exception handling to use ucall UCALL_UNHANDLED instead of port IO. Tested: Forcing a page fault in the ./x86_64/xapic_ipi_test halter_guest_code() shows this: $ ./x86_64/xapic_ipi_test ... Unexpected vectored event in guest (vector:0xe) Signed-off-by: Ricardo Koller --- .../selftests/kvm/include/x86_64/processor.h | 2 -- .../testing/selftests/kvm/lib/x86_64/processor.c | 15 ++++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 0b30b4e15c38..379f12cbdc06 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -53,8 +53,6 @@ #define CPUID_PKU (1ul << 3) #define CPUID_LA57 (1ul << 16) -#define UNEXPECTED_VECTOR_PORT 0xfff0u - /* General Registers in 64-Bit Mode */ struct gpr64_regs { u64 rax; diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index a8906e60a108..284d26a25cd3 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1207,7 +1207,7 @@ static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr, void kvm_exit_unexpected_vector(uint32_t value) { - outl(UNEXPECTED_VECTOR_PORT, value); + ucall(UCALL_UNHANDLED, 1, value); } void route_exception(struct ex_regs *regs) @@ -1260,16 +1260,13 @@ void vm_handle_exception(struct kvm_vm *vm, int vector, void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid) { - if (vcpu_state(vm, vcpuid)->exit_reason == KVM_EXIT_IO - && vcpu_state(vm, vcpuid)->io.port == UNEXPECTED_VECTOR_PORT - && vcpu_state(vm, vcpuid)->io.size == 4) { - /* Grab pointer to io data */ - uint32_t *data = (void *)vcpu_state(vm, vcpuid) - + vcpu_state(vm, vcpuid)->io.data_offset; + struct ucall uc; + if (get_ucall(vm, vcpuid, &uc) == UCALL_UNHANDLED) { + uint64_t vector = uc.args[0]; TEST_ASSERT(false, - "Unexpected vectored event in guest (vector:0x%x)", - *data); + "Unexpected vectored event in guest (vector:0x%lx)", + vector); } }