Commit 54e43320 authored by Anup Patel's avatar Anup Patel Committed by Anup Patel
Browse files

RISC-V: KVM: Initial skeletal support for AIA



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: default avatarAnup Patel <apatel@ventanamicro.com>
Reviewed-by: default avatarAtish Patra <atishp@rivosinc.com>
Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Signed-off-by: default avatarAnup Patel <anup@brainfault.org>
parent e290dbb7
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -48,6 +48,12 @@
#define RISCV_ISA_EXT_MAX		64
#define RISCV_ISA_EXT_NAME_LEN_MAX	32

#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__

#include <linux/jump_label.h>
+109 −0
Original line number Diff line number Diff line
/* 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 <apatel@ventanamicro.com>
 */

#ifndef __KVM_RISCV_AIA_H
#define __KVM_RISCV_AIA_H

#include <linux/jump_label.h>
#include <linux/kvm_types.h>

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 *vcpu)
{
}

static inline void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
{
}

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 = 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
+7 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/kvm_types.h>
#include <linux/spinlock.h>
#include <asm/hwcap.h>
#include <asm/kvm_aia.h>
#include <asm/kvm_vcpu_fp.h>
#include <asm/kvm_vcpu_insn.h>
#include <asm/kvm_vcpu_sbi.h>
@@ -94,6 +95,9 @@ struct kvm_arch {

	/* Guest Timer */
	struct kvm_guest_timer timer;

	/* AIA Guest/VM context */
	struct kvm_aia aia;
};

struct kvm_cpu_trap {
@@ -221,6 +225,9 @@ struct kvm_vcpu_arch {
	/* SBI context */
	struct kvm_vcpu_sbi_context sbi_context;

	/* 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;

+1 −0
Original line number Diff line number Diff line
@@ -26,3 +26,4 @@ kvm-y += vcpu_sbi_replace.o
kvm-y += vcpu_sbi_hsm.o
kvm-y += vcpu_timer.o
kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o vcpu_sbi_pmu.o
kvm-y += aia.o

arch/riscv/kvm/aia.c

0 → 100644
+66 −0
Original line number Diff line number Diff line
// 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 <apatel@ventanamicro.com>
 */

#include <linux/kvm_host.h>
#include <asm/hwcap.h>

DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available);

static void aia_set_hvictl(bool ext_irq_pending)
{
	unsigned long hvictl;

	/*
	 * HVICTL.IID == 9 and HVICTL.IPRIO == 0 represents
	 * no interrupt in HVICTL.
	 */

	hvictl = (IRQ_S_EXT << HVICTL_IID_SHIFT) & HVICTL_IID;
	hvictl |= 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)
{
}
Loading