Skip to content

Commit 06e22bb

Browse files
committed
Merge tag 'kvmarm-fixes-for-4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm
KVM/arm fixes for 4.17, take #1 - PSCI selection API, a leftover from 4.16 - Kick vcpu on active interrupt affinity change - Plug a VMID allocation race on oversubscribed systems - Silence debug messages - Update Christoffer's email address
2 parents 6d08b06 + 85bd0ba commit 06e22bb

File tree

14 files changed

+178
-15
lines changed

14 files changed

+178
-15
lines changed

Documentation/virtual/kvm/api.txt

+8-1
Original file line numberDiff line numberDiff line change
@@ -1960,6 +1960,9 @@ ARM 32-bit VFP control registers have the following id bit patterns:
19601960
ARM 64-bit FP registers have the following id bit patterns:
19611961
0x4030 0000 0012 0 <regno:12>
19621962

1963+
ARM firmware pseudo-registers have the following bit pattern:
1964+
0x4030 0000 0014 <regno:16>
1965+
19631966

19641967
arm64 registers are mapped using the lower 32 bits. The upper 16 of
19651968
that is the register group type, or coprocessor number:
@@ -1976,6 +1979,9 @@ arm64 CCSIDR registers are demultiplexed by CSSELR value:
19761979
arm64 system registers have the following id bit patterns:
19771980
0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
19781981

1982+
arm64 firmware pseudo-registers have the following bit pattern:
1983+
0x6030 0000 0014 <regno:16>
1984+
19791985

19801986
MIPS registers are mapped using the lower 32 bits. The upper 16 of that is
19811987
the register group type:
@@ -2510,7 +2516,8 @@ Possible features:
25102516
and execute guest code when KVM_RUN is called.
25112517
- KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
25122518
Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
2513-
- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
2519+
- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
2520+
backward compatible with v0.2) for the CPU.
25142521
Depends on KVM_CAP_ARM_PSCI_0_2.
25152522
- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
25162523
Depends on KVM_CAP_ARM_PMU_V3.
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
KVM implements the PSCI (Power State Coordination Interface)
2+
specification in order to provide services such as CPU on/off, reset
3+
and power-off to the guest.
4+
5+
The PSCI specification is regularly updated to provide new features,
6+
and KVM implements these updates if they make sense from a virtualization
7+
point of view.
8+
9+
This means that a guest booted on two different versions of KVM can
10+
observe two different "firmware" revisions. This could cause issues if
11+
a given guest is tied to a particular PSCI revision (unlikely), or if
12+
a migration causes a different PSCI version to be exposed out of the
13+
blue to an unsuspecting guest.
14+
15+
In order to remedy this situation, KVM exposes a set of "firmware
16+
pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
17+
interface. These registers can be saved/restored by userspace, and set
18+
to a convenient value if required.
19+
20+
The following register is defined:
21+
22+
* KVM_REG_ARM_PSCI_VERSION:
23+
24+
- Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
25+
(and thus has already been initialized)
26+
- Returns the current PSCI version on GET_ONE_REG (defaulting to the
27+
highest PSCI version implemented by KVM and compatible with v0.2)
28+
- Allows any PSCI version implemented by KVM and compatible with
29+
v0.2 to be set with SET_ONE_REG
30+
- Affects the whole VM (even if the register view is per-vcpu)

MAINTAINERS

+2-2
Original file line numberDiff line numberDiff line change
@@ -7753,7 +7753,7 @@ F: arch/x86/include/asm/svm.h
77537753
F: arch/x86/kvm/svm.c
77547754

77557755
KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm)
7756-
M: Christoffer Dall <christoffer.dall@linaro.org>
7756+
M: Christoffer Dall <christoffer.dall@arm.com>
77577757
M: Marc Zyngier <[email protected]>
77587758
L: [email protected] (moderated for non-subscribers)
77597759
@@ -7767,7 +7767,7 @@ F: virt/kvm/arm/
77677767
F: include/kvm/arm_*
77687768

77697769
KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
7770-
M: Christoffer Dall <christoffer.dall@linaro.org>
7770+
M: Christoffer Dall <christoffer.dall@arm.com>
77717771
M: Marc Zyngier <[email protected]>
77727772
L: [email protected] (moderated for non-subscribers)
77737773

arch/arm/include/asm/kvm_host.h

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ struct kvm_arch {
7777
/* Interrupt controller */
7878
struct vgic_dist vgic;
7979
int max_vcpus;
80+
81+
/* Mandated version of PSCI */
82+
u32 psci_version;
8083
};
8184

8285
#define KVM_NR_MEM_OBJS 40

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

