Skip to content

Commit c14f646

Browse files
committed
Merge tag 'loongarch-kvm-6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson into HEAD
LoongArch KVM changes for v6.20 1. Add more CPUCFG mask bits. 2. Improve feature detection. 3. Add FPU/LBT delay load support. 4. Set default return value in KVM IO bus ops. 5. Add paravirt preempt feature support. 6. Add KVM steal time test case for tools/selftests.
2 parents 05f7e89 + 2d94a3f commit c14f646

File tree

17 files changed

+319
-116
lines changed

17 files changed

+319
-116
lines changed

arch/loongarch/include/asm/kvm_host.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define KVM_REQ_TLB_FLUSH_GPA KVM_ARCH_REQ(0)
3838
#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(1)
3939
#define KVM_REQ_PMU KVM_ARCH_REQ(2)
40+
#define KVM_REQ_AUX_LOAD KVM_ARCH_REQ(3)
4041

4142
#define KVM_GUESTDBG_SW_BP_MASK \
4243
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)
@@ -164,6 +165,7 @@ enum emulation_result {
164165

165166
#define LOONGARCH_PV_FEAT_UPDATED BIT_ULL(63)
166167
#define LOONGARCH_PV_FEAT_MASK (BIT(KVM_FEATURE_IPI) | \
168+
BIT(KVM_FEATURE_PREEMPT) | \
167169
BIT(KVM_FEATURE_STEAL_TIME) | \
168170
BIT(KVM_FEATURE_USER_HCALL) | \
169171
BIT(KVM_FEATURE_VIRT_EXTIOI))
@@ -200,6 +202,7 @@ struct kvm_vcpu_arch {
200202

201203
/* Which auxiliary state is loaded (KVM_LARCH_*) */
202204
unsigned int aux_inuse;
205+
unsigned int aux_ldtype;
203206

204207
/* FPU state */
205208
struct loongarch_fpu fpu FPU_ALIGN;
@@ -252,6 +255,7 @@ struct kvm_vcpu_arch {
252255
u64 guest_addr;
253256
u64 last_steal;
254257
struct gfn_to_hva_cache cache;
258+
u8 preempted;
255259
} st;
256260
};
257261

@@ -265,6 +269,11 @@ static inline void writel_sw_gcsr(struct loongarch_csrs *csr, int reg, unsigned
265269
csr->csrs[reg] = val;
266270
}
267271

272+
static inline bool kvm_guest_has_msgint(struct kvm_vcpu_arch *arch)
273+
{
274+
return arch->cpucfg[1] & CPUCFG1_MSGINT;
275+
}
276+
268277
static inline bool kvm_guest_has_fpu(struct kvm_vcpu_arch *arch)
269278
{
270279
return arch->cpucfg[2] & CPUCFG2_FP;

arch/loongarch/include/asm/kvm_para.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ struct kvm_steal_time {
3737
__u64 steal;
3838
__u32 version;
3939
__u32 flags;
40-
__u32 pad[12];
40+
__u8 preempted;
41+
__u8 pad[47];
4142
};
43+
#define KVM_VCPU_PREEMPTED (1 << 0)
4244

4345
/*
4446
* Hypercall interface for KVM hypervisor

arch/loongarch/include/asm/loongarch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,7 @@
690690
#define LOONGARCH_CSR_ISR3 0xa3
691691

692692
#define LOONGARCH_CSR_IRR 0xa4
693+
#define LOONGARCH_CSR_IPR 0xa5
693694

694695
#define LOONGARCH_CSR_PRID 0xc0
695696

arch/loongarch/include/asm/qspinlock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ static inline bool virt_spin_lock(struct qspinlock *lock)
3434
return true;
3535
}
3636

37+
#define vcpu_is_preempted vcpu_is_preempted
38+
39+
bool vcpu_is_preempted(int cpu);
40+
3741
#endif /* CONFIG_PARAVIRT */
3842

3943
#include <asm-generic/qspinlock.h>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ struct kvm_fpu {
105105
#define KVM_LOONGARCH_VM_FEAT_PV_STEALTIME 7
106106
#define KVM_LOONGARCH_VM_FEAT_PTW 8
107107
#define KVM_LOONGARCH_VM_FEAT_MSGINT 9
108+
#define KVM_LOONGARCH_VM_FEAT_PV_PREEMPT 10
108109

109110
/* Device Control API on vcpu fd */
110111
#define KVM_LOONGARCH_VCPU_CPUCFG 0

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define CPUCFG_KVM_FEATURE (CPUCFG_KVM_BASE + 4)
1616
#define KVM_FEATURE_IPI 1
1717
#define KVM_FEATURE_STEAL_TIME 2
18+
#define KVM_FEATURE_PREEMPT 3
1819
/* BIT 24 - 31 are features configurable by user space vmm */
1920
#define KVM_FEATURE_VIRT_EXTIOI 24
2021
#define KVM_FEATURE_USER_HCALL 25

arch/loongarch/kernel/paravirt.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ static int has_steal_clock;
1212
struct static_key paravirt_steal_enabled;
1313
struct static_key paravirt_steal_rq_enabled;
1414
static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
15+
static DEFINE_STATIC_KEY_FALSE(virt_preempt_key);
1516
DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key);
1617

