diff options
| -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-- | arch/x86/kvm/vmx.c | 14 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.h | 7 | ||||
| -rw-r--r-- | include/kvm/arm_psci.h | 16 | ||||
| -rw-r--r-- | include/uapi/linux/kvm.h | 7 | ||||
| -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 |
17 files changed, 189 insertions, 32 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 3e41e12a88a4..db2bc3fe0ba4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -7744,7 +7744,7 @@ F: arch/x86/include/asm/svm.h | |||
| 7744 | F: arch/x86/kvm/svm.c | 7744 | F: arch/x86/kvm/svm.c |
| 7745 | 7745 | ||
| 7746 | KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm) | 7746 | KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm) |
| 7747 | M: Christoffer Dall <christoffer.dall@linaro.org> | 7747 | M: Christoffer Dall <christoffer.dall@arm.com> |
| 7748 | M: Marc Zyngier <marc.zyngier@arm.com> | 7748 | M: Marc Zyngier <marc.zyngier@arm.com> |
| 7749 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 7749 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 7750 | L: kvmarm@lists.cs.columbia.edu | 7750 | L: kvmarm@lists.cs.columbia.edu |
| @@ -7758,7 +7758,7 @@ F: virt/kvm/arm/ | |||
| 7758 | F: include/kvm/arm_* | 7758 | F: include/kvm/arm_* |
| 7759 | 7759 | ||
| 7760 | KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64) | 7760 | KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64) |
| 7761 | M: Christoffer Dall <christoffer.dall@linaro.org> | 7761 | M: Christoffer Dall <christoffer.dall@arm.com> |
| 7762 | M: Marc Zyngier <marc.zyngier@arm.com> | 7762 | M: Marc Zyngier <marc.zyngier@arm.com> |
| 7763 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 7763 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 7764 | L: kvmarm@lists.cs.columbia.edu | 7764 | 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) | ||