+6
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ struct kvm_arch_memory_slot {
195195
#define KVM_REG_ARM_VFP_FPINST 0x1009
196196
#define KVM_REG_ARM_VFP_FPINST2 0x100A
197197

198+
/* KVM-as-firmware specific pseudo-registers */
199+
#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
200+
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
201+
KVM_REG_ARM_FW | ((r) & 0xffff))
202+
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
203+
198204
/* Device Control API: ARM VGIC */
199205
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
200206
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1

arch/arm/kvm/guest.c

+13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/module.h>
2323
#include <linux/vmalloc.h>
2424
#include <linux/fs.h>
25+
#include <kvm/arm_psci.h>
2526
#include <asm/cputype.h>
2627
#include <linux/uaccess.h>
2728
#include <asm/kvm.h>
@@ -176,6 +177,7 @@ static unsigned long num_core_regs(void)
176177
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
177178
{
178179
return num_core_regs() + kvm_arm_num_coproc_regs(vcpu)
180+
+ kvm_arm_get_fw_num_regs(vcpu)
179181
+ NUM_TIMER_REGS;
180182
}
181183

@@ -196,6 +198,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
196198
uindices++;
197199
}
198200

201+
ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
202+
if (ret)
203+
return ret;
204+
uindices += kvm_arm_get_fw_num_regs(vcpu);
205+
199206
ret = copy_timer_indices(vcpu, uindices);
200207
if (ret)
201208
return ret;
@@ -214,6 +221,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
214221
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
215222
return get_core_reg(vcpu, reg);
216223

224+
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
225+
return kvm_arm_get_fw_reg(vcpu, reg);
226+
217227
if (is_timer_reg(reg->id))
218228
return get_timer_reg(vcpu, reg);
219229

@@ -230,6 +240,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
230240
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
231241
return set_core_reg(vcpu, reg);
232242

243+
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
244+
return kvm_arm_set_fw_reg(vcpu, reg);
245+
233246
if (is_timer_reg(reg->id))
234247
return set_timer_reg(vcpu, reg);
235248

arch/arm64/include/asm/kvm_host.h

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ struct kvm_arch {
7575

7676
/* Interrupt controller */
7777
struct vgic_dist vgic;
78+
79+
/* Mandated version of PSCI */
80+
u32 psci_version;
7881
};
7982

8083
#define KVM_NR_MEM_OBJS 40

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

+6
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ struct kvm_arch_memory_slot {
206206
#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
207207
#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
208208

209+
/* KVM-as-firmware specific pseudo-registers */
210+
#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
211+
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
212+
KVM_REG_ARM_FW | ((r) & 0xffff))
213+
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
214+
209215
/* Device Control API: ARM VGIC */
210216
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
211217
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1

arch/arm64/kvm/guest.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/module.h>
2626
#include <linux/vmalloc.h>
2727
#include <linux/fs.h>
28+
#include <kvm/arm_psci.h>
2829
#include <asm/cputype.h>
2930
#include <linux/uaccess.h>
3031
#include <asm/kvm.h>
@@ -205,7 +206,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
205206
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
206207
{
207208
return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
208-
+ NUM_TIMER_REGS;
209+
+ kvm_arm_get_fw_num_regs(vcpu) + NUM_TIMER_REGS;
209210
}
210211

211212
/**
@@ -225,6 +226,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
225226
uindices++;
226227
}
227228

229+
ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
230+
if (ret)
231+
return ret;
232+
uindices += kvm_arm_get_fw_num_regs(vcpu);
233+
228234
ret = copy_timer_indices(vcpu, uindices);
229235
if (ret)
230236
return ret;
@@ -243,6 +249,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
243249
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
244250
return get_core_reg(vcpu, reg);
245251

252+
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
253+
return kvm_arm_get_fw_reg(vcpu, reg);
254+
246255
if (is_timer_reg(reg->id))
247256
return get_timer_reg(vcpu, reg);
248257

@@ -259,6 +268,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
259268
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
260269
return set_core_reg(vcpu, reg);
261270

271+
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
272+
return kvm_arm_set_fw_reg(vcpu, reg);
273+
262274
if (is_timer_reg(reg->id))
263275
return set_timer_reg(vcpu, reg);
264276

arch/arm64/kvm/sys_regs.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -996,14 +996,12 @@ static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)
996996

997997
if (id == SYS_ID_AA64PFR0_EL1) {
998998
if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT))
999-
pr_err_once("kvm [%i]: SVE unsupported for guests, suppressing\n",
1000-
task_pid_nr(current));
999+
kvm_debug("SVE unsupported for guests, suppressing\n");
10011000

10021001
val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
10031002
} else if (id == SYS_ID_AA64MMFR1_EL1) {
10041003
if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
1005-
pr_err_once("kvm [%i]: LORegions unsupported for guests, suppressing\n",
1006-
task_pid_nr(current));
1004+
kvm_debug("LORegions unsupported for guests, suppressing\n");
10071005

10081006
val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT);
10091007
}

include/kvm/arm_psci.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,27 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
3737
* Our PSCI implementation stays the same across versions from
3838
* v0.2 onward, only adding the few mandatory functions (such
3939
* as FEATURES with 1.0) that are required by newer
40-
* revisions. It is thus safe to return the latest.
40+
* revisions. It is thus safe to return the latest, unless
41+
* userspace has instructed us otherwise.
4142
*/
42-
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
43+
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
44+
if (vcpu->kvm->arch.psci_version)
45+
return vcpu->kvm->arch.psci_version;
46+
4347
return KVM_ARM_PSCI_LATEST;
48+
}
4449

