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(); |
