diff options
| author | Radim Krčmář <rkrcmar@redhat.com> | 2018-04-25 08:16:50 -0400 |
|---|---|---|
| committer | Radim Krčmář <rkrcmar@redhat.com> | 2018-04-25 08:16:50 -0400 |
| commit | 06e22bb6fa5bd2d7d6cdd4d886aef90c3ef8f9c7 (patch) | |
| tree | 600ef54eb192cfd401fa7b266cfe5bc8c0b0dbd7 | |
| parent | 6d08b06e67cd117f6992c46611dfb4ce267cd71e (diff) | |
| parent | 85bd0ba1ff9875798fad94218b627ea9f768f3c3 (diff) | |
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
| -rw-r--r-- | Documentation/virtual/kvm/api.txt | 9 | ||||
| -rw-r--r-- | Documentation/virtual/kvm/arm/psci.txt | 30 | ||||
| -rw-r--r-- | MAINTAINERS | 4 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | arch/arm/include/uapi/asm/kvm.h | 6 | ||||
| -rw-r--r-- | arch/arm/kvm/guest.c | 13 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | arch/arm64/include/uapi/asm/kvm.h | 6 | ||||
| -rw-r--r-- | arch/arm64/kvm/guest.c | 14 | ||||
| -rw-r--r-- | arch/arm64/kvm/sys_regs.c | 6 | ||||
| -rw-r--r-- | include/kvm/arm_psci.h | 16 | ||||
| -rw-r--r-- | virt/kvm/arm/arm.c | 15 | ||||
| -rw-r--r-- | virt/kvm/arm/psci.c | 60 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic.c | 8 |
14 files changed, 178 insertions, 15 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 1c7958b57fe9..758bf403a169 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
| @@ -1960,6 +1960,9 @@ ARM 32-bit VFP control registers have the following id bit patterns: | |||
| 1960 | ARM 64-bit FP registers have the following id bit patterns: | 1960 | ARM 64-bit FP registers have the following id bit patterns: |
| 1961 | 0x4030 0000 0012 0 <regno:12> | 1961 | 0x4030 0000 0012 0 <regno:12> |
| 1962 | 1962 | ||
| 1963 | ARM firmware pseudo-registers have the following bit pattern: | ||
| 1964 | 0x4030 0000 0014 <regno:16> | ||
| 1965 | |||
| 1963 | 1966 | ||
| 1964 | arm64 registers are mapped using the lower 32 bits. The upper 16 of | 1967 | arm64 registers are mapped using the lower 32 bits. The upper 16 of |
| 1965 | that is the register group type, or coprocessor number: | 1968 | that is the register group type, or coprocessor number: |
| @@ -1976,6 +1979,9 @@ arm64 CCSIDR registers are demultiplexed by CSSELR value: | |||
| 1976 | arm64 system registers have the following id bit patterns: | 1979 | arm64 system registers have the following id bit patterns: |
| 1977 | 0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3> | 1980 | 0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3> |
| 1978 | 1981 | ||
| 1982 | arm64 firmware pseudo-registers have the following bit pattern: | ||
| 1983 | 0x6030 0000 0014 <regno:16> | ||
| 1984 | |||
| 1979 | 1985 | ||
| 1980 | MIPS registers are mapped using the lower 32 bits. The upper 16 of that is | 1986 | MIPS registers are mapped using the lower 32 bits. The upper 16 of that is |
| 1981 | the register group type: | 1987 | the register group type: |
| @@ -2510,7 +2516,8 @@ Possible features: | |||
| 2510 | and execute guest code when KVM_RUN is called. | 2516 | and execute guest code when KVM_RUN is called. |
| 2511 | - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. | 2517 | - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. |
| 2512 | Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). | 2518 | 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. | ||
| 2514 | Depends on KVM_CAP_ARM_PSCI_0_2. | 2521 | Depends on KVM_CAP_ARM_PSCI_0_2. |
| 2515 | - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU. | 2522 | - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU. |
| 2516 | Depends on KVM_CAP_ARM_PMU_V3. | 2523 | Depends on KVM_CAP_ARM_PMU_V3. |
diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt new file mode 100644 index 000000000000..aafdab887b04 --- /dev/null +++ b/Documentation/virtual/kvm/arm/psci.txt | |||
| @@ -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) | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 92be777d060a..151060871f5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -7753,7 +7753,7 @@ F: arch/x86/include/asm/svm.h | |||
| 7753 | F: arch/x86/kvm/svm.c | 7753 | F: arch/x86/kvm/svm.c |
| 7754 | 7754 | ||
| 7755 | KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm) | 7755 | KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm) |
| 7756 | M: Christoffer Dall <christoffer.dall@linaro.org> | 7756 | M: Christoffer Dall <christoffer.dall@arm.com> |
| 7757 | M: Marc Zyngier <marc.zyngier@arm.com> | 7757 | M: Marc Zyngier <marc.zyngier@arm.com> |
| 7758 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 7758 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 7759 | L: kvmarm@lists.cs.columbia.edu | 7759 | L: kvmarm@lists.cs.columbia.edu |
| @@ -7767,7 +7767,7 @@ F: virt/kvm/arm/ | |||
| 7767 | F: include/kvm/arm_* | 7767 | F: include/kvm/arm_* |
| 7768 | 7768 | ||
| 7769 | KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64) | 7769 | KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64) |
| 7770 | M: Christoffer Dall <christoffer.dall@linaro.org> | 7770 | M: Christoffer Dall <christoffer.dall@arm.com> |
| 7771 | M: Marc Zyngier <marc.zyngier@arm.com> | 7771 | M: Marc Zyngier <marc.zyngier@arm.com> |
| 7772 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 7772 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 7773 | L: kvmarm@lists.cs.columbia.edu | 7773 | L: kvmarm@lists.cs.columbia.edu |
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index c6a749568dd6..c7c28c885a19 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h | |||
| @@ -77,6 +77,9 @@ struct kvm_arch { | |||
| 77 | /* Interrupt controller */ | 77 | /* Interrupt controller */ |
| 78 | struct vgic_dist vgic; | 78 | struct vgic_dist vgic; |
| 79 | int max_vcpus; | 79 | int max_vcpus; |
| 80 | |||
| 81 | /* Mandated version of PSCI */ | ||
| 82 | u32 psci_version; | ||
| 80 | }; | 83 | }; |
| 81 | 84 | ||
| 82 | #define KVM_NR_MEM_OBJS 40 | 85 | #define KVM_NR_MEM_OBJS 40 |
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 2ba95d6fe852..caae4843cb70 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h | |||
| @@ -195,6 +195,12 @@ struct kvm_arch_memory_slot { | |||
| 195 | #define KVM_REG_ARM_VFP_FPINST 0x1009 | 195 | #define KVM_REG_ARM_VFP_FPINST 0x1009 |
| 196 | #define KVM_REG_ARM_VFP_FPINST2 0x100A | 196 | #define KVM_REG_ARM_VFP_FPINST2 0x100A |
| 197 | 197 | ||
| 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 | |||
| 198 | /* Device Control API: ARM VGIC */ | 204 | /* Device Control API: ARM VGIC */ |
| 199 | #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 | 205 | #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 |
| 200 | #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 | 206 | #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 |
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784ebbfd6..a18f33edc471 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/vmalloc.h> | 23 | #include <linux/vmalloc.h> |
| 24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| 25 | #include <kvm/arm_psci.h> | ||
| 25 | #include <asm/cputype.h> | 26 | #include <asm/cputype.h> |
| 26 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
| 27 | #include <asm/kvm.h> | 28 | #include <asm/kvm.h> |
| @@ -176,6 +177,7 @@ static unsigned long num_core_regs(void) | |||
| 176 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) | 177 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) |
| 177 | { | 178 | { |
| 178 | return num_core_regs() + kvm_arm_num_coproc_regs(vcpu) | 179 | return num_core_regs() + kvm_arm_num_coproc_regs(vcpu) |
| 180 | + kvm_arm_get_fw_num_regs(vcpu) | ||
| 179 | + NUM_TIMER_REGS; | 181 | + NUM_TIMER_REGS; |
| 180 | } | 182 | } |
| 181 | 183 | ||
| @@ -196,6 +198,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) | |||
| 196 | uindices++; | 198 | uindices++; |
| 197 | } | 199 | } |
| 198 | 200 | ||
| 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 | |||
| 199 | ret = copy_timer_indices(vcpu, uindices); | 206 | ret = copy_timer_indices(vcpu, uindices); |
| 200 | if (ret) | 207 | if (ret) |
| 201 | return ret; | 208 | return ret; |
| @@ -214,6 +221,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 214 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) | 221 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) |
| 215 | return get_core_reg(vcpu, reg); | 222 | return get_core_reg(vcpu, reg); |
| 216 | 223 | ||
| 224 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW) | ||
| 225 | return kvm_arm_get_fw_reg(vcpu, reg); | ||
| 226 | |||
| 217 | if (is_timer_reg(reg->id)) | 227 | if (is_timer_reg(reg->id)) |
| 218 | return get_timer_reg(vcpu, reg); | 228 | return get_timer_reg(vcpu, reg); |
| 219 | 229 | ||
| @@ -230,6 +240,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 230 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) | 240 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) |
| 231 | return set_core_reg(vcpu, reg); | 241 | return set_core_reg(vcpu, reg); |
| 232 | 242 | ||
| 243 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW) | ||
| 244 | return kvm_arm_set_fw_reg(vcpu, reg); | ||
| 245 | |||
| 233 | if (is_timer_reg(reg->id)) | 246 | if (is_timer_reg(reg->id)) |
| 234 | return set_timer_reg(vcpu, reg); | 247 | return set_timer_reg(vcpu, reg); |
| 235 | 248 | ||
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index ab46bc70add6..469de8acd06f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h | |||
| @@ -75,6 +75,9 @@ struct kvm_arch { | |||
| 75 | 75 | ||
| 76 | /* Interrupt controller */ | 76 | /* Interrupt controller */ |
| 77 | struct vgic_dist vgic; | 77 | struct vgic_dist vgic; |
| 78 | |||
| 79 | /* Mandated version of PSCI */ | ||
| 80 | u32 psci_version; | ||
| 78 | }; | 81 | }; |
| 79 | 82 | ||
| 80 | #define KVM_NR_MEM_OBJS 40 | 83 | #define KVM_NR_MEM_OBJS 40 |
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 9abbf3044654..04b3256f8e6d 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h | |||
| @@ -206,6 +206,12 @@ struct kvm_arch_memory_slot { | |||
| 206 | #define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2) | 206 | #define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2) |
| 207 | #define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2) | 207 | #define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2) |
| 208 | 208 | ||
| 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 | |||
| 209 | /* Device Control API: ARM VGIC */ | 215 | /* Device Control API: ARM VGIC */ |
| 210 | #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 | 216 | #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 |
| 211 | #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 | 217 | #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 |
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 959e50d2588c..56a0260ceb11 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 26 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
| 27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
| 28 | #include <kvm/arm_psci.h> | ||
| 28 | #include <asm/cputype.h> | 29 | #include <asm/cputype.h> |
| 29 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
| 30 | #include <asm/kvm.h> | 31 | #include <asm/kvm.h> |
| @@ -205,7 +206,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 205 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) | 206 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) |
| 206 | { | 207 | { |
| 207 | return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu) | 208 | 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; |
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | /** | 212 | /** |
| @@ -225,6 +226,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) | |||
| 225 | uindices++; | 226 | uindices++; |
| 226 | } | 227 | } |
| 227 | 228 | ||
| 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 | |||
| 228 | ret = copy_timer_indices(vcpu, uindices); | 234 | ret = copy_timer_indices(vcpu, uindices); |
| 229 | if (ret) | 235 | if (ret) |
| 230 | return ret; | 236 | return ret; |
| @@ -243,6 +249,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 243 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) | 249 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) |
| 244 | return get_core_reg(vcpu, reg); | 250 | return get_core_reg(vcpu, reg); |
| 245 | 251 | ||
| 252 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW) | ||
| 253 | return kvm_arm_get_fw_reg(vcpu, reg); | ||
| 254 | |||
| 246 | if (is_timer_reg(reg->id)) | 255 | if (is_timer_reg(reg->id)) |
| 247 | return get_timer_reg(vcpu, reg); | 256 | return get_timer_reg(vcpu, reg); |
| 248 | 257 | ||
| @@ -259,6 +268,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) | |||
| 259 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) | 268 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) |
| 260 | return set_core_reg(vcpu, reg); | 269 | return set_core_reg(vcpu, reg); |
| 261 | 270 | ||
| 271 | if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW) | ||
| 272 | return kvm_arm_set_fw_reg(vcpu, reg); | ||
| 273 | |||
| 262 | if (is_timer_reg(reg->id)) | 274 | if (is_timer_reg(reg->id)) |
| 263 | return set_timer_reg(vcpu, reg); | 275 | return set_timer_reg(vcpu, reg); |
| 264 | 276 | ||
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 806b0b126a64..6e3b969391fd 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c | |||
| @@ -996,14 +996,12 @@ static u64 read_id_reg(struct sys_reg_desc const *r, bool raz) | |||
| 996 | 996 | ||
| 997 | if (id == SYS_ID_AA64PFR0_EL1) { | 997 | if (id == SYS_ID_AA64PFR0_EL1) { |
| 998 | if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT)) | 998 | if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT)) |
| 999 | pr_err_once("kvm [%i]: SVE unsupported for guests, suppressing\n", | 999 | kvm_debug("SVE unsupported for guests, suppressing\n"); |
| 1000 | task_pid_nr(current)); | ||
| 1001 | 1000 | ||
| 1002 | val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT); | 1001 | val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT); |
| 1003 | } else if (id == SYS_ID_AA64MMFR1_EL1) { | 1002 | } else if (id == SYS_ID_AA64MMFR1_EL1) { |
| 1004 | if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT)) | 1003 | if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT)) |
| 1005 | pr_err_once("kvm [%i]: LORegions unsupported for guests, suppressing\n", | 1004 | kvm_debug("LORegions unsupported for guests, suppressing\n"); |
| 1006 | task_pid_nr(current)); | ||
| 1007 | 1005 | ||
| 1008 | val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT); | 1006 | val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT); |
| 1009 | } | 1007 | } |
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h index e518e4e3dfb5..4b1548129fa2 100644 --- a/include/kvm/arm_psci.h +++ b/include/kvm/arm_psci.h | |||
| @@ -37,10 +37,15 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm) | |||
| 37 | * Our PSCI implementation stays the same across versions from | 37 | * Our PSCI implementation stays the same across versions from |
| 38 | * v0.2 onward, only adding the few mandatory functions (such | 38 | * v0.2 onward, only adding the few mandatory functions (such |
| 39 | * as FEATURES with 1.0) that are required by newer | 39 | * 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. | ||
| 41 | */ | 42 | */ |
| 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 | |||
| 43 | return KVM_ARM_PSCI_LATEST; | 47 | return KVM_ARM_PSCI_LATEST; |
| 48 | } | ||
| 44 | 49 | ||
| 45 | return KVM_ARM_PSCI_0_1; | 50 | return KVM_ARM_PSCI_0_1; |
| 46 | } | 51 | } |
| @@ -48,4 +53,11 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm) | |||
| 48 | 53 | ||
| 49 | int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); | 54 | int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); |
| 50 | 55 | ||
| 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 | |||
| 51 | #endif /* __KVM_ARM_PSCI_H__ */ | 63 | #endif /* __KVM_ARM_PSCI_H__ */ |
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index dba629c5f8ac..a4c1b76240df 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c | |||
| @@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); | |||
| 63 | static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); | 63 | static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); |
| 64 | static u32 kvm_next_vmid; | 64 | static u32 kvm_next_vmid; |
| 65 | static unsigned int kvm_vmid_bits __read_mostly; | 65 | static unsigned int kvm_vmid_bits __read_mostly; |
| 66 | static DEFINE_SPINLOCK(kvm_vmid_lock); | 66 | static DEFINE_RWLOCK(kvm_vmid_lock); |
| 67 | 67 | ||
| 68 | static bool vgic_present; | 68 | static bool vgic_present; |
| 69 | 69 | ||
| @@ -473,11 +473,16 @@ static void update_vttbr(struct kvm *kvm) | |||
| 473 | { | 473 | { |
| 474 | phys_addr_t pgd_phys; | 474 | phys_addr_t pgd_phys; |
| 475 | u64 vmid; | 475 | u64 vmid; |
| 476 | bool new_gen; | ||
| 476 | 477 | ||
| 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) | ||
| 478 | return; | 483 | return; |
| 479 | 484 | ||
| 480 | spin_lock(&kvm_vmid_lock); | 485 | write_lock(&kvm_vmid_lock); |
| 481 | 486 | ||
| 482 | /* | 487 | /* |
| 483 | * We need to re-check the vmid_gen here to ensure that if another vcpu | 488 | * We need to re-check the vmid_gen here to ensure that if another vcpu |
| @@ -485,7 +490,7 @@ static void update_vttbr(struct kvm *kvm) | |||
| 485 | * use the same vmid. | 490 | * use the same vmid. |
| 486 | */ | 491 | */ |
| 487 | if (!need_new_vmid_gen(kvm)) { | 492 | if (!need_new_vmid_gen(kvm)) { |
| 488 | spin_unlock(&kvm_vmid_lock); | 493 | write_unlock(&kvm_vmid_lock); |
| 489 | return; | 494 | return; |
| 490 | } | 495 | } |
| 491 | 496 | ||
| @@ -519,7 +524,7 @@ static void update_vttbr(struct kvm *kvm) | |||
| 519 | vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits); | 524 | vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits); |
| 520 | kvm->arch.vttbr = kvm_phys_to_vttbr(pgd_phys) | vmid; | 525 | kvm->arch.vttbr = kvm_phys_to_vttbr(pgd_phys) | vmid; |
| 521 | 526 | ||
| 522 | spin_unlock(&kvm_vmid_lock); | 527 | write_unlock(&kvm_vmid_lock); |
| 523 | } | 528 | } |
| 524 | 529 | ||
| 525 | static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | 530 | static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) |
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index 6919352cbf15..c4762bef13c6 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/arm-smccc.h> | 18 | #include <linux/arm-smccc.h> |
| 19 | #include <linux/preempt.h> | 19 | #include <linux/preempt.h> |
| 20 | #include <linux/kvm_host.h> | 20 | #include <linux/kvm_host.h> |
| 21 | #include <linux/uaccess.h> | ||
| 21 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
| 22 | 23 | ||
| 23 | #include <asm/cputype.h> | 24 | #include <asm/cputype.h> |
| @@ -427,3 +428,62 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) | |||
| 427 | smccc_set_retval(vcpu, val, 0, 0, 0); | 428 | smccc_set_retval(vcpu, val, 0, 0, 0); |
| 428 | return 1; | 429 | return 1; |
| 429 | } | 430 | } |
| 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 | } | ||
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index e74baec76361..4b6d72939c42 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c | |||
| @@ -594,6 +594,7 @@ retry: | |||
| 594 | 594 | ||
| 595 | list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) { | 595 | list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) { |
| 596 | struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB; | 596 | struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB; |
| 597 | bool target_vcpu_needs_kick = false; | ||
| 597 | 598 | ||
| 598 | spin_lock(&irq->irq_lock); | 599 | spin_lock(&irq->irq_lock); |
| 599 | 600 | ||
| @@ -664,11 +665,18 @@ retry: | |||
| 664 | list_del(&irq->ap_list); | 665 | list_del(&irq->ap_list); |
| 665 | irq->vcpu = target_vcpu; | 666 | irq->vcpu = target_vcpu; |
| 666 | list_add_tail(&irq->ap_list, &new_cpu->ap_list_head); | 667 | list_add_tail(&irq->ap_list, &new_cpu->ap_list_head); |
| 668 | target_vcpu_needs_kick = true; | ||
| 667 | } | 669 | } |
| 668 | 670 | ||
| 669 | spin_unlock(&irq->irq_lock); | 671 | spin_unlock(&irq->irq_lock); |
| 670 | spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock); | 672 | spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock); |
| 671 | spin_unlock_irqrestore(&vcpuA->arch.vgic_cpu.ap_list_lock, flags); | 673 | spin_unlock_irqrestore(&vcpuA->arch.vgic_cpu.ap_list_lock, flags); |
| 674 | |||
| 675 | if (target_vcpu_needs_kick) { | ||
| 676 | kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu); | ||
| 677 | kvm_vcpu_kick(target_vcpu); | ||
| 678 | } | ||
| 679 | |||
| 672 | goto retry; | 680 | goto retry; |
| 673 | } | 681 | } |
| 674 | 682 | ||
