Skip to content

Commit 54e4332

Browse files
committed
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: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent e290dbb commit 54e4332

File tree

9 files changed

+255
-6
lines changed

9 files changed

+255
-6
lines changed

Diff for: arch/riscv/include/asm/hwcap.h

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
#define RISCV_ISA_EXT_MAX 64
4949
#define RISCV_ISA_EXT_NAME_LEN_MAX 32
5050

51+
#ifdef CONFIG_RISCV_M_MODE
52+
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA
53+
#else
54+
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA
55+
#endif
56+
5157
#ifndef __ASSEMBLY__
5258

5359
#include <linux/jump_label.h>

Diff for: arch/riscv/include/asm/kvm_aia.h

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2021 Western Digital Corporation or its affiliates.
4+
* Copyright (C) 2022 Ventana Micro Systems Inc.
5+
*
6+
* Authors:
7+
* Anup Patel <apatel@ventanamicro.com>
8+
*/
9+
10+
#ifndef __KVM_RISCV_AIA_H
11+
#define __KVM_RISCV_AIA_H
12+
13+
#include <linux/jump_label.h>
14+
#include <linux/kvm_types.h>
15+
16+
struct kvm_aia {
17+
/* In-kernel irqchip created */
18+
bool in_kernel;
19+
20+
/* In-kernel irqchip initialized */
21+
bool initialized;
22+
};
23+
24+
struct kvm_vcpu_aia {
25+
};
26+
27+
#define kvm_riscv_aia_initialized(k) ((k)->arch.aia.initialized)
28+
29+
#define irqchip_in_kernel(k) ((k)->arch.aia.in_kernel)
30+
31+
DECLARE_STATIC_KEY_FALSE(kvm_riscv_aia_available);
32+
#define kvm_riscv_aia_available() \
33+
static_branch_unlikely(&kvm_riscv_aia_available)
34+
35+
static inline void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
36+
{
37+
}
38+
39+
static inline void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
40+
{
41+
}
42+
43+
static inline bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu,
44+
u64 mask)
45+
{
46+
return false;
47+
}
48+
49+
static inline void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu)
50+
{
51+
}
52+
53+
static inline void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu)
54+
{
55+
}
56+
57+
static inline void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu)
58+
{
59+
}
60+
61+
static inline int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
62+
unsigned long reg_num,
63+
unsigned long *out_val)
64+
{
65+
*out_val = 0;
66+
return 0;
67+
}
68+
69+
static inline int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
70+
unsigned long reg_num,
71+
unsigned long val)
72+
{
73+
return 0;
74+
}
75+
76+
#define KVM_RISCV_VCPU_AIA_CSR_FUNCS
77+
78+
static inline int kvm_riscv_vcpu_aia_update(struct kvm_vcpu *vcpu)
79+
{
80+
return 1;
81+
}
82+
83+
static inline void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu)
84+
{
85+
}
86+
87+
static inline int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu)
88+
{
89+
return 0;
90+
}
91+
92+
static inline void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu)
93+
{
94+
}
95+
96+
static inline void kvm_riscv_aia_init_vm(struct kvm *kvm)
97+
{
98+
}
99+
100+
static inline void kvm_riscv_aia_destroy_vm(struct kvm *kvm)
101+
{
102+
}
103+
104+
void kvm_riscv_aia_enable(void);
105+
void kvm_riscv_aia_disable(void);
106+
int kvm_riscv_aia_init(void);
107+
void kvm_riscv_aia_exit(void);
108+
109+
#endif

Diff for: arch/riscv/include/asm/kvm_host.h

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/kvm_types.h>
1515
#include <linux/spinlock.h>
1616
#include <asm/hwcap.h>
17+
#include <asm/kvm_aia.h>
1718
#include <asm/kvm_vcpu_fp.h>
1819
#include <asm/kvm_vcpu_insn.h>
1920
#include <asm/kvm_vcpu_sbi.h>
@@ -94,6 +95,9 @@ struct kvm_arch {
9495

9596
/* Guest Timer */
9697
struct kvm_guest_timer timer;
98+
99+
/* AIA Guest/VM context */
100+
struct kvm_aia aia;
97101
};
98102

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

228+
/* AIA VCPU context */
229+
struct kvm_vcpu_aia aia_context;
230+
224231
/* Cache pages needed to program page tables with spinlock held */
225232
struct kvm_mmu_memory_cache mmu_page_cache;
226233

