diff options
Diffstat (limited to 'arch/arm/kvm/arm.c')
-rw-r--r-- | arch/arm/kvm/arm.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 8680b9ffd2ae..2d30e3afdaf9 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/kvm_mmu.h> | 43 | #include <asm/kvm_mmu.h> |
44 | #include <asm/kvm_emulate.h> | 44 | #include <asm/kvm_emulate.h> |
45 | #include <asm/kvm_coproc.h> | 45 | #include <asm/kvm_coproc.h> |
46 | #include <asm/kvm_psci.h> | ||
46 | #include <asm/opcodes.h> | 47 | #include <asm/opcodes.h> |
47 | 48 | ||
48 | #ifdef REQUIRES_VIRT | 49 | #ifdef REQUIRES_VIRT |
@@ -160,6 +161,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
160 | case KVM_CAP_SYNC_MMU: | 161 | case KVM_CAP_SYNC_MMU: |
161 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: | 162 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: |
162 | case KVM_CAP_ONE_REG: | 163 | case KVM_CAP_ONE_REG: |
164 | case KVM_CAP_ARM_PSCI: | ||
163 | r = 1; | 165 | r = 1; |
164 | break; | 166 | break; |
165 | case KVM_CAP_COALESCED_MMIO: | 167 | case KVM_CAP_COALESCED_MMIO: |
@@ -443,14 +445,18 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
443 | trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), | 445 | trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0), |
444 | vcpu->arch.hsr & HSR_HVC_IMM_MASK); | 446 | vcpu->arch.hsr & HSR_HVC_IMM_MASK); |
445 | 447 | ||
448 | if (kvm_psci_call(vcpu)) | ||
449 | return 1; | ||
450 | |||
446 | kvm_inject_undefined(vcpu); | 451 | kvm_inject_undefined(vcpu); |
447 | return 1; | 452 | return 1; |
448 | } | 453 | } |
449 | 454 | ||
450 | static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) | 455 | static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) |
451 | { | 456 | { |
452 | /* We don't support SMC; don't do that. */ | 457 | if (kvm_psci_call(vcpu)) |
453 | kvm_debug("smc: at %08x", *vcpu_pc(vcpu)); | 458 | return 1; |
459 | |||
454 | kvm_inject_undefined(vcpu); | 460 | kvm_inject_undefined(vcpu); |
455 | return 1; | 461 | return 1; |
456 | } | 462 | } |
@@ -589,9 +595,26 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | |||
589 | return 0; | 595 | return 0; |
590 | 596 | ||
591 | vcpu->arch.has_run_once = true; | 597 | vcpu->arch.has_run_once = true; |
598 | |||
599 | /* | ||
600 | * Handle the "start in power-off" case by calling into the | ||
601 | * PSCI code. | ||
602 | */ | ||
603 | if (test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) { | ||
604 | *vcpu_reg(vcpu, 0) = KVM_PSCI_FN_CPU_OFF; | ||
605 | kvm_psci_call(vcpu); | ||
606 | } | ||
607 | |||
592 | return 0; | 608 | return 0; |
593 | } | 609 | } |
594 | 610 | ||
611 | static void vcpu_pause(struct kvm_vcpu *vcpu) | ||
612 | { | ||
613 | wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); | ||
614 | |||
615 | wait_event_interruptible(*wq, !vcpu->arch.pause); | ||
616 | } | ||
617 | |||
595 | /** | 618 | /** |
596 | * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code | 619 | * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code |
597 | * @vcpu: The VCPU pointer | 620 | * @vcpu: The VCPU pointer |
@@ -635,6 +658,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
635 | 658 | ||
636 | update_vttbr(vcpu->kvm); | 659 | update_vttbr(vcpu->kvm); |
637 | 660 | ||
661 | if (vcpu->arch.pause) | ||
662 | vcpu_pause(vcpu); | ||
663 | |||
638 | local_irq_disable(); | 664 | local_irq_disable(); |
639 | 665 | ||
640 | /* | 666 | /* |