Skip to content

Commit 5aac9c6

Browse files
Xiang Chenchenyi211
authored andcommitted
downstream: kvm: hisi_virt: Probe and configure IPIV capacity on HIP12
IPIV is an virtualization extension on HIP12, which allows IPIs on guest directly sending by hardware to other vcpu stead of trapping to EL2. It will bring IPI interrupt optimization on guest. Introduce the method to detect and enable the feature, and also add a kernel command parameter "kvm-arm.ipiv_enabled" (default is 0) so that users can disable or enable the feature. The feature is based on GICv4p1. Signed-off-by: Xiang Chen <[email protected]> Signed-off-by: Jinqian Yang <[email protected]> Signed-off-by: Slim6882 <[email protected]> Signed-off-by: chenyi <[email protected]>
1 parent 96f3cf5 commit 5aac9c6

File tree

7 files changed

+103
-0
lines changed

7 files changed

+103
-0
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2647,6 +2647,9 @@
26472647
[KVM,ARM] Allow use of GICv4 for direct injection of
26482648
LPIs.
26492649

2650+
kvm-arm.ipiv_enabled=
2651+
[KVM,ARM] Allow use of HiSilicon ipiv on GICv4.1
2652+
26502653
kvm-arm.dvmbm_enabled=
26512654
[KVM,ARM] Allow use of HiSilicon DVMBM capability.
26522655
Default: 0

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,5 +1230,6 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu);
12301230
extern bool force_wfi_trap;
12311231
extern bool kvm_ncsnp_support;
12321232
extern bool kvm_dvmbm_support;
1233+
extern bool kvm_ipiv_support;
12331234

12341235
#endif /* __ARM64_KVM_HOST_H__ */

arch/arm64/kvm/arm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ bool kvm_ncsnp_support;
6464
/* Capability of DVMBM */
6565
bool kvm_dvmbm_support;
6666

67+
/* Capability of IPIV */
68+
bool kvm_ipiv_support;
6769

6870
static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
6971
DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
@@ -2654,8 +2656,13 @@ static __init int kvm_arm_init(void)
26542656
probe_hisi_cpu_type();
26552657
kvm_ncsnp_support = hisi_ncsnp_supported();
26562658
kvm_dvmbm_support = hisi_dvmbm_supported();
2659+
kvm_ipiv_support = hisi_ipiv_supported();
26572660
kvm_info("KVM ncsnp %s\n", kvm_ncsnp_support ? "enabled" : "disabled");
26582661
kvm_info("KVM dvmbm %s\n", kvm_dvmbm_support ? "enabled" : "disabled");
2662+
kvm_info("KVM ipiv %s\n", kvm_ipiv_support ? "enabled" : "disabled");
2663+
2664+
if (kvm_ipiv_support)
2665+
ipiv_gicd_init();
26592666

26602667
if (kvm_dvmbm_support)
26612668
kvm_get_pg_cfg();

arch/arm64/kvm/hisilicon/hisi_virt.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
static enum hisi_cpu_type cpu_type = UNKNOWN_HI_TYPE;
1313

1414
static bool dvmbm_enabled;
15+
static bool ipiv_enabled;
1516

1617
static const char * const hisi_cpu_type_str[] = {
1718
"Hisi1612",
@@ -157,6 +158,43 @@ static void hardware_disable_dvmbm(void *data)
157158
write_sysreg_s(val, SYS_LSUDVM_CTRL_EL2);
158159
}
159160