4550
return KVM_ARM_PSCI_0_1;
4651
}
4752

4853

4954
int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
5055

56+
struct kvm_one_reg;
57+
58+
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
59+
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
60+
int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
61+
int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
62+
5163
#endif /* __KVM_ARM_PSCI_H__ */

virt/kvm/arm/arm.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
6363
static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
6464
static u32 kvm_next_vmid;
6565
static unsigned int kvm_vmid_bits __read_mostly;
66-
static DEFINE_SPINLOCK(kvm_vmid_lock);
66+
static DEFINE_RWLOCK(kvm_vmid_lock);
6767

6868
static bool vgic_present;
6969

@@ -473,19 +473,24 @@ static void update_vttbr(struct kvm *kvm)
473473
{
474474
phys_addr_t pgd_phys;
475475
u64 vmid;
476+
bool new_gen;
476477

477-
if (!need_new_vmid_gen(kvm))
478+
read_lock(&kvm_vmid_lock);
479+
new_gen = need_new_vmid_gen(kvm);
480+
read_unlock(&kvm_vmid_lock);
481+
482+
if (!new_gen)
478483
return;
479484

480-
spin_lock(&kvm_vmid_lock);
485+
write_lock(&kvm_vmid_lock);
481486

482487
/*
483488
* We need to re-check the vmid_gen here to ensure that if another vcpu
484489
* already allocated a valid vmid for this vm, then this vcpu should
485490
* use the same vmid.
486491
*/
487492
if (!need_new_vmid_gen(kvm)) {
488-
spin_unlock(&kvm_vmid_lock);
493+
write_unlock(&kvm_vmid_lock);
489494
return;
490495
}
491496

@@ -519,7 +524,7 @@ static void update_vttbr(struct kvm *kvm)
519524
vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits);
520525
kvm->arch.vttbr = kvm_phys_to_vttbr(pgd_phys) | vmid;
521526

522-
spin_unlock(&kvm_vmid_lock);
527+
write_unlock(&kvm_vmid_lock);
523528
}
524529

525530
static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)

virt/kvm/arm/psci.c

+60
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/arm-smccc.h>
1919
#include <linux/preempt.h>
2020
#include <linux/kvm_host.h>
21+
#include <linux/uaccess.h>
2122
#include <linux/wait.h>
2223

2324
#include <asm/cputype.h>
@@ -427,3 +428,62 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
427428
smccc_set_retval(vcpu, val, 0, 0, 0);
428429
return 1;
429430
}
431+
432+
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
433+
{
434+
return 1; /* PSCI version */
435+
}
436+
437+
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
438+
{
439+
if (put_user(KVM_REG_ARM_PSCI_VERSION, uindices))
440+
return -EFAULT;
441+
442+
return 0;
443+
}
444+
445+
int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
446+
{
447+
if (reg->id == KVM_REG_ARM_PSCI_VERSION) {
448+
void __user *uaddr = (void __user *)(long)reg->addr;
449+
u64 val;
450+
451+
val = kvm_psci_version(vcpu, vcpu->kvm);
452+
if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
453+
return -EFAULT;
454+
455+
return 0;
456+
}
457+
458+
return -EINVAL;
459+
}
460+
461+
int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
462+
{
463+
if (reg->id == KVM_REG_ARM_PSCI_VERSION) {
464+
void __user *uaddr = (void __user *)(long)reg->addr;
465+
bool wants_02;
466+
u64 val;
467+
468+
if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
469+
return -EFAULT;
470+
471+
wants_02 = test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features);
472+
473+
switch (val) {
474+
case KVM_ARM_PSCI_0_1:
475+
if (wants_02)
476+
return -EINVAL;
477+
vcpu->kvm->arch.psci_version = val;
478+
return 0;
479+
case KVM_ARM_PSCI_0_2:
480+
case KVM_ARM_PSCI_1_0:
481+
if (!wants_02)
482+
return -EINVAL;
483+
vcpu->kvm->arch.psci_version = val;
484+
return 0;
485+
}
486+
}
487+
488+
return -EINVAL;
489+
}

0 commit comments

Comments
 (0)