1718
static u64 native_steal_clock(int cpu)
@@ -267,6 +268,18 @@ static int pv_time_cpu_down_prepare(unsigned int cpu)
267268

268269
return 0;
269270
}
271+
272+
bool vcpu_is_preempted(int cpu)
273+
{
274+
struct kvm_steal_time *src;
275+
276+
if (!static_branch_unlikely(&virt_preempt_key))
277+
return false;
278+
279+
src = &per_cpu(steal_time, cpu);
280+
return !!(src->preempted & KVM_VCPU_PREEMPTED);
281+
}
282+
EXPORT_SYMBOL(vcpu_is_preempted);
270283
#endif
271284

272285
static void pv_cpu_reboot(void *unused)
@@ -308,6 +321,9 @@ int __init pv_time_init(void)
308321
pr_err("Failed to install cpu hotplug callbacks\n");
309322
return r;
310323
}
324+
325+
if (kvm_para_has_feature(KVM_FEATURE_PREEMPT))
326+
static_branch_enable(&virt_preempt_key);
311327
#endif
312328

313329
static_call_update(pv_steal_clock, paravt_steal_clock);
@@ -318,7 +334,10 @@ int __init pv_time_init(void)
318334
static_key_slow_inc(&paravirt_steal_rq_enabled);
319335
#endif
320336

321-
pr_info("Using paravirt steal-time\n");
337+
if (static_key_enabled(&virt_preempt_key))
338+
pr_info("Using paravirt steal-time with preempt enabled\n");
339+
else
340+
pr_info("Using paravirt steal-time with preempt disabled\n");
322341

323342
return 0;
324343
}

arch/loongarch/kvm/exit.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ static int kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu, int ecode)
754754
return RESUME_HOST;
755755
}
756756

757-
kvm_own_fpu(vcpu);
757+
vcpu->arch.aux_ldtype = KVM_LARCH_FPU;
758+
kvm_make_request(KVM_REQ_AUX_LOAD, vcpu);
758759

759760
return RESUME_GUEST;
760761
}
@@ -792,8 +793,12 @@ static long kvm_save_notify(struct kvm_vcpu *vcpu)
792793
*/
793794
static int kvm_handle_lsx_disabled(struct kvm_vcpu *vcpu, int ecode)
794795
{
795-
if (kvm_own_lsx(vcpu))
796+
if (!kvm_guest_has_lsx(&vcpu->arch))
796797
kvm_queue_exception(vcpu, EXCCODE_INE, 0);
798+
else {
799+
vcpu->arch.aux_ldtype = KVM_LARCH_LSX;
800+
kvm_make_request(KVM_REQ_AUX_LOAD, vcpu);
801+
}
797802

798803
return RESUME_GUEST;
799804
}
@@ -808,16 +813,24 @@ static int kvm_handle_lsx_disabled(struct kvm_vcpu *vcpu, int ecode)
808813
*/
809814
static int kvm_handle_lasx_disabled(struct kvm_vcpu *vcpu, int ecode)
810815
{
811-
if (kvm_own_lasx(vcpu))
816+
if (!kvm_guest_has_lasx(&vcpu->arch))
812817
kvm_queue_exception(vcpu, EXCCODE_INE, 0);
818+
else {
819+
vcpu->arch.aux_ldtype = KVM_LARCH_LASX;
820+
kvm_make_request(KVM_REQ_AUX_LOAD, vcpu);
821+
}
813822

814823
return RESUME_GUEST;
815824
}
816825

817826
static int kvm_handle_lbt_disabled(struct kvm_vcpu *vcpu, int ecode)
818827
{
819-
if (kvm_own_lbt(vcpu))
828+
if (!kvm_guest_has_lbt(&vcpu->arch))
820829
kvm_queue_exception(vcpu, EXCCODE_INE, 0);
830+
else {
831+
vcpu->arch.aux_ldtype = KVM_LARCH_LBT;
832+
kvm_make_request(KVM_REQ_AUX_LOAD, vcpu);
833+
}
821834

822835
return RESUME_GUEST;
823836
}

arch/loongarch/kvm/intc/eiointc.c

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level)
119119
static int loongarch_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s,
120120
gpa_t addr, unsigned long *val)
121121
{
122-
int index, ret = 0;
122+
int index;
123123
u64 data = 0;
124124
gpa_t offset;
125125

@@ -150,40 +150,36 @@ static int loongarch_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eioint
150150
data = s->coremap[index];
151151
break;
152152
default:
153-
ret = -EINVAL;
154153
break;
155154
}
156155
*val = data;
157156

158-
return ret;
157+
return 0;
159158
}
160159

