diff options
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 43 | ||||
-rw-r--r-- | arch/arm/kvm/guest.c | 25 | ||||
-rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/arm64/kvm/guest.c | 25 |
6 files changed, 48 insertions, 54 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index bb82a906e51e..81f1b974c06a 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -2453,6 +2453,11 @@ return ENOEXEC for that vcpu. | |||
2453 | Note that because some registers reflect machine topology, all vcpus | 2453 | Note that because some registers reflect machine topology, all vcpus |
2454 | should be created before this ioctl is invoked. | 2454 | should be created before this ioctl is invoked. |
2455 | 2455 | ||
2456 | Userspace can call this function multiple times for a given vcpu, including | ||
2457 | after the vcpu has been run. This will reset the vcpu to its initial | ||
2458 | state. All calls to this function after the initial call must use the same | ||
2459 | target and same set of feature flags, otherwise EINVAL will be returned. | ||
2460 | |||
2456 | Possible features: | 2461 | Possible features: |
2457 | - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state. | 2462 | - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state. |
2458 | Depends on KVM_CAP_ARM_PSCI. If not set, the CPU will be powered on | 2463 | Depends on KVM_CAP_ARM_PSCI. If not set, the CPU will be powered on |
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 53036e21756b..254e0650e48b 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h | |||
@@ -150,8 +150,6 @@ struct kvm_vcpu_stat { | |||
150 | u32 halt_wakeup; | 150 | u32 halt_wakeup; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | ||
154 | const struct kvm_vcpu_init *init); | ||
155 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); | 153 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); |
156 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); | 154 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); |
157 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); | 155 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); |
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 24c9ca4076b2..4043769583e7 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -263,6 +263,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | |||
263 | { | 263 | { |
264 | /* Force users to call KVM_ARM_VCPU_INIT */ | 264 | /* Force users to call KVM_ARM_VCPU_INIT */ |
265 | vcpu->arch.target = -1; | 265 | vcpu->arch.target = -1; |
266 | bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); | ||
266 | 267 | ||
267 | /* Set up the timer */ | 268 | /* Set up the timer */ |
268 | kvm_timer_vcpu_init(vcpu); | 269 | kvm_timer_vcpu_init(vcpu); |
@@ -649,6 +650,48 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, | |||
649 | return -EINVAL; | 650 | return -EINVAL; |
650 | } | 651 | } |
651 | 652 | ||
653 | static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | ||
654 | const struct kvm_vcpu_init *init) | ||
655 | { | ||
656 | unsigned int i; | ||
657 | int phys_target = kvm_target_cpu(); | ||
658 | |||
659 | if (init->target != phys_target) | ||
660 | return -EINVAL; | ||
661 | |||
662 | /* | ||
663 | * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must | ||
664 | * use the same target. | ||
665 | */ | ||
666 | if (vcpu->arch.target != -1 && vcpu->arch.target != init->target) | ||
667 | return -EINVAL; | ||
668 | |||
669 | /* -ENOENT for unknown features, -EINVAL for invalid combinations. */ | ||
670 | for (i = 0; i < sizeof(init->features) * 8; i++) { | ||
671 | bool set = (init->features[i / 32] & (1 << (i % 32))); | ||
672 | |||
673 | if (set && i >= KVM_VCPU_MAX_FEATURES) | ||
674 | return -ENOENT; | ||
675 | |||
676 | /* | ||
677 | * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must | ||
678 | * use the same feature set. | ||
679 | */ | ||
680 | if (vcpu->arch.target != -1 && i < KVM_VCPU_MAX_FEATURES && | ||
681 | test_bit(i, vcpu->arch.features) != set) | ||
682 | return -EINVAL; | ||
683 | |||
684 | if (set) | ||
685 | set_bit(i, vcpu->arch.features); | ||
686 | } | ||
687 | |||
688 | vcpu->arch.target = phys_target; | ||
689 | |||
690 | /* Now we know what it is, we can reset it. */ | ||
691 | return kvm_reset_vcpu(vcpu); | ||
692 | } | ||
693 | |||
694 | |||
652 | static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, | 695 | static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, |
653 | struct kvm_vcpu_init *init) | 696 | struct kvm_vcpu_init *init) |
654 | { | 697 | { |
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 8c97208b9b97..384bab67c462 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c | |||
@@ -273,31 +273,6 @@ int __attribute_const__ kvm_target_cpu(void) | |||
273 | } | 273 | } |
274 | } | 274 | } |
275 | 275 | ||
276 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | ||
277 | const struct kvm_vcpu_init *init) | ||
278 | { | ||
279 | unsigned int i; | ||
280 | |||
281 | /* We can only cope with guest==host and only on A15/A7 (for now). */ | ||
282 | if (init->target != kvm_target_cpu()) | ||
283 | return -EINVAL; | ||
284 | |||
285 | vcpu->arch.target = init->target; | ||
286 | bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); | ||
287 | |||
288 | /* -ENOENT for unknown features, -EINVAL for invalid combinations. */ | ||
289 | for (i = 0; i < sizeof(init->features) * 8; i++) { | ||
290 | if (test_bit(i, (void *)init->features)) { | ||
291 | if (i >= KVM_VCPU_MAX_FEATURES) | ||
292 | return -ENOENT; | ||
293 | set_bit(i, vcpu->arch.features); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | /* Now we know what it is, we can reset it. */ | ||
298 | return kvm_reset_vcpu(vcpu); | ||
299 | } | ||
300 | |||
301 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) | 276 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) |
302 | { | 277 | { |
303 | int target = kvm_target_cpu(); | 278 | int target = kvm_target_cpu(); |
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2012c4ba8d67..65c615294589 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h | |||
@@ -165,8 +165,6 @@ struct kvm_vcpu_stat { | |||
165 | u32 halt_wakeup; | 165 | u32 halt_wakeup; |
166 | }; | 166 | }; |
167 | 167 | ||
168 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | ||
169 | const struct kvm_vcpu_init *init); | ||
170 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); | 168 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init); |
171 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); | 169 | unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); |
172 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); | 170 | int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); |
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 84d5959ff874..9535bd555d1d 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c | |||
@@ -296,31 +296,6 @@ int __attribute_const__ kvm_target_cpu(void) | |||
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
299 | int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, | ||
300 | const struct kvm_vcpu_init *init) | ||
301 | { | ||
302 | unsigned int i; | ||
303 | int phys_target = kvm_target_cpu(); | ||
304 | |||
305 | if (init->target != phys_target) | ||
306 | return -EINVAL; | ||
307 | |||
308 | vcpu->arch.target = phys_target; | ||
309 | bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); | ||
310 | |||
311 | /* -ENOENT for unknown features, -EINVAL for invalid combinations. */ | ||
312 | for (i = 0; i < sizeof(init->features) * 8; i++) { | ||
313 | if (init->features[i / 32] & (1 << (i % 32))) { | ||
314 | if (i >= KVM_VCPU_MAX_FEATURES) | ||
315 | return -ENOENT; | ||
316 | set_bit(i, vcpu->arch.features); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | /* Now we know what it is, we can reset it. */ | ||
321 | return kvm_reset_vcpu(vcpu); | ||
322 | } | ||
323 | |||
324 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) | 299 | int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) |
325 | { | 300 | { |
326 | int target = kvm_target_cpu(); | 301 | int target = kvm_target_cpu(); |