161+
static int __init early_ipiv_enable(char *buf)
162+
{
163+
return strtobool(buf, &ipiv_enabled);
164+
}
165+
early_param("kvm-arm.ipiv_enabled", early_ipiv_enable);
166+
167+
bool hisi_ipiv_supported(void)
168+
{
169+
if (cpu_type != HI_IP12)
170+
return false;
171+
172+
/* Determine whether IPIV is supported by the hardware */
173+
if (!(read_sysreg(aidr_el1) & AIDR_EL1_IPIV_MASK)) {
174+
kvm_info("Hisi ipiv not supported by the hardware\n");
175+
return false;
176+
}
177+
178+
/* User provided kernel command-line parameter */
179+
if (!ipiv_enabled || !is_kernel_in_hyp_mode())
180+
return false;
181+
182+
/* Enable IPIV feature if necessary */
183+
if (!is_gicv4p1()) {
184+
kvm_info("Hisi ipiv needs to enable GICv4p1!\n");
185+
return false;
186+
}
187+
188+
kvm_info("Enable Hisi ipiv, do not support vSGI broadcast\n");
189+
return true;
190+
}
191+
192+
void ipiv_gicd_init(void)
193+
{
194+
gic_dist_enable_ipiv();
195+
}
196+
197+
160198
bool hisi_dvmbm_supported(void)
161199
{
162200
if (cpu_type != HI_IP10 && cpu_type != HI_IP10C &&

arch/arm64/kvm/hisilicon/hisi_virt.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ enum hisi_cpu_type {
1818
UNKNOWN_HI_TYPE
1919
};
2020

21+
/* HIP12 */
22+
#define AIDR_EL1_IPIV_MASK GENMASK_ULL(17, 16)
2123
/* HIP10 */
2224
#define AIDR_EL1_DVMBM_MASK GENMASK_ULL(13, 12)
2325
#define SYS_LSUDVM_CTRL_EL2 sys_reg(3, 4, 15, 7, 4)
@@ -75,7 +77,9 @@ enum hisi_cpu_type {
7577
void probe_hisi_cpu_type(void);
7678
bool hisi_ncsnp_supported(void);
7779
bool hisi_dvmbm_supported(void);
80+
bool hisi_ipiv_supported(void);
7881
void kvm_get_pg_cfg(void);
82+
void ipiv_gicd_init(void);
7983

8084
int kvm_sched_affinity_vcpu_init(struct kvm_vcpu *vcpu);
8185
void kvm_sched_affinity_vcpu_destroy(struct kvm_vcpu *vcpu);
@@ -96,11 +100,17 @@ static inline bool hisi_dvmbm_supported(void)
96100
}
97101
static inline void kvm_get_pg_cfg(void) {}
98102

103+
static inline bool hisi_ipiv_supported(void)
104+
{
105+
return false;
106+
}
107+
99108
static inline int kvm_sched_affinity_vcpu_init(struct kvm_vcpu *vcpu)
100109
{
101110
return 0;
102111
}
103112
static inline void kvm_sched_affinity_vcpu_destroy(struct kvm_vcpu *vcpu) {}
113+
static inline void ipiv_gicd_init(void) {}
104114
static inline int kvm_sched_affinity_vm_init(struct kvm *kvm)
105115
{
106116
return 0;
@@ -111,4 +121,6 @@ static inline void kvm_tlbi_dvmbm_vcpu_put(struct kvm_vcpu *vcpu) {}
111121
static inline void kvm_hisi_reload_lsudvmbm(struct kvm *kvm) {}
112122
#endif /* CONFIG_KVM_HISI_VIRT */
113123

124+
extern bool gic_dist_enable_ipiv(void);
125+
extern bool is_gicv4p1(void);
114126
#endif /* __HISI_VIRT_H__ */

drivers/irqchip/irq-gic-v3.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,36 @@ static int gic_dist_supports_lpis(void)
13541354
!gicv3_nolpi);
13551355
}
13561356

1357+
bool is_gicv4p1(void)
1358+
{
1359+
if (!gic_data.rdists.has_rvpeid)
1360+
return false;
1361+
1362+
return true;
1363+
}
1364+
EXPORT_SYMBOL(is_gicv4p1);
1365+
1366+
void gic_dist_enable_ipiv(void)
1367+
{
1368+
u32 val;
1369+
1370+
val = readl_relaxed(gic_data.dist_base + GICD_MISC_CTRL);
1371+
val |= GICD_MISC_CTRL_CFG_IPIV_EN;
1372+
writel_relaxed(val, gic_data.dist_base + GICD_MISC_CTRL);
1373+
static_branch_enable(&ipiv_enable);
1374+
1375+
val = (0 << GICD_IPIV_CTRL_AFF_DIRECT_VPEID_SHIFT) |
1376+
(0 << GICD_IPIV_CTRL_AFF1_LEFT_SHIFT_SHIFT) |
1377+
(4 << GICD_IPIV_CTRL_AFF2_LEFT_SHIFT_SHIFT) |
1378+
(7 << GICD_IPIV_CTRL_VM_TABLE_INNERCACHE_SHIFT) |
1379+
(2 << GICD_IPIV_CTRL_VM_TABLE_SHAREABILITY_SHIFT);
1380+
writel_relaxed(val, gic_data.dist_base + GICD_IPIV_CTRL);
1381+
1382+
/* Set target ITS address of IPIV feature */
1383+
writel_relaxed(0x4880, gic_data.dist_base + GICD_IPIV_ITS_TA_BASE);
1384+
}
1385+
EXPORT_SYMBOL(gic_dist_enable_ipiv);
1386+
13571387
static void gic_cpu_init(void)
13581388
{
13591389
void __iomem *rbase;

include/linux/irqchip/arm-gic-v3.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@
111111
#define GIC_PAGE_SIZE_64K 2ULL
112112
#define GIC_PAGE_SIZE_MASK 3ULL
113113

114+
#define GICD_MISC_CTRL 0x2084
115+
#define GICD_MISC_CTRL_CFG_IPIV_EN (1U << 19)
116+
117+
/* IPIV private register */
118+
#define GICD_IPIV_CTRL 0xc05c
119+
#define GICD_IPIV_CTRL_AFF_DIRECT_VPEID_SHIFT 4
120+
#define GICD_IPIV_CTRL_AFF1_LEFT_SHIFT_SHIFT 8
121+
#define GICD_IPIV_CTRL_AFF2_LEFT_SHIFT_SHIFT 12
122+
#define GICD_IPIV_CTRL_VM_TABLE_INNERCACHE_SHIFT 16
123+
#define GICD_IPIV_CTRL_VM_TABLE_SHAREABILITY_SHIFT 19
124+
#define GICD_IPIV_ITS_TA_BASE 0xc010
125+
114126
/*
115127
* Re-Distributor registers, offsets from RD_base
116128
*/

0 commit comments

Comments
 (0)