aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-01-11 21:37:16 -0500
committerPaul Mackerras <paulus@ozlabs.org>2018-01-18 20:10:21 -0500
commit9b9b13a6d1537ddc4caccd6f1c41b78edbc08437 (patch)
tree6f276be60ff3f994a9c2bd47b1ff2afcbc734586
parent35c2405efc0142860c4b698f4c6331567c4ca1ef (diff)
KVM: PPC: Book3S HV: Keep XIVE escalation interrupt masked unless ceded
This works on top of the single escalation support. When in single escalation, with this change, we will keep the escalation interrupt disabled unless the VCPU is in H_CEDE (idle). In any other case, we know the VCPU will be rescheduled and thus there is no need to take escalation interrupts in the host whenever a guest interrupt fires. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
-rw-r--r--arch/powerpc/include/asm/kvm_host.h3
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S62
-rw-r--r--arch/powerpc/kvm/book3s_xive.c30
4 files changed, 97 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 0c44fa67608d..fef8133becc8 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -740,7 +740,10 @@ struct kvm_vcpu_arch {
740 struct kvmppc_xive_vcpu *xive_vcpu; /* XIVE virtual CPU data */ 740 struct kvmppc_xive_vcpu *xive_vcpu; /* XIVE virtual CPU data */
741 __be32 xive_cam_word; /* Cooked W2 in proper endian with valid bit */ 741 __be32 xive_cam_word; /* Cooked W2 in proper endian with valid bit */
742 u8 xive_pushed; /* Is the VP pushed on the physical CPU ? */ 742 u8 xive_pushed; /* Is the VP pushed on the physical CPU ? */
743 u8 xive_esc_on; /* Is the escalation irq enabled ? */
743 union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */ 744 union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */
745 u64 xive_esc_raddr; /* Escalation interrupt ESB real addr */
746 u64 xive_esc_vaddr; /* Escalation interrupt ESB virt addr */
744#endif 747#endif
745 748
746#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 749#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 825089cf3e23..1672dffd94e2 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -734,6 +734,9 @@ int main(void)
734 DEFINE(VCPU_XIVE_CAM_WORD, offsetof(struct kvm_vcpu, 734 DEFINE(VCPU_XIVE_CAM_WORD, offsetof(struct kvm_vcpu,
735 arch.xive_cam_word)); 735 arch.xive_cam_word));
736 DEFINE(VCPU_XIVE_PUSHED, offsetof(struct kvm_vcpu, arch.xive_pushed)); 736 DEFINE(VCPU_XIVE_PUSHED, offsetof(struct kvm_vcpu, arch.xive_pushed));
737 DEFINE(VCPU_XIVE_ESC_ON, offsetof(struct kvm_vcpu, arch.xive_esc_on));
738 DEFINE(VCPU_XIVE_ESC_RADDR, offsetof(struct kvm_vcpu, arch.xive_esc_raddr));
739 DEFINE(VCPU_XIVE_ESC_VADDR, offsetof(struct kvm_vcpu, arch.xive_esc_vaddr));
737#endif 740#endif
738 741
739#ifdef CONFIG_KVM_EXIT_TIMING 742#ifdef CONFIG_KVM_EXIT_TIMING
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index a7f429bc6de0..a7a20b85d8eb 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1045,6 +1045,41 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
1045 */ 1045 */
1046 li r0,0 1046 li r0,0
1047 stb r0, VCPU_IRQ_PENDING(r4) 1047 stb r0, VCPU_IRQ_PENDING(r4)
1048
1049 /*
1050 * In single escalation mode, if the escalation interrupt is
1051 * on, we mask it.
1052 */
1053 lbz r0, VCPU_XIVE_ESC_ON(r4)
1054 cmpwi r0,0
1055 beq 1f
1056 ld r10, VCPU_XIVE_ESC_RADDR(r4)
1057 li r9, XIVE_ESB_SET_PQ_01
1058 ldcix r0, r10, r9
1059 sync
1060
1061 /* We have a possible subtle race here: The escalation interrupt might
1062 * have fired and be on its way to the host queue while we mask it,
1063 * and if we unmask it early enough (re-cede right away), there is
1064 * a theorical possibility that it fires again, thus landing in the
1065 * target queue more than once which is a big no-no.
1066 *
1067 * Fortunately, solving this is rather easy. If the above load setting
1068 * PQ to 01 returns a previous value where P is set, then we know the
1069 * escalation interrupt is somewhere on its way to the host. In that
1070 * case we simply don't clear the xive_esc_on flag below. It will be
1071 * eventually cleared by the handler for the escalation interrupt.
1072 *
1073 * Then, when doing a cede, we check that flag again before re-enabling
1074 * the escalation interrupt, and if set, we abort the cede.
1075 */
1076 andi. r0, r0, XIVE_ESB_VAL_P
1077 bne- 1f
1078
1079 /* Now P is 0, we can clear the flag */
1080 li r0, 0
1081 stb r0, VCPU_XIVE_ESC_ON(r4)
10821:
1048no_xive: 1083no_xive:
1049#endif /* CONFIG_KVM_XICS */ 1084#endif /* CONFIG_KVM_XICS */
1050 1085
@@ -2756,7 +2791,32 @@ kvm_cede_prodded:
2756 /* we've ceded but we want to give control to the host */ 2791 /* we've ceded but we want to give control to the host */
2757kvm_cede_exit: 2792kvm_cede_exit:
2758 ld r9, HSTATE_KVM_VCPU(r13) 2793 ld r9, HSTATE_KVM_VCPU(r13)
2759 b guest_exit_cont 2794#ifdef CONFIG_KVM_XICS
2795 /* Abort if we still have a pending escalation */
2796 lbz r5, VCPU_XIVE_ESC_ON(r9)
2797 cmpwi r5, 0
2798 beq 1f
2799 li r0, 0
2800 stb r0, VCPU_CEDED(r9)
28011: /* Enable XIVE escalation */
2802 li r5, XIVE_ESB_SET_PQ_00
2803 mfmsr r0
2804 andi. r0, r0, MSR_DR /* in real mode? */
2805 beq 1f
2806 ld r10, VCPU_XIVE_ESC_VADDR(r9)
2807 cmpdi r10, 0
2808 beq 3f
2809 ldx r0, r10, r5
2810 b 2f
28111: ld r10, VCPU_XIVE_ESC_RADDR(r9)
2812 cmpdi r10, 0
2813 beq 3f
2814 ldcix r0, r10, r5
28152: sync
2816 li r0, 1
2817 stb r0, VCPU_XIVE_ESC_ON(r9)
2818#endif /* CONFIG_KVM_XICS */
28193: b guest_exit_cont
2760 2820
2761 /* Try to handle a machine check in real mode */ 2821 /* Try to handle a machine check in real mode */
2762machine_check_realmode: 2822machine_check_realmode:
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
index eef9ccafdc09..7a047bc88f11 100644
--- a/arch/powerpc/kvm/book3s_xive.c
+++ b/arch/powerpc/kvm/book3s_xive.c
@@ -89,6 +89,17 @@ static irqreturn_t xive_esc_irq(int irq, void *data)
89 if (vcpu->arch.ceded) 89 if (vcpu->arch.ceded)
90 kvmppc_fast_vcpu_kick(vcpu); 90 kvmppc_fast_vcpu_kick(vcpu);
91 91
92 /* Since we have the no-EOI flag, the interrupt is effectively
93 * disabled now. Clearing xive_esc_on means we won't bother
94 * doing so on the next entry.
95 *
96 * This also allows the entry code to know that if a PQ combination
97 * of 10 is observed while xive_esc_on is true, it means the queue
98 * contains an unprocessed escalation interrupt. We don't make use of
99 * that knowledge today but might (see comment in book3s_hv_rmhandler.S)
100 */
101 vcpu->arch.xive_esc_on = false;
102
92 return IRQ_HANDLED; 103 return IRQ_HANDLED;
93} 104}
94 105
@@ -134,6 +145,25 @@ static int xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio)
134 goto error; 145 goto error;
135 } 146 }
136 xc->esc_virq_names[prio] = name; 147 xc->esc_virq_names[prio] = name;
148
149 /* In single escalation mode, we grab the ESB MMIO of the
150 * interrupt and mask it. Also populate the VCPU v/raddr
151 * of the ESB page for use by asm entry/exit code. Finally
152 * set the XIVE_IRQ_NO_EOI flag which will prevent the
153 * core code from performing an EOI on the escalation
154 * interrupt, thus leaving it effectively masked after
155 * it fires once.
156 */
157 if (xc->xive->single_escalation) {
158 struct irq_data *d = irq_get_irq_data(xc->esc_virq[prio]);
159 struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
160
161 xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01);
162 vcpu->arch.xive_esc_raddr = xd->eoi_page;
163 vcpu->arch.xive_esc_vaddr = (__force u64)xd->eoi_mmio;
164 xd->flags |= XIVE_IRQ_NO_EOI;
165 }
166
137 return 0; 167 return 0;
138error: 168error:
139 irq_dispose_mapping(xc->esc_virq[prio]); 169 irq_dispose_mapping(xc->esc_virq[prio]);