161160
static int kvm_eiointc_read(struct kvm_vcpu *vcpu,
162161
struct kvm_io_device *dev,
163162
gpa_t addr, int len, void *val)
164163
{
165-
int ret = -EINVAL;
166164
unsigned long flags, data, offset;
167165
struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
168166

169167
if (!eiointc) {
170168
kvm_err("%s: eiointc irqchip not valid!\n", __func__);
171-
return -EINVAL;
169+
return 0;
172170
}
173171

174172
if (addr & (len - 1)) {
175173
kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len);
176-
return -EINVAL;
174+
return 0;
177175
}
178176

179177
offset = addr & 0x7;
180178
addr -= offset;
181179
vcpu->stat.eiointc_read_exits++;
182180
spin_lock_irqsave(&eiointc->lock, flags);
183-
ret = loongarch_eiointc_read(vcpu, eiointc, addr, &data);
181+
loongarch_eiointc_read(vcpu, eiointc, addr, &data);
184182
spin_unlock_irqrestore(&eiointc->lock, flags);
185-
if (ret)
186-
return ret;
187183

188184
data = data >> (offset * 8);
189185
switch (len) {
@@ -208,7 +204,7 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
208204
struct loongarch_eiointc *s,
209205
gpa_t addr, u64 value, u64 field_mask)
210206
{
211-
int index, irq, ret = 0;
207+
int index, irq;
212208
u8 cpu;
213209
u64 data, old, mask;
214210
gpa_t offset;
@@ -287,54 +283,52 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
287283
eiointc_update_sw_coremap(s, index * 8, data, sizeof(data), true);
288284
break;
289285
default:
290-
ret = -EINVAL;
291286
break;
292287
}
293288

294-
return ret;
289+
return 0;
295290
}
296291

297292
static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
298293
struct kvm_io_device *dev,
299294
gpa_t addr, int len, const void *val)
300295
{
301-
int ret = -EINVAL;
302296
unsigned long flags, value;
303297
struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
304298

305299
if (!eiointc) {
306300
kvm_err("%s: eiointc irqchip not valid!\n", __func__);
307-
return -EINVAL;
301+
return 0;
308302
}
309303

310304
if (addr & (len - 1)) {
311305
kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len);
312-
return -EINVAL;
306+
return 0;
313307
}
314308

315309
vcpu->stat.eiointc_write_exits++;
316310
spin_lock_irqsave(&eiointc->lock, flags);
317311
switch (len) {
318312
case 1:
319313
value = *(unsigned char *)val;
320-
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, 0xFF);
314+
loongarch_eiointc_write(vcpu, eiointc, addr, value, 0xFF);
321315
break;
322316
case 2:
323317
value = *(unsigned short *)val;
324-
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, USHRT_MAX);
318+
loongarch_eiointc_write(vcpu, eiointc, addr, value, USHRT_MAX);
325319
break;
326320
case 4:
327321
value = *(unsigned int *)val;
328-
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, UINT_MAX);
322+
loongarch_eiointc_write(vcpu, eiointc, addr, value, UINT_MAX);
329323
break;
330324
default:
331325
value = *(unsigned long *)val;
332-
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, ULONG_MAX);
326+
loongarch_eiointc_write(vcpu, eiointc, addr, value, ULONG_MAX);
333327
break;
334328
}
335329
spin_unlock_irqrestore(&eiointc->lock, flags);
336330

337-
return ret;
331+
return 0;
338332
}
339333

340334
static const struct kvm_io_device_ops kvm_eiointc_ops = {
@@ -352,7 +346,7 @@ static int kvm_eiointc_virt_read(struct kvm_vcpu *vcpu,
352346

353347
if (!eiointc) {
354348
kvm_err("%s: eiointc irqchip not valid!\n", __func__);
355-
return -EINVAL;
349+
return 0;
356350
}
357351

358352
addr -= EIOINTC_VIRT_BASE;
@@ -376,28 +370,25 @@ static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu,
376370
struct kvm_io_device *dev,
377371
gpa_t addr, int len, const void *val)
378372
{
379-
int ret = 0;
380373
unsigned long flags;
381374
u32 value = *(u32 *)val;
382375
struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
383376

384377
if (!eiointc) {
385378
kvm_err("%s: eiointc irqchip not valid!\n", __func__);
386-
return -EINVAL;
379+
return 0;
387380
}
388381

389382
addr -= EIOINTC_VIRT_BASE;
390383
spin_lock_irqsave(&eiointc->lock, flags);
391384
switch (addr) {
392385
case EIOINTC_VIRT_FEATURES:
393-
ret = -EPERM;
394386
break;
395387
case EIOINTC_VIRT_CONFIG:
396388
/*
397389
* eiointc features can only be set at disabled status
398390
*/
399391
if ((eiointc->status & BIT(EIOINTC_ENABLE)) && value) {
400-
ret = -EPERM;
401392
break;
402393
}
403394
eiointc->status = value & eiointc->features;
@@ -407,7 +398,7 @@ static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu,
407398
}
408399
spin_unlock_irqrestore(&eiointc->lock, flags);
409400

410-
return ret;
401+
return 0;
411402
}
412403

413404
static const struct kvm_io_device_ops kvm_eiointc_virt_ops = {

0 commit comments

Comments
 (0)