aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-01-04 12:12:48 -0500
committerAlexander Graf <agraf@suse.de>2013-01-10 07:42:31 -0500
commit1c810636556c8d53a37406b34a64d9b9b0161aa6 (patch)
treeb163d427c9dcff066330d4ac13de529a9831a044 /arch
parent37ecb257f68ce4fb7c7048a1123bbcbbe36d9575 (diff)
KVM: PPC: BookE: Implement EPR exit
The External Proxy Facility in FSL BookE chips allows the interrupt controller to automatically acknowledge an interrupt as soon as a core gets its pending external interrupt delivered. Today, user space implements the interrupt controller, so we need to check on it during such a cycle. This patch implements logic for user space to enable EPR exiting, disable EPR exiting and EPR exiting itself, so that user space can acknowledge an interrupt when an external interrupt has successfully been delivered into the guest vcpu. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h9
-rw-r--r--arch/powerpc/kvm/booke.c14
-rw-r--r--arch/powerpc/kvm/powerpc.c10
4 files changed, 34 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index ab49c6cf891c..8a72d59467eb 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -520,6 +520,8 @@ struct kvm_vcpu_arch {
520 u8 sane; 520 u8 sane;
521 u8 cpu_type; 521 u8 cpu_type;
522 u8 hcall_needed; 522 u8 hcall_needed;
523 u8 epr_enabled;
524 u8 epr_needed;
523 525
524 u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ 526 u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
525 527
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 5f5f69abd281..493630e209c8 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -264,6 +264,15 @@ static inline void kvm_linear_init(void)
264{} 264{}
265#endif 265#endif
266 266
267static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
268{
269#ifdef CONFIG_KVM_BOOKE_HV
270 mtspr(SPRN_GEPR, epr);
271#elif defined(CONFIG_BOOKE)
272 vcpu->arch.epr = epr;
273#endif
274}
275
267int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu, 276int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
268 struct kvm_config_tlb *cfg); 277 struct kvm_config_tlb *cfg);
269int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, 278int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 964f4475f55c..940ec806187e 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -306,7 +306,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
306{ 306{
307 int allowed = 0; 307 int allowed = 0;
308 ulong msr_mask = 0; 308 ulong msr_mask = 0;
309 bool update_esr = false, update_dear = false; 309 bool update_esr = false, update_dear = false, update_epr = false;
310 ulong crit_raw = vcpu->arch.shared->critical; 310 ulong crit_raw = vcpu->arch.shared->critical;
311 ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); 311 ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
312 bool crit; 312 bool crit;
@@ -330,6 +330,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
330 keep_irq = true; 330 keep_irq = true;
331 } 331 }
332 332
333 if ((priority == BOOKE_IRQPRIO_EXTERNAL) && vcpu->arch.epr_enabled)
334 update_epr = true;
335
333 switch (priority) { 336 switch (priority) {
334 case BOOKE_IRQPRIO_DTLB_MISS: 337 case BOOKE_IRQPRIO_DTLB_MISS:
335 case BOOKE_IRQPRIO_DATA_STORAGE: 338 case BOOKE_IRQPRIO_DATA_STORAGE:
@@ -408,6 +411,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
408 set_guest_esr(vcpu, vcpu->arch.queued_esr); 411 set_guest_esr(vcpu, vcpu->arch.queued_esr);
409 if (update_dear == true) 412 if (update_dear == true)
410 set_guest_dear(vcpu, vcpu->arch.queued_dear); 413 set_guest_dear(vcpu, vcpu->arch.queued_dear);
414 if (update_epr == true)
415 kvm_make_request(KVM_REQ_EPR_EXIT, vcpu);
411 416
412 new_msr &= msr_mask; 417 new_msr &= msr_mask;
413#if defined(CONFIG_64BIT) 418#if defined(CONFIG_64BIT)
@@ -615,6 +620,13 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
615 r = 0; 620 r = 0;
616 } 621 }
617 622
623 if (kvm_check_request(KVM_REQ_EPR_EXIT, vcpu)) {
624 vcpu->run->epr.epr = 0;
625 vcpu->arch.epr_needed = true;
626 vcpu->run->exit_reason = KVM_EXIT_EPR;
627 r = 0;
628 }
629
618 return r; 630 return r;
619} 631}
620 632
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index e2225e5b8a4c..934413cd3a1b 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -306,6 +306,7 @@ int kvm_dev_ioctl_check_extension(long ext)
306#ifdef CONFIG_BOOKE 306#ifdef CONFIG_BOOKE
307 case KVM_CAP_PPC_BOOKE_SREGS: 307 case KVM_CAP_PPC_BOOKE_SREGS:
308 case KVM_CAP_PPC_BOOKE_WATCHDOG: 308 case KVM_CAP_PPC_BOOKE_WATCHDOG:
309 case KVM_CAP_PPC_EPR:
309#else 310#else
310 case KVM_CAP_PPC_SEGSTATE: 311 case KVM_CAP_PPC_SEGSTATE:
311 case KVM_CAP_PPC_HIOR: 312 case KVM_CAP_PPC_HIOR:
@@ -721,6 +722,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
721 for (i = 0; i < 9; ++i) 722 for (i = 0; i < 9; ++i)
722 kvmppc_set_gpr(vcpu, 4 + i, run->papr_hcall.args[i]); 723 kvmppc_set_gpr(vcpu, 4 + i, run->papr_hcall.args[i]);
723 vcpu->arch.hcall_needed = 0; 724 vcpu->arch.hcall_needed = 0;
725#ifdef CONFIG_BOOKE
726 } else if (vcpu->arch.epr_needed) {
727 kvmppc_set_epr(vcpu, run->epr.epr);
728 vcpu->arch.epr_needed = 0;
729#endif
724 } 730 }
725 731
726 r = kvmppc_vcpu_run(run, vcpu); 732 r = kvmppc_vcpu_run(run, vcpu);
@@ -762,6 +768,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
762 r = 0; 768 r = 0;
763 vcpu->arch.papr_enabled = true; 769 vcpu->arch.papr_enabled = true;
764 break; 770 break;
771 case KVM_CAP_PPC_EPR:
772 r = 0;
773 vcpu->arch.epr_enabled = cap->args[0];
774 break;
765#ifdef CONFIG_BOOKE 775#ifdef CONFIG_BOOKE
766 case KVM_CAP_PPC_BOOKE_WATCHDOG: 776 case KVM_CAP_PPC_BOOKE_WATCHDOG:
767 r = 0; 777 r = 0;