diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s_xics.c')
-rw-r--r-- | arch/powerpc/kvm/book3s_xics.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index 1417e65b6bbd..7fd247cbd0d1 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #define XICS_DBG(fmt...) trace_printk(fmt) | 30 | #define XICS_DBG(fmt...) trace_printk(fmt) |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define ENABLE_REALMODE true | ||
34 | #define DEBUG_REALMODE false | ||
35 | |||
33 | /* | 36 | /* |
34 | * LOCKING | 37 | * LOCKING |
35 | * ======= | 38 | * ======= |
@@ -220,8 +223,10 @@ static inline bool icp_try_update(struct kvmppc_icp *icp, | |||
220 | * in Accept (H_XIRR) and Up_Cppr (H_XPPR). | 223 | * in Accept (H_XIRR) and Up_Cppr (H_XPPR). |
221 | * | 224 | * |
222 | * We also do not try to figure out whether the EE state has changed, | 225 | * We also do not try to figure out whether the EE state has changed, |
223 | * we unconditionally set it if the new state calls for it for the | 226 | * we unconditionally set it if the new state calls for it. The reason |
224 | * same reason. | 227 | * for that is that we opportunistically remove the pending interrupt |
228 | * flag when raising CPPR, so we need to set it back here if an | ||
229 | * interrupt is still pending. | ||
225 | */ | 230 | */ |
226 | if (new.out_ee) { | 231 | if (new.out_ee) { |
227 | kvmppc_book3s_queue_irqprio(icp->vcpu, | 232 | kvmppc_book3s_queue_irqprio(icp->vcpu, |
@@ -483,7 +488,7 @@ static void icp_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp, | |||
483 | icp_check_resend(xics, icp); | 488 | icp_check_resend(xics, icp); |
484 | } | 489 | } |
485 | 490 | ||
486 | static noinline unsigned long h_xirr(struct kvm_vcpu *vcpu) | 491 | static noinline unsigned long kvmppc_h_xirr(struct kvm_vcpu *vcpu) |
487 | { | 492 | { |
488 | union kvmppc_icp_state old_state, new_state; | 493 | union kvmppc_icp_state old_state, new_state; |
489 | struct kvmppc_icp *icp = vcpu->arch.icp; | 494 | struct kvmppc_icp *icp = vcpu->arch.icp; |
@@ -517,8 +522,8 @@ static noinline unsigned long h_xirr(struct kvm_vcpu *vcpu) | |||
517 | return xirr; | 522 | return xirr; |
518 | } | 523 | } |
519 | 524 | ||
520 | static noinline int h_ipi(struct kvm_vcpu *vcpu, unsigned long server, | 525 | static noinline int kvmppc_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, |
521 | unsigned long mfrr) | 526 | unsigned long mfrr) |
522 | { | 527 | { |
523 | union kvmppc_icp_state old_state, new_state; | 528 | union kvmppc_icp_state old_state, new_state; |
524 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; | 529 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; |
@@ -586,7 +591,7 @@ static noinline int h_ipi(struct kvm_vcpu *vcpu, unsigned long server, | |||
586 | return H_SUCCESS; | 591 | return H_SUCCESS; |
587 | } | 592 | } |
588 | 593 | ||
589 | static noinline void h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) | 594 | static noinline void kvmppc_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) |
590 | { | 595 | { |
591 | union kvmppc_icp_state old_state, new_state; | 596 | union kvmppc_icp_state old_state, new_state; |
592 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; | 597 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; |
@@ -643,7 +648,7 @@ static noinline void h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) | |||
643 | icp_deliver_irq(xics, icp, reject); | 648 | icp_deliver_irq(xics, icp, reject); |
644 | } | 649 | } |
645 | 650 | ||
646 | static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) | 651 | static noinline int kvmppc_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) |
647 | { | 652 | { |
648 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; | 653 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; |
649 | struct kvmppc_icp *icp = vcpu->arch.icp; | 654 | struct kvmppc_icp *icp = vcpu->arch.icp; |
@@ -693,29 +698,54 @@ static noinline int h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) | |||
693 | return H_SUCCESS; | 698 | return H_SUCCESS; |
694 | } | 699 | } |
695 | 700 | ||
701 | static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall) | ||
702 | { | ||
703 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; | ||
704 | struct kvmppc_icp *icp = vcpu->arch.icp; | ||
705 | |||
706 | XICS_DBG("XICS_RM: H_%x completing, act: %x state: %lx tgt: %p\n", | ||
707 | hcall, icp->rm_action, icp->rm_dbgstate.raw, icp->rm_dbgtgt); | ||
708 | |||
709 | if (icp->rm_action & XICS_RM_KICK_VCPU) | ||
710 | kvmppc_fast_vcpu_kick(icp->rm_kick_target); | ||
711 | if (icp->rm_action & XICS_RM_CHECK_RESEND) | ||
712 | icp_check_resend(xics, icp); | ||
713 | if (icp->rm_action & XICS_RM_REJECT) | ||
714 | icp_deliver_irq(xics, icp, icp->rm_reject); | ||
715 | |||
716 | icp->rm_action = 0; | ||
717 | |||
718 | return H_SUCCESS; | ||
719 | } | ||
720 | |||
696 | int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req) | 721 | int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req) |
697 | { | 722 | { |
723 | struct kvmppc_xics *xics = vcpu->kvm->arch.xics; | ||
698 | unsigned long res; | 724 | unsigned long res; |
699 | int rc = H_SUCCESS; | 725 | int rc = H_SUCCESS; |
700 | 726 | ||
701 | /* Check if we have an ICP */ | 727 | /* Check if we have an ICP */ |
702 | if (!vcpu->arch.icp || !vcpu->kvm->arch.xics) | 728 | if (!xics || !vcpu->arch.icp) |
703 | return H_HARDWARE; | 729 | return H_HARDWARE; |
704 | 730 | ||
731 | /* Check for real mode returning too hard */ | ||
732 | if (xics->real_mode) | ||
733 | return kvmppc_xics_rm_complete(vcpu, req); | ||
734 | |||
705 | switch (req) { | 735 | switch (req) { |
706 | case H_XIRR: | 736 | case H_XIRR: |
707 | res = h_xirr(vcpu); | 737 | res = kvmppc_h_xirr(vcpu); |
708 | kvmppc_set_gpr(vcpu, 4, res); | 738 | kvmppc_set_gpr(vcpu, 4, res); |
709 | break; | 739 | break; |
710 | case H_CPPR: | 740 | case H_CPPR: |
711 | h_cppr(vcpu, kvmppc_get_gpr(vcpu, 4)); | 741 | kvmppc_h_cppr(vcpu, kvmppc_get_gpr(vcpu, 4)); |
712 | break; | 742 | break; |
713 | case H_EOI: | 743 | case H_EOI: |
714 | rc = h_eoi(vcpu, kvmppc_get_gpr(vcpu, 4)); | 744 | rc = kvmppc_h_eoi(vcpu, kvmppc_get_gpr(vcpu, 4)); |
715 | break; | 745 | break; |
716 | case H_IPI: | 746 | case H_IPI: |
717 | rc = h_ipi(vcpu, kvmppc_get_gpr(vcpu, 4), | 747 | rc = kvmppc_h_ipi(vcpu, kvmppc_get_gpr(vcpu, 4), |
718 | kvmppc_get_gpr(vcpu, 5)); | 748 | kvmppc_get_gpr(vcpu, 5)); |
719 | break; | 749 | break; |
720 | } | 750 | } |
721 | 751 | ||
@@ -933,6 +963,14 @@ int kvm_xics_create(struct kvm *kvm, u32 type) | |||
933 | 963 | ||
934 | xics_debugfs_init(xics); | 964 | xics_debugfs_init(xics); |
935 | 965 | ||
966 | #ifdef CONFIG_KVM_BOOK3S_64_HV | ||
967 | if (cpu_has_feature(CPU_FTR_ARCH_206)) { | ||
968 | /* Enable real mode support */ | ||
969 | xics->real_mode = ENABLE_REALMODE; | ||
970 | xics->real_mode_dbg = DEBUG_REALMODE; | ||
971 | } | ||
972 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | ||
973 | |||
936 | return 0; | 974 | return 0; |
937 | } | 975 | } |
938 | 976 | ||