Diff for: arch/riscv/kvm/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ kvm-y += vcpu_sbi_replace.o
2626
kvm-y += vcpu_sbi_hsm.o
2727
kvm-y += vcpu_timer.o
2828
kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o vcpu_sbi_pmu.o
29+
kvm-y += aia.o

Diff for: arch/riscv/kvm/aia.c

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2021 Western Digital Corporation or its affiliates.
4+
* Copyright (C) 2022 Ventana Micro Systems Inc.
5+
*
6+
* Authors:
7+
* Anup Patel <apatel@ventanamicro.com>
8+
*/
9+
10+
#include <linux/kvm_host.h>
11+
#include <asm/hwcap.h>
12+
13+
DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available);
14+
15+
static void aia_set_hvictl(bool ext_irq_pending)
16+
{
17+
unsigned long hvictl;
18+
19+
/*
20+
* HVICTL.IID == 9 and HVICTL.IPRIO == 0 represents
21+
* no interrupt in HVICTL.
22+
*/
23+
24+
hvictl = (IRQ_S_EXT << HVICTL_IID_SHIFT) & HVICTL_IID;
25+
hvictl |= ext_irq_pending;
26+
csr_write(CSR_HVICTL, hvictl);
27+
}
28+
29+
void kvm_riscv_aia_enable(void)
30+
{
31+
if (!kvm_riscv_aia_available())
32+
return;
33+
34+
aia_set_hvictl(false);
35+
csr_write(CSR_HVIPRIO1, 0x0);
36+
csr_write(CSR_HVIPRIO2, 0x0);
37+
#ifdef CONFIG_32BIT
38+
csr_write(CSR_HVIPH, 0x0);
39+
csr_write(CSR_HIDELEGH, 0x0);
40+
csr_write(CSR_HVIPRIO1H, 0x0);
41+
csr_write(CSR_HVIPRIO2H, 0x0);
42+
#endif
43+
}
44+
45+
void kvm_riscv_aia_disable(void)
46+
{
47+
if (!kvm_riscv_aia_available())
48+
return;
49+
50+
aia_set_hvictl(false);
51+
}
52+
53+
int kvm_riscv_aia_init(void)
54+
{
55+
if (!riscv_isa_extension_available(NULL, SxAIA))
56+
return -ENODEV;
57+
58+
/* Enable KVM AIA support */
59+
static_branch_enable(&kvm_riscv_aia_available);
60+
61+
return 0;
62+
}
63+
64+
void kvm_riscv_aia_exit(void)
65+
{
66+
}

Diff for: arch/riscv/kvm/main.c

+21-1
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,15 @@ int kvm_arch_hardware_enable(void)
4444

4545
csr_write(CSR_HVIP, 0);
4646

47+
kvm_riscv_aia_enable();
48+
4749
return 0;
4850
}
4951

5052
void kvm_arch_hardware_disable(void)
5153
{
54+
kvm_riscv_aia_disable();
55+
5256
/*
5357
* After clearing the hideleg CSR, the host kernel will receive
5458
* spurious interrupts if hvip CSR has pending interrupts and the
@@ -63,6 +67,7 @@ void kvm_arch_hardware_disable(void)
6367

6468
static int __init riscv_kvm_init(void)
6569
{
70+
int rc;
6671
const char *str;
6772

6873
if (!riscv_isa_extension_available(NULL, h)) {
@@ -84,6 +89,10 @@ static int __init riscv_kvm_init(void)
8489

8590
kvm_riscv_gstage_vmid_detect();
8691

92+
rc = kvm_riscv_aia_init();
93+
if (rc && rc != -ENODEV)
94+
return rc;
95+
8796
kvm_info("hypervisor extension available\n");
8897

8998
switch (kvm_riscv_gstage_mode()) {
@@ -106,12 +115,23 @@ static int __init riscv_kvm_init(void)
106115

107116
kvm_info("VMID %ld bits available\n", kvm_riscv_gstage_vmid_bits());
108117

109-
return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
118+
if (kvm_riscv_aia_available())
119+
kvm_info("AIA available\n");
120+
121+
rc = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
122+
if (rc) {
123+
kvm_riscv_aia_exit();
124+
return rc;
125+
}
126+
127+
return 0;
110128
}
111129
module_init(riscv_kvm_init);
112130

113131
static void __exit riscv_kvm_exit(void)
114132
{
133+
kvm_riscv_aia_exit();
134+
115135
kvm_exit();
116136
}
117137
module_exit(riscv_kvm_exit);

0 commit comments

Comments
 (0)