From nobody Sun Sep 14 01:58:55 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CF91C77B60 for ; Tue, 4 Apr 2023 15:35:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235786AbjDDPfz (ORCPT ); Tue, 4 Apr 2023 11:35:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52820 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235693AbjDDPfm (ORCPT ); Tue, 4 Apr 2023 11:35:42 -0400 Received: from mail-oi1-x22b.google.com (mail-oi1-x22b.google.com [IPv6:2607:f8b0:4864:20::22b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6CE04EDD for ; Tue, 4 Apr 2023 08:35:34 -0700 (PDT) Received: by mail-oi1-x22b.google.com with SMTP id bj20so24502225oib.3 for ; Tue, 04 Apr 2023 08:35:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1680622534; x=1683214534; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JGqXgeLBfRULoc6Z9dXAtLsyGFp5MekVqLdi5gc3SgU=; b=jI42tPQLeUmZlwK6PsLhRfaSzTriB9N+nf55oNLD697PTgXR77FeLARXuX9SN7kdrU nQYtkgAUGmRUX9COqm1ktt+HdcAcpQlgVX9Ku0gO9pCnx2KQfWuDI4L+7UTnQaJCfiSt cy9ebwS82z9ZCafWmoKu571GCF1Sy3xM0ow0gqUubIve8/iM7MX08ChGJS+5m8sTS82u 7D9Bor70TptTJ5fY68I4/b7W2Es9i8jbFxyu/1mkW1J5MPqCOTzS+kF47pfKtiMHJsSY LoSCjdVajG1SEYK/W5pCAqzM6/u9YBTJbF0sMQUnmSaDiJ/mWCQVwirVcy30Fsv7E2+S cx8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680622534; x=1683214534; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JGqXgeLBfRULoc6Z9dXAtLsyGFp5MekVqLdi5gc3SgU=; b=B+Kc4mN7HDK4pU+c8wfE+uPFrBrqnAvbD3RKQ584bvYuL2yNCtiv4w1uh67S1MuWtQ m0n7s/eHDKYS/0laa8bBuv4qiRHvOLpTfQV/ianu103QsIZZcYQcQ1E7ndGrA4HFrg2+ CjE4Y0O/bsX1Fa66hieLeVhDyWgoIW9rM8KDxspYQQIE/Nr9/qiP25vMqK0Hy5UhG57Y LQ4Zn1Q6JMrxx3d4r+7EGY9ca1aTllmmqVal86Zu6htQlg6aeoz8ieDMh/Hz2WmaZDYO lua/MGUXRlSMwxmSkHb7wM2xLDUvus0UKY+H7QEn7hPHcFatWSGrjBESA7W5P6SuF4Kx TYEw== X-Gm-Message-State: AAQBX9cOgl8/G1YgWuFCo1Bwa5JnodPM6vwqkcI8YEg2ph+ktJ8bVxq4 jEO4rhsVLZA0gOz/CjixOMviNA== X-Google-Smtp-Source: AKy350YvJSZXA10zkuRwQm02Icu8XPEUX1t9l/vHGGxYzHqcesxtcTOj8IR+6d8gBkb9dBfJMqSzjQ== X-Received: by 2002:a54:488a:0:b0:387:210a:6f47 with SMTP id r10-20020a54488a000000b00387210a6f47mr1703552oic.21.1680622534124; Tue, 04 Apr 2023 08:35:34 -0700 (PDT) Received: from anup-ubuntu-vm.localdomain ([103.97.165.210]) by smtp.gmail.com with ESMTPSA id w124-20020acadf82000000b00387384dc768sm5325803oig.9.2023.04.04.08.35.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 04 Apr 2023 08:35:33 -0700 (PDT) From: Anup Patel To: Paolo Bonzini , Atish Patra Cc: Palmer Dabbelt , Paul Walmsley , Andrew Jones , Anup Patel , kvm@vger.kernel.org, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Anup Patel , Atish Patra Subject: [PATCH v4 4/9] RISC-V: KVM: Initial skeletal support for AIA Date: Tue, 4 Apr 2023 21:04:47 +0530 Message-Id: <20230404153452.2405681-5-apatel@ventanamicro.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230404153452.2405681-1-apatel@ventanamicro.com> References: <20230404153452.2405681-1-apatel@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" To incrementally implement AIA support, we first add minimal skeletal support which only compiles and detects AIA hardware support at the boot-time but does not provide any functionality. Signed-off-by: Anup Patel Reviewed-by: Atish Patra Reviewed-by: Andrew Jones --- arch/riscv/include/asm/hwcap.h | 6 ++ arch/riscv/include/asm/kvm_aia.h | 109 ++++++++++++++++++++++++++++++ arch/riscv/include/asm/kvm_host.h | 7 ++ arch/riscv/kvm/Makefile | 1 + arch/riscv/kvm/aia.c | 66 ++++++++++++++++++ arch/riscv/kvm/main.c | 22 +++++- arch/riscv/kvm/vcpu.c | 45 ++++++++++-- arch/riscv/kvm/vcpu_insn.c | 1 + arch/riscv/kvm/vm.c | 4 ++ 9 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 arch/riscv/include/asm/kvm_aia.h create mode 100644 arch/riscv/kvm/aia.c diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 74f5dab2148f..ab2abf561520 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -48,6 +48,12 @@ #define RISCV_ISA_EXT_MAX 64 #define RISCV_ISA_EXT_NAME_LEN_MAX 32 =20 +#ifdef CONFIG_RISCV_M_MODE +#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA +#else +#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA +#endif + #ifndef __ASSEMBLY__ =20 #include diff --git a/arch/riscv/include/asm/kvm_aia.h b/arch/riscv/include/asm/kvm_= aia.h new file mode 100644 index 000000000000..258a835d4c32 --- /dev/null +++ b/arch/riscv/include/asm/kvm_aia.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#ifndef __KVM_RISCV_AIA_H +#define __KVM_RISCV_AIA_H + +#include +#include + +struct kvm_aia { + /* In-kernel irqchip created */ + bool in_kernel; + + /* In-kernel irqchip initialized */ + bool initialized; +}; + +struct kvm_vcpu_aia { +}; + +#define kvm_riscv_aia_initialized(k) ((k)->arch.aia.initialized) + +#define irqchip_in_kernel(k) ((k)->arch.aia.in_kernel) + +DECLARE_STATIC_KEY_FALSE(kvm_riscv_aia_available); +#define kvm_riscv_aia_available() \ + static_branch_unlikely(&kvm_riscv_aia_available) + +static inline void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vc= pu) +{ +} + +static inline void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcp= u) +{ +} + +static inline bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, + u64 mask) +{ + return false; +} + +static inline void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu) +{ +} + +static inline void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu) +{ +} + +static inline void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu) +{ +} + +static inline int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu, + unsigned long reg_num, + unsigned long *out_val) +{ + *out_val =3D 0; + return 0; +} + +static inline int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu, + unsigned long reg_num, + unsigned long val) +{ + return 0; +} + +#define KVM_RISCV_VCPU_AIA_CSR_FUNCS + +static inline int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu) +{ + return 1; +} + +static inline void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu) +{ +} + +static inline int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu) +{ + return 0; +} + +static inline void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu) +{ +} + +static inline void kvm_riscv_aia_init_vm(struct kvm *kvm) +{ +} + +static inline void kvm_riscv_aia_destroy_vm(struct kvm *kvm) +{ +} + +void kvm_riscv_aia_enable(void); +void kvm_riscv_aia_disable(void); +int kvm_riscv_aia_init(void); +void kvm_riscv_aia_exit(void); + +#endif diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm= _host.h index cc7da66ee0c0..3157cf748df1 100644 --- a/arch/riscv/include/asm/kvm_host.h +++ b/arch/riscv/include/asm/kvm_host.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,9 @@ struct kvm_arch { =20 /* Guest Timer */ struct kvm_guest_timer timer; + + /* AIA Guest/VM context */ + struct kvm_aia aia; }; =20 struct kvm_cpu_trap { @@ -221,6 +225,9 @@ struct kvm_vcpu_arch { /* SBI context */ struct kvm_vcpu_sbi_context sbi_context; =20 + /* AIA VCPU context */ + struct kvm_vcpu_aia aia_context; + /* Cache pages needed to program page tables with spinlock held */ struct kvm_mmu_memory_cache mmu_page_cache; =20 diff --git a/arch/riscv/kvm/Makefile b/arch/riscv/kvm/Makefile index 278e97c06e0a..8031b8912a0d 100644 --- a/arch/riscv/kvm/Makefile +++ b/arch/riscv/kvm/Makefile @@ -26,3 +26,4 @@ kvm-y +=3D vcpu_sbi_replace.o kvm-y +=3D vcpu_sbi_hsm.o kvm-y +=3D vcpu_timer.o kvm-$(CONFIG_RISCV_PMU_SBI) +=3D vcpu_pmu.o vcpu_sbi_pmu.o +kvm-y +=3D aia.o diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c new file mode 100644 index 000000000000..7a633331cd3e --- /dev/null +++ b/arch/riscv/kvm/aia.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + * Copyright (C) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#include +#include + +DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available); + +static void aia_set_hvictl(bool ext_irq_pending) +{ + unsigned long hvictl; + + /* + * HVICTL.IID =3D=3D 9 and HVICTL.IPRIO =3D=3D 0 represents + * no interrupt in HVICTL. + */ + + hvictl =3D (IRQ_S_EXT << HVICTL_IID_SHIFT) & HVICTL_IID; + hvictl |=3D ext_irq_pending; + csr_write(CSR_HVICTL, hvictl); +} + +void kvm_riscv_aia_enable(void) +{ + if (!kvm_riscv_aia_available()) + return; + + aia_set_hvictl(false); + csr_write(CSR_HVIPRIO1, 0x0); + csr_write(CSR_HVIPRIO2, 0x0); +#ifdef CONFIG_32BIT + csr_write(CSR_HVIPH, 0x0); + csr_write(CSR_HIDELEGH, 0x0); + csr_write(CSR_HVIPRIO1H, 0x0); + csr_write(CSR_HVIPRIO2H, 0x0); +#endif +} + +void kvm_riscv_aia_disable(void) +{ + if (!kvm_riscv_aia_available()) + return; + + aia_set_hvictl(false); +} + +int kvm_riscv_aia_init(void) +{ + if (!riscv_isa_extension_available(NULL, SxAIA)) + return -ENODEV; + + /* Enable KVM AIA support */ + static_branch_enable(&kvm_riscv_aia_available); + + return 0; +} + +void kvm_riscv_aia_exit(void) +{ +} diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c index 41ad7639a17b..6396352b4e4d 100644 --- a/arch/riscv/kvm/main.c +++ b/arch/riscv/kvm/main.c @@ -44,11 +44,15 @@ int kvm_arch_hardware_enable(void) =20 csr_write(CSR_HVIP, 0); =20 + kvm_riscv_aia_enable(); + return 0; } =20 void kvm_arch_hardware_disable(void) { + kvm_riscv_aia_disable(); + /* * After clearing the hideleg CSR, the host kernel will receive * spurious interrupts if hvip CSR has pending interrupts and the @@ -63,6 +67,7 @@ void kvm_arch_hardware_disable(void) =20 static int __init riscv_kvm_init(void) { + int rc; const char *str; =20 if (!riscv_isa_extension_available(NULL, h)) { @@ -84,6 +89,10 @@ static int __init riscv_kvm_init(void) =20 kvm_riscv_gstage_vmid_detect(); =20 + rc =3D kvm_riscv_aia_init(); + if (rc && rc !=3D -ENODEV) + return rc; + kvm_info("hypervisor extension available\n"); =20 switch (kvm_riscv_gstage_mode()) { @@ -106,12 +115,23 @@ static int __init riscv_kvm_init(void) =20 kvm_info("VMID %ld bits available\n", kvm_riscv_gstage_vmid_bits()); =20 - return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); + if (kvm_riscv_aia_available()) + kvm_info("AIA available\n"); + + rc =3D kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); + if (rc) { + kvm_riscv_aia_exit(); + return rc; + } + + return 0; } module_init(riscv_kvm_init); =20 static void __exit riscv_kvm_exit(void) { + kvm_riscv_aia_exit(); + kvm_exit(); } module_exit(riscv_kvm_exit); diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c index 02b49cb94561..b46e9cc92938 100644 --- a/arch/riscv/kvm/vcpu.c +++ b/arch/riscv/kvm/vcpu.c @@ -137,6 +137,8 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu) =20 kvm_riscv_vcpu_timer_reset(vcpu); =20 + kvm_riscv_vcpu_aia_reset(vcpu); + WRITE_ONCE(vcpu->arch.irqs_pending, 0); WRITE_ONCE(vcpu->arch.irqs_pending_mask, 0); =20 @@ -159,6 +161,7 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned i= nt id) =20 int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) { + int rc; struct kvm_cpu_context *cntx; struct kvm_vcpu_csr *reset_csr =3D &vcpu->arch.guest_reset_csr; unsigned long host_isa, i; @@ -201,6 +204,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) /* setup performance monitoring */ kvm_riscv_vcpu_pmu_init(vcpu); =20 + /* Setup VCPU AIA */ + rc =3D kvm_riscv_vcpu_aia_init(vcpu); + if (rc) + return rc; + /* Reset VCPU */ kvm_riscv_reset_vcpu(vcpu); =20 @@ -220,6 +228,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) =20 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) { + /* Cleanup VCPU AIA context */ + kvm_riscv_vcpu_aia_deinit(vcpu); + /* Cleanup VCPU timer */ kvm_riscv_vcpu_timer_deinit(vcpu); =20 @@ -741,6 +752,9 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *v= cpu) csr->hvip &=3D ~mask; csr->hvip |=3D val; } + + /* Flush AIA high interrupts */ + kvm_riscv_vcpu_aia_flush_interrupts(vcpu); } =20 void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu) @@ -766,6 +780,9 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vc= pu) } } =20 + /* Sync-up AIA high interrupts */ + kvm_riscv_vcpu_aia_sync_interrupts(vcpu); + /* Sync-up timer CSRs */ kvm_riscv_vcpu_timer_sync(vcpu); } @@ -802,10 +819,15 @@ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *v= cpu, unsigned int irq) =20 bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, unsigned long ma= sk) { - unsigned long ie =3D ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK) - << VSIP_TO_HVIP_SHIFT) & mask; + unsigned long ie; + + ie =3D ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK) + << VSIP_TO_HVIP_SHIFT) & mask; + if (READ_ONCE(vcpu->arch.irqs_pending) & ie) + return true; =20 - return (READ_ONCE(vcpu->arch.irqs_pending) & ie) ? true : false; + /* Check AIA high interrupts */ + return kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask); } =20 void kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu) @@ -901,6 +923,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) kvm_riscv_vcpu_guest_fp_restore(&vcpu->arch.guest_context, vcpu->arch.isa); =20 + kvm_riscv_vcpu_aia_load(vcpu, cpu); + vcpu->cpu =3D cpu; } =20 @@ -910,6 +934,8 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) =20 vcpu->cpu =3D -1; =20 + kvm_riscv_vcpu_aia_put(vcpu); + kvm_riscv_vcpu_guest_fp_save(&vcpu->arch.guest_context, vcpu->arch.isa); kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context); @@ -977,6 +1003,7 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcp= u) struct kvm_vcpu_csr *csr =3D &vcpu->arch.guest_csr; =20 csr_write(CSR_HVIP, csr->hvip); + kvm_riscv_vcpu_aia_update_hvip(vcpu); } =20 /* @@ -1049,6 +1076,15 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) =20 kvm_riscv_check_vcpu_requests(vcpu); =20 + preempt_disable(); + + /* Update AIA HW state before entering guest */ + ret =3D kvm_riscv_vcpu_aia_update(vcpu); + if (ret <=3D 0) { + preempt_enable(); + continue; + } + local_irq_disable(); =20 /* @@ -1077,6 +1113,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) xfer_to_guest_mode_work_pending()) { vcpu->mode =3D OUTSIDE_GUEST_MODE; local_irq_enable(); + preempt_enable(); kvm_vcpu_srcu_read_lock(vcpu); continue; } @@ -1110,8 +1147,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) /* Syncup interrupts state with HW */ kvm_riscv_vcpu_sync_interrupts(vcpu); =20 - preempt_disable(); - /* * We must ensure that any pending interrupts are taken before * we exit guest timing so that timer ticks are accounted as diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c index f689337b78ff..7a6abed41bc1 100644 --- a/arch/riscv/kvm/vcpu_insn.c +++ b/arch/riscv/kvm/vcpu_insn.c @@ -214,6 +214,7 @@ struct csr_func { }; =20 static const struct csr_func csr_funcs[] =3D { + KVM_RISCV_VCPU_AIA_CSR_FUNCS KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS }; =20 diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c index 65a964d7e70d..bc03d2ddcb51 100644 --- a/arch/riscv/kvm/vm.c +++ b/arch/riscv/kvm/vm.c @@ -41,6 +41,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) return r; } =20 + kvm_riscv_aia_init_vm(kvm); + kvm_riscv_guest_timer_init(kvm); =20 return 0; @@ -49,6 +51,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) void kvm_arch_destroy_vm(struct kvm *kvm) { kvm_destroy_vcpus(kvm); + + kvm_riscv_aia_destroy_vm(kvm); } =20 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) --=20 2.34.1