Skip to content

Commit cdc118f

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: KVM: Enable paravirt feature control from VMM
Export kernel paravirt features to user space, so that VMM can control each single paravirt feature. By default paravirt features will be the same with kvm supported features if VMM does not set it. Also a new feature KVM_FEATURE_VIRT_EXTIOI is added which can be set from user space. This feature indicates that the virt EIOINTC can route interrupts to 256 vCPUs, rather than 4 vCPUs like with real HW. Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent f4e40ea commit cdc118f

File tree

11 files changed

+117
-48
lines changed

11 files changed

+117
-48
lines changed

arch/loongarch/include/asm/kvm_host.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ struct kvm_arch {
112112
unsigned int root_level;
113113
spinlock_t phyid_map_lock;
114114
struct kvm_phyid_map *phyid_map;
115+
/* Enabled PV features */
116+
unsigned long pv_features;
115117

116118
s64 time_offset;
117119
struct kvm_context __percpu *vmcs;
@@ -143,6 +145,11 @@ enum emulation_result {
143145
#define KVM_LARCH_SWCSR_LATEST (0x1 << 5)
144146
#define KVM_LARCH_HWCSR_USABLE (0x1 << 6)
145147

148+
#define LOONGARCH_PV_FEAT_UPDATED BIT_ULL(63)
149+
#define LOONGARCH_PV_FEAT_MASK (BIT(KVM_FEATURE_IPI) | \
150+
BIT(KVM_FEATURE_STEAL_TIME) | \
151+
BIT(KVM_FEATURE_VIRT_EXTIOI))
152+
146153
struct kvm_vcpu_arch {
147154
/*
148155
* Switch pointer-to-function type to unsigned long

arch/loongarch/include/asm/kvm_para.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef _ASM_LOONGARCH_KVM_PARA_H
33
#define _ASM_LOONGARCH_KVM_PARA_H
44

5+
#include <uapi/asm/kvm_para.h>
6+
57
/*
68
* Hypercall code field
79
*/

arch/loongarch/include/asm/kvm_vcpu.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,9 @@ static inline bool kvm_pvtime_supported(void)
130130
return !!sched_info_on();
131131
}
132132

133+
static inline bool kvm_guest_has_pv_feature(struct kvm_vcpu *vcpu, unsigned int feature)
134+
{
135+
return vcpu->kvm->arch.pv_features & BIT(feature);
136+
}
137+
133138
#endif /* __ASM_LOONGARCH_KVM_VCPU_H__ */

arch/loongarch/include/asm/loongarch.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,8 @@
161161

162162
/*
163163
* CPUCFG index area: 0x40000000 -- 0x400000ff
164-
* SW emulation for KVM hypervirsor
164+
* SW emulation for KVM hypervirsor, see arch/loongarch/include/uapi/asm/kvm_para.h
165165
*/
166-
#define CPUCFG_KVM_BASE 0x40000000
167-
#define CPUCFG_KVM_SIZE 0x100
168-
169-
#define CPUCFG_KVM_SIG (CPUCFG_KVM_BASE + 0)
170-
#define KVM_SIGNATURE "KVM\0"
171-
#define CPUCFG_KVM_FEATURE (CPUCFG_KVM_BASE + 4)
172-
#define KVM_FEATURE_IPI BIT(1)
173-
#define KVM_FEATURE_STEAL_TIME BIT(2)
174166

175167
#ifndef __ASSEMBLY__
176168

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
# SPDX-License-Identifier: GPL-2.0
22
syscall-y += unistd_64.h
3-
4-
generic-y += kvm_para.h

arch/loongarch/include/uapi/asm/kvm.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,15 @@ struct kvm_fpu {
9292
#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
9393

9494
/* Device Control API on vm fd */
95-
#define KVM_LOONGARCH_VM_FEAT_CTRL 0
96-
#define KVM_LOONGARCH_VM_FEAT_LSX 0
97-
#define KVM_LOONGARCH_VM_FEAT_LASX 1
98-
#define KVM_LOONGARCH_VM_FEAT_X86BT 2
99-
#define KVM_LOONGARCH_VM_FEAT_ARMBT 3
100-
#define KVM_LOONGARCH_VM_FEAT_MIPSBT 4
101-
#define KVM_LOONGARCH_VM_FEAT_PMU 5
95+
#define KVM_LOONGARCH_VM_FEAT_CTRL 0
96+
#define KVM_LOONGARCH_VM_FEAT_LSX 0
97+
#define KVM_LOONGARCH_VM_FEAT_LASX 1
98+
#define KVM_LOONGARCH_VM_FEAT_X86BT 2
99+
#define KVM_LOONGARCH_VM_FEAT_ARMBT 3
100+
#define KVM_LOONGARCH_VM_FEAT_MIPSBT 4
101+
#define KVM_LOONGARCH_VM_FEAT_PMU 5
102+
#define KVM_LOONGARCH_VM_FEAT_PV_IPI 6
103+
#define KVM_LOONGARCH_VM_FEAT_PV_STEALTIME 7
102104

103105
/* Device Control API on vcpu fd */
104106
#define KVM_LOONGARCH_VCPU_CPUCFG 0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+
#ifndef _UAPI_ASM_KVM_PARA_H
3+
#define _UAPI_ASM_KVM_PARA_H
4+
5+
#include <linux/types.h>
6+
7+
/*
8+
* CPUCFG index area: 0x40000000 -- 0x400000ff
9+
* SW emulation for KVM hypervirsor
10+
*/
11+
#define CPUCFG_KVM_BASE 0x40000000
12+
#define CPUCFG_KVM_SIZE 0x100
13+
#define CPUCFG_KVM_SIG (CPUCFG_KVM_BASE + 0)
14+
#define KVM_SIGNATURE "KVM\0"
15+
#define CPUCFG_KVM_FEATURE (CPUCFG_KVM_BASE + 4)
16+
#define KVM_FEATURE_IPI 1
17+
#define KVM_FEATURE_STEAL_TIME 2
18+
/* BIT 24 - 31 are features configurable by user space vmm */
19+
#define KVM_FEATURE_VIRT_EXTIOI 24
20+
21+
#endif /* _UAPI_ASM_KVM_PARA_H */

arch/loongarch/kernel/paravirt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ int __init pv_ipi_init(void)
176176
return 0;
177177

178178
feature = read_cpucfg(CPUCFG_KVM_FEATURE);
179-
if (!(feature & KVM_FEATURE_IPI))
179+
if (!(feature & BIT(KVM_FEATURE_IPI)))
180180
return 0;
181181

182182
#ifdef CONFIG_SMP
@@ -207,15 +207,15 @@ static int pv_enable_steal_time(void)
207207
}
208208

209209
addr |= KVM_STEAL_PHYS_VALID;
210-
kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, KVM_FEATURE_STEAL_TIME, addr);
210+
kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, BIT(KVM_FEATURE_STEAL_TIME), addr);
211211

212212
return 0;
213213
}
214214

215215
static void pv_disable_steal_time(void)
216216
{
217217
if (has_steal_clock)
218-
kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, KVM_FEATURE_STEAL_TIME, 0);
218+
kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, BIT(KVM_FEATURE_STEAL_TIME), 0);
219219
}
220220

221221
#ifdef CONFIG_SMP
@@ -267,7 +267,7 @@ int __init pv_time_init(void)
267267
return 0;
268268

269269
feature = read_cpucfg(CPUCFG_KVM_FEATURE);
270-
if (!(feature & KVM_FEATURE_STEAL_TIME))
270+
if (!(feature & BIT(KVM_FEATURE_STEAL_TIME)))
271271
return 0;
272272

273273
has_steal_clock = 1;

arch/loongarch/kvm/exit.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ static int kvm_emu_cpucfg(struct kvm_vcpu *vcpu, larch_inst inst)
5050
vcpu->arch.gprs[rd] = *(unsigned int *)KVM_SIGNATURE;
5151
break;
5252
case CPUCFG_KVM_FEATURE:
53-
ret = KVM_FEATURE_IPI;
54-
if (kvm_pvtime_supported())
55-
ret |= KVM_FEATURE_STEAL_TIME;
53+
ret = vcpu->kvm->arch.pv_features & LOONGARCH_PV_FEAT_MASK;
5654
vcpu->arch.gprs[rd] = ret;
5755
break;
5856
default:
@@ -705,25 +703,22 @@ static long kvm_save_notify(struct kvm_vcpu *vcpu)
705703
id = kvm_read_reg(vcpu, LOONGARCH_GPR_A1);
706704
data = kvm_read_reg(vcpu, LOONGARCH_GPR_A2);
707705
switch (id) {
708-
case KVM_FEATURE_STEAL_TIME:
709-
if (!kvm_pvtime_supported())
710-
return KVM_HCALL_INVALID_CODE;
711-
706+
case BIT(KVM_FEATURE_STEAL_TIME):
712707
if (data & ~(KVM_STEAL_PHYS_MASK | KVM_STEAL_PHYS_VALID))
713708
return KVM_HCALL_INVALID_PARAMETER;
714709

715710
vcpu->arch.st.guest_addr = data;
716711
if (!(data & KVM_STEAL_PHYS_VALID))
717-
break;
712+
return 0;
718713

719714
vcpu->arch.st.last_steal = current->sched_info.run_delay;
720715
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
721-
break;
716+
return 0;
722717
default:
723-
break;
718+
return KVM_HCALL_INVALID_CODE;
724719
};
725720

726-
return 0;
721+
return KVM_HCALL_INVALID_CODE;
727722
};
728723

729724
/*
@@ -797,19 +792,21 @@ static int kvm_send_pv_ipi(struct kvm_vcpu *vcpu)
797792
*/
798793
static void kvm_handle_service(struct kvm_vcpu *vcpu)
799794
{
795+
long ret = KVM_HCALL_INVALID_CODE;
800796
unsigned long func = kvm_read_reg(vcpu, LOONGARCH_GPR_A0);
801-
long ret;
802797

803798
switch (func) {
804799
case KVM_HCALL_FUNC_IPI:
805-
kvm_send_pv_ipi(vcpu);
806-
ret = KVM_HCALL_SUCCESS;
800+
if (kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_IPI)) {
801+
kvm_send_pv_ipi(vcpu);
802+
ret = KVM_HCALL_SUCCESS;
803+
}
807804
break;
808805
case KVM_HCALL_FUNC_NOTIFY:
809-
ret = kvm_save_notify(vcpu);
806+
if (kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME))
807+
ret = kvm_save_notify(vcpu);
810808
break;
811809
default:
812-
ret = KVM_HCALL_INVALID_CODE;
813810
break;
814811
}
815812

arch/loongarch/kvm/vcpu.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,8 @@ static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu,
953953
case LOONGARCH_CPUCFG2:
954954
case LOONGARCH_CPUCFG6:
955955
return 0;
956+
case CPUCFG_KVM_FEATURE:
957+
return 0;
956958
default:
957959
return -ENXIO;
958960
}
@@ -963,8 +965,8 @@ static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu,
963965
static int kvm_loongarch_pvtime_has_attr(struct kvm_vcpu *vcpu,
964966
struct kvm_device_attr *attr)
965967
{
966-
if (!kvm_pvtime_supported() ||
967-
attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA)
968+
if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME)
969+
|| attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA)
968970
return -ENXIO;
969971

970972
return 0;
@@ -996,9 +998,18 @@ static int kvm_loongarch_cpucfg_get_attr(struct kvm_vcpu *vcpu,
996998
uint64_t val;
997999
uint64_t __user *uaddr = (uint64_t __user *)attr->addr;
9981000

999-
ret = _kvm_get_cpucfg_mask(attr->attr, &val);
1000-
if (ret)
1001-
return ret;
1001+
switch (attr->attr) {
1002+
case 0 ... (KVM_MAX_CPUCFG_REGS - 1):
1003+
ret = _kvm_get_cpucfg_mask(attr->attr, &val);
1004+
if (ret)
1005+
return ret;
1006+
break;
1007+
case CPUCFG_KVM_FEATURE:
1008+
val = vcpu->kvm->arch.pv_features & LOONGARCH_PV_FEAT_MASK;
1009+
break;
1010+
default:
1011+
return -ENXIO;
1012+
}
10021013

10031014
put_user(val, uaddr);
10041015

@@ -1011,8 +1022,8 @@ static int kvm_loongarch_pvtime_get_attr(struct kvm_vcpu *vcpu,
10111022
u64 gpa;
10121023
u64 __user *user = (u64 __user *)attr->addr;
10131024

1014-
if (!kvm_pvtime_supported() ||
1015-
attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA)
1025+
if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME)
1026+
|| attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA)
10161027
return -ENXIO;
10171028

10181029
gpa = vcpu->arch.st.guest_addr;
@@ -1044,7 +1055,28 @@ static int kvm_loongarch_vcpu_get_attr(struct kvm_vcpu *vcpu,
10441055
static int kvm_loongarch_cpucfg_set_attr(struct kvm_vcpu *vcpu,
10451056
struct kvm_device_attr *attr)
10461057
{
1047-
return -ENXIO;
1058+
u64 val, valid;
1059+
u64 __user *user = (u64 __user *)attr->addr;
1060+
struct kvm *kvm = vcpu->kvm;
1061+
1062+
switch (attr->attr) {
1063+
case CPUCFG_KVM_FEATURE:
1064+
if (get_user(val, user))
1065+
return -EFAULT;
1066+
1067+
valid = LOONGARCH_PV_FEAT_MASK;
1068+
if (val & ~valid)
1069+
return -EINVAL;
1070+
1071+
/* All vCPUs need set the same PV features */
1072+
if ((kvm->arch.pv_features & LOONGARCH_PV_FEAT_UPDATED)
1073+
&& ((kvm->arch.pv_features & valid) != val))
1074+
return -EINVAL;
1075+
kvm->arch.pv_features = val | LOONGARCH_PV_FEAT_UPDATED;
1076+
return 0;
1077+
default:
1078+
return -ENXIO;
1079+
}
10481080
}
10491081

10501082
static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu,
@@ -1054,8 +1086,8 @@ static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu,
10541086
u64 gpa, __user *user = (u64 __user *)attr->addr;
10551087
struct kvm *kvm = vcpu->kvm;
10561088

1057-
if (!kvm_pvtime_supported() ||
1058-
attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA)
1089+
if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME)
1090+
|| attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA)
10591091
return -ENXIO;
10601092

10611093
if (get_user(gpa, user))

0 commit comments

Comments
 (0)