Skip to contentSkip to conversation

powerpc/xive: Remove incorrect debug code

PATCH New Benjamin Herrenschmidt 1 participant 16 messages Jan 11, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v3 1/16 powerpc/xive: Remove incorrect debug code

WORD2 if the TIMA isn't byte accessible and
isn't that useful to know about, take out the
pr_devel statement.

---
 arch/powerpc/sysdev/xive/common.c | 5 -----
 1 file changed, 5 deletions(-)
arch/powerpc/sysdev/xive/common.c +0 -5
index a3b8d7d1316e..838ebdbfe4c5 100644
@@ -1269,11 +1269,6 @@ static void xive_setup_cpu(void)
 {
 	struct xive_cpu *xc = __this_cpu_read(xive_cpu);
 
-	/* Debug: Dump the TM state */
-	pr_devel("CPU %d [HW 0x%02x] VT=%02x\n",
-	    smp_processor_id(), hard_smp_processor_id(),
-	    in_8(xive_tima + xive_tima_offset + TM_WORD2));
-
 	/* The backend might have additional things to do */
 	if (xive_ops->setup_cpu)
 		xive_ops->setup_cpu(smp_processor_id(), xc);
Signature · 1 line
2.14.3
#1 lore raw

PATCH v3 2/16 powerpc: Remove DEBUG define in 64-bit early setup code

This statement causes some not very useful messages to always be printed on the serial port at boot, even on quiet boots.

---
 arch/powerpc/kernel/setup_64.c | 2 --
 1 file changed, 2 deletions(-)
arch/powerpc/kernel/setup_64.c +0 -2
index 8956a9856604..d3124c302146 100644
@@ -10,8 +10,6 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#define DEBUG
-
 #include <linux/export.h>
 #include <linux/string.h>
 #include <linux/sched.h>
Signature · 1 line
2.14.3
#2 lore raw

PATCH v3 3/16 powerpc: Reduce log level of "OPAL detected !" message

In reply to Benjamin Herrenschmidt

This message isn't terribly useful.

---
 arch/powerpc/platforms/powernv/opal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/powernv/opal.c +1 -1
index 041ddbd1fc57..2479e3396ed8 100644
@@ -127,7 +127,7 @@ int __init early_init_dt_scan_opal(unsigned long node,
 
 	if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
 		powerpc_firmware_features |= FW_FEATURE_OPAL;
-		pr_info("OPAL detected !\n");
+		pr_debug("OPAL detected !\n");
 	} else {
 		panic("OPAL != V3 detected, no longer supported.\n");
 	}
Signature · 1 line
2.14.3
#3 lore raw

PATCH v3 4/16 powerpc/kvm/xive: Add more debugfs queues info

In reply to Benjamin Herrenschmidt

Add details about enabled queues and escalation interrupts

---
 arch/powerpc/kvm/book3s_xive.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
arch/powerpc/kvm/book3s_xive.c +28 -0
index 0d750d274c4e..cd21c891be9e 100644
@@ -1795,6 +1795,7 @@ static int xive_debug_show(struct seq_file *m, void *private)
 
 	kvm_for_each_vcpu(i, vcpu, kvm) {
 		struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+		unsigned int i;
 
 		if (!xc)
 			continue;
@@ -1804,6 +1805,33 @@ static int xive_debug_show(struct seq_file *m, void *private)
 			   xc->server_num, xc->cppr, xc->hw_cppr,
 			   xc->mfrr, xc->pending,
 			   xc->stat_rm_h_xirr, xc->stat_vm_h_xirr);
+		for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
+			struct xive_q *q = &xc->queues[i];
+			u32 i0, i1, idx;
+
+			if (!q->qpage && !xc->esc_virq[i])
+				continue;
+
+			seq_printf(m, " [q%d]: ", i);
+
+			if (q->qpage) {
+				idx = q->idx;
+				i0 = be32_to_cpup(q->qpage + idx);
+				idx = (idx + 1) & q->msk;
+				i1 = be32_to_cpup(q->qpage + idx);
+				seq_printf(m, "T=%d %08x %08x... \n", q->toggle, i0, i1);
+			}
+			if (xc->esc_virq[i]) {
+				struct irq_data *d = irq_get_irq_data(xc->esc_virq[i]);
+				struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+				u64 pq = xive_vm_esb_load(xd, XIVE_ESB_GET);
+				seq_printf(m, "E:%c%c I(%d:%llx:%llx)",
+					   (pq & XIVE_ESB_VAL_P) ? 'P' : 'p',
+					   (pq & XIVE_ESB_VAL_Q) ? 'Q' : 'q',
+					   xc->esc_virq[i], pq, xd->eoi_page);
+				seq_printf(m, "\n");
+			}
+		}
 
 		t_rm_h_xirr += xc->stat_rm_h_xirr;
 		t_rm_h_ipoll += xc->stat_rm_h_ipoll;
Signature · 1 line
2.14.3
#4 lore raw

PATCH v3 5/16 powerpc/kvm/xive: Enable use of the new "single escalation" feature

In reply to Benjamin Herrenschmidt

That feature, provided by Power9 DDD2.0 and later, when supported by newer OPAL versions, allows to sacrifice a queue (priority 7) in favor of merging all the escalation interrupts of the queues of a single VP into a single interrupt.

This reduces the number of host interrupts used up by KVM guests especially when those guests use multiple priorities.

It will also enable a future change to control the masking of the escalation interrupts more precisely to avoid spurrious ones.

---
 arch/powerpc/include/asm/opal-api.h |  1 +
 arch/powerpc/include/asm/xive.h     |  3 ++-
 arch/powerpc/kvm/book3s_xive.c      | 48 ++++++++++++++++++++++++-------------
 arch/powerpc/kvm/book3s_xive.h      | 15 +++++-------
 arch/powerpc/sysdev/xive/native.c   | 18 ++++++++++++--
 5 files changed, 57 insertions(+), 28 deletions(-)
arch/powerpc/include/asm/opal-api.h +1 -0
index 233c7504b1f2..fc926743647e 100644
@@ -1073,6 +1073,7 @@ enum {
 /* Flags for OPAL_XIVE_GET/SET_VP_INFO */
 enum {
 	OPAL_XIVE_VP_ENABLED		= 0x00000001,
+	OPAL_XIVE_VP_SINGLE_ESCALATION	= 0x00000002,
 };
 
 /* "Any chip" replacement for chip ID for allocation functions */
arch/powerpc/include/asm/xive.h +2 -1
index 371fbebf1ec9..11d5edeb5c22 100644
@@ -143,9 +143,10 @@ extern void xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio);
 
 extern void xive_native_sync_source(u32 hw_irq);
 extern bool is_xive_irq(struct irq_chip *chip);
-extern int xive_native_enable_vp(u32 vp_id);
+extern int xive_native_enable_vp(u32 vp_id, bool single_escalation);
 extern int xive_native_disable_vp(u32 vp_id);
 extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id);
+extern bool xive_native_has_single_escalation(void);
 
 #else
 
arch/powerpc/kvm/book3s_xive.c +32 -16

111 lines not on this page · raw message

arch/powerpc/kvm/book3s_xive.h +6 -9
index 6ba63f8e8a61..a08ae6fd4c51 100644
@@ -120,6 +120,8 @@ struct kvmppc_xive {
 	u32	q_order;
 	u32	q_page_order;
 
+	/* Flags */
+	u8	single_escalation;
 };
 
 #define KVMPPC_XIVE_Q_COUNT	8
@@ -201,25 +203,20 @@ static inline struct kvmppc_xive_src_block *kvmppc_xive_find_source(struct kvmpp
  * is as follow.
  *
  * Guest request for 0...6 are honored. Guest request for anything
- * higher results in a priority of 7 being applied.
- *
- * However, when XIRR is returned via H_XIRR, 7 is translated to 0xb
- * in order to match AIX expectations
+ * higher results in a priority of 6 being applied.
  *
  * Similar mapping is done for CPPR values
  */
 static inline u8 xive_prio_from_guest(u8 prio)
 {
-	if (prio = 0xff || prio < 8)
+	if (prio = 0xff || prio < 6)
 		return prio;
-	return 7;
+	return 6;
 }
 
 static inline u8 xive_prio_to_guest(u8 prio)
 {
-	if (prio = 0xff || prio < 7)
-		return prio;
-	return 0xb;
+	return prio;
 }
 
 static inline u32 __xive_read_eq(__be32 *qpage, u32 msk, u32 *idx, u32 *toggle)
arch/powerpc/sysdev/xive/native.c +16 -2
index ebc244b08d67..d22aeb0b69e1 100644
@@ -42,6 +42,7 @@ static u32 xive_provision_chip_count;
 static u32 xive_queue_shift;
 static u32 xive_pool_vps = XIVE_INVALID_VP;
 static struct kmem_cache *xive_provision_cache;
+static bool xive_has_single_esc;
 
 int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)
 {
@@ -571,6 +572,10 @@ bool __init xive_native_init(void)
 			break;
 	}
 
+	/* Do we support single escalation */
+	if (of_get_property(np, "single-escalation-support", NULL) != NULL)
+		xive_has_single_esc = true;
+
 	/* Configure Thread Management areas for KVM */
 	for_each_possible_cpu(cpu)
 		kvmppc_set_xive_tima(cpu, r.start, tima);
@@ -667,12 +672,15 @@ void xive_native_free_vp_block(u32 vp_base)
 }
 EXPORT_SYMBOL_GPL(xive_native_free_vp_block);
 
-int xive_native_enable_vp(u32 vp_id)
+int xive_native_enable_vp(u32 vp_id, bool single_escalation)
 {
 	s64 rc;
+	u64 flags = OPAL_XIVE_VP_ENABLED;
 
+	if (single_escalation)
+		flags |= OPAL_XIVE_VP_SINGLE_ESCALATION;
 	for (;;) {
-		rc = opal_xive_set_vp_info(vp_id, OPAL_XIVE_VP_ENABLED, 0);
+		rc = opal_xive_set_vp_info(vp_id, flags, 0);
 		if (rc != OPAL_BUSY)
 			break;
 		msleep(1);
@@ -710,3 +718,9 @@ int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(xive_native_get_vp_info);
+
+bool xive_native_has_single_escalation(void)
+{
+	return xive_has_single_esc;
+}
+EXPORT_SYMBOL_GPL(xive_native_has_single_escalation);
Signature · 1 line
2.14.3
#5 lore raw

PATCH v3 6/16 powerpc/kvm/xive: Don't use existing "prodded" flag for xive escalations

In reply to Benjamin Herrenschmidt

The prodded flag is only cleared at the beginning of H_CEDE, so every time we have an escalation, we will cause the *next* H_CEDE to return immediately.

Instead use a dedicated "irq_pending" flag to indicate that a guest interrupt is pending for the VCPU. We don't reuse the existing exception bitmap as to avoid expensive atomic ops.

---
 arch/powerpc/include/asm/kvm_host.h     |  1 +
 arch/powerpc/kernel/asm-offsets.c       |  1 +
 arch/powerpc/kvm/book3s_hv.c            |  2 +-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 10 ++++++++++
 arch/powerpc/kvm/book3s_xive.c          |  3 +--
 5 files changed, 14 insertions(+), 3 deletions(-)
arch/powerpc/include/asm/kvm_host.h +1 -0
index 3aa5b577cd60..bfe51356af5e 100644
@@ -709,6 +709,7 @@ struct kvm_vcpu_arch {
 	u8 ceded;
 	u8 prodded;
 	u8 doorbell_request;
+	u8 irq_pending; /* Used by XIVE to signal pending guest irqs */
 	u32 last_inst;
 
 	struct swait_queue_head *wqp;
arch/powerpc/kernel/asm-offsets.c +1 -0
index 6b958414b4e0..825089cf3e23 100644
@@ -514,6 +514,7 @@ int main(void)
 	OFFSET(VCPU_PENDING_EXC, kvm_vcpu, arch.pending_exceptions);
 	OFFSET(VCPU_CEDED, kvm_vcpu, arch.ceded);
 	OFFSET(VCPU_PRODDED, kvm_vcpu, arch.prodded);
+	OFFSET(VCPU_IRQ_PENDING, kvm_vcpu, arch.irq_pending);
 	OFFSET(VCPU_DBELL_REQ, kvm_vcpu, arch.doorbell_request);
 	OFFSET(VCPU_MMCR, kvm_vcpu, arch.mmcr);
 	OFFSET(VCPU_PMC, kvm_vcpu, arch.pmc);
arch/powerpc/kvm/book3s_hv.c +1 -1
index 2d46037ce936..eafd722dce56 100644
@@ -2987,7 +2987,7 @@ static inline bool xive_interrupt_pending(struct kvm_vcpu *vcpu)
 {
 	if (!xive_enabled())
 		return false;
-	return vcpu->arch.xive_saved_state.pipr <
+	return vcpu->arch.irq_pending || vcpu->arch.xive_saved_state.pipr <
 		vcpu->arch.xive_saved_state.cppr;
 }
 #else
arch/powerpc/kvm/book3s_hv_rmhandlers.S +10 -0
index 2659844784b8..142b820946dc 100644
@@ -1033,6 +1033,16 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 	li	r9, 1
 	stw	r9, VCPU_XIVE_PUSHED(r4)
 	eieio
+
+	/*
+	 * We clear the irq_pending flag. There is a small chance of a
+	 * race vs. the escalation interrupt happening on another
+	 * processor setting it again, but the only consequence is to
+	 * cause a spurrious wakeup on the next H_CEDE which is not an
+	 * issue.
+	 */
+	li	r0,0
+	stb	r0, VCPU_IRQ_PENDING(r4);
 no_xive:
 #endif /* CONFIG_KVM_XICS */
 
arch/powerpc/kvm/book3s_xive.c +1 -2
index 87f814e81e7d..de78ac38f7ed 100644
@@ -84,8 +84,7 @@ static irqreturn_t xive_esc_irq(int irq, void *data)
 {
 	struct kvm_vcpu *vcpu = data;
 
-	/* We use the existing H_PROD mechanism to wake up the target */
-	vcpu->arch.prodded = 1;
+	vcpu->arch.irq_pending = 1;
 	smp_mb();
 	if (vcpu->arch.ceded)
 		kvmppc_fast_vcpu_kick(vcpu);
Signature · 1 line
2.14.3
#6 lore raw

PATCH v3 7/16 powerpc/kvm/xive: Check DR not IR to chose real vs virt mode MMIOs

In reply to Benjamin Herrenschmidt
---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +1 -1
index 142b820946dc..68a9b28dfd25 100644
@@ -1442,7 +1442,7 @@ guest_exit_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 	li	r7, TM_SPC_PULL_OS_CTX
 	li	r6, TM_QW1_OS
 	mfmsr	r0
-	andi.	r0, r0, MSR_IR		/* in real mode? */
+	andi.	r0, r0, MSR_DR		/* in real mode? */
 	beq	2f
 	ld	r10, HSTATE_XIVE_TIMA_VIRT(r13)
 	cmpldi	cr0, r10, 0
Signature · 1 line
2.14.3
#7 lore raw

PATCH v3 8/16 powerpc/kvm/xive: Make xive_pushed a byte, not a word

In reply to Benjamin Herrenschmidt
---
 arch/powerpc/include/asm/kvm_host.h     | 3 ++-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 6 +++---
 2 files changed, 5 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/kvm_host.h +2 -1
index bfe51356af5e..2cf2cc6b389a 100644
@@ -739,7 +739,8 @@ struct kvm_vcpu_arch {
 	struct kvmppc_icp *icp; /* XICS presentation controller */
 	struct kvmppc_xive_vcpu *xive_vcpu; /* XIVE virtual CPU data */
 	__be32 xive_cam_word;    /* Cooked W2 in proper endian with valid bit */
-	u32 xive_pushed;	 /* Is the VP pushed on the physical CPU ? */
+	u8 xive_pushed;		 /* Is the VP pushed on the physical CPU ? */
+	u8 xive_esc_on;		 /* Is the escalation irq enabled ? */
 	union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */
 #endif
 
arch/powerpc/kvm/book3s_hv_rmhandlers.S +3 -3
index 68a9b28dfd25..bc3fc39d482b 100644
@@ -1031,7 +1031,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 	li	r9, TM_QW1_OS + TM_WORD2
 	stwcix	r11,r9,r10
 	li	r9, 1
-	stw	r9, VCPU_XIVE_PUSHED(r4)
+	stb	r9, VCPU_XIVE_PUSHED(r4)
 	eieio
 
 	/*
@@ -1436,7 +1436,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 guest_exit_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 #ifdef CONFIG_KVM_XICS
 	/* We are exiting, pull the VP from the XIVE */
-	lwz	r0, VCPU_XIVE_PUSHED(r9)
+	lbz	r0, VCPU_XIVE_PUSHED(r9)
 	cmpwi	cr0, r0, 0
 	beq	1f
 	li	r7, TM_SPC_PULL_OS_CTX
@@ -1465,7 +1465,7 @@ guest_exit_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 	/* Fixup some of the state for the next load */
 	li	r10, 0
 	li	r0, 0xff
-	stw	r10, VCPU_XIVE_PUSHED(r9)
+	stb	r10, VCPU_XIVE_PUSHED(r9)
 	stb	r10, (VCPU_XIVE_SAVED_STATE+3)(r9)
 	stb	r0, (VCPU_XIVE_SAVED_STATE+4)(r9)
 	eieio
Signature · 1 line
2.14.3
#8 lore raw

PATCH v3 9/16 powerpc/xive: Move definition of ESB bits

In reply to Benjamin Herrenschmidt

From xive.h to xive-regs.h since it's a HW register definition and it can be used from assembly

---
 arch/powerpc/include/asm/xive-regs.h | 35 +++++++++++++++++++++++++++++++++++
 arch/powerpc/include/asm/xive.h      | 35 -----------------------------------
 2 files changed, 35 insertions(+), 35 deletions(-)
arch/powerpc/include/asm/xive-regs.h +35 -0
index 1d3f2be5ae39..fa4288822b68 100644
@@ -9,6 +9,41 @@
 #ifndef _ASM_POWERPC_XIVE_REGS_H
 #define _ASM_POWERPC_XIVE_REGS_H
 
+/*
+ * "magic" Event State Buffer (ESB) MMIO offsets.
+ *
+ * Each interrupt source has a 2-bit state machine called ESB
+ * which can be controlled by MMIO. It's made of 2 bits, P and
+ * Q. P indicates that an interrupt is pending (has been sent
+ * to a queue and is waiting for an EOI). Q indicates that the
+ * interrupt has been triggered while pending.
+ *
+ * This acts as a coalescing mechanism in order to guarantee
+ * that a given interrupt only occurs at most once in a queue.
+ *
+ * When doing an EOI, the Q bit will indicate if the interrupt
+ * needs to be re-triggered.
+ *
+ * The following offsets into the ESB MMIO allow to read or
+ * manipulate the PQ bits. They must be used with an 8-bytes
+ * load instruction. They all return the previous state of the
+ * interrupt (atomically).
+ *
+ * Additionally, some ESB pages support doing an EOI via a
+ * store at 0 and some ESBs support doing a trigger via a
+ * separate trigger page.
+ */
+#define XIVE_ESB_STORE_EOI	0x400 /* Store */
+#define XIVE_ESB_LOAD_EOI	0x000 /* Load */
+#define XIVE_ESB_GET		0x800 /* Load */
+#define XIVE_ESB_SET_PQ_00	0xc00 /* Load */
+#define XIVE_ESB_SET_PQ_01	0xd00 /* Load */
+#define XIVE_ESB_SET_PQ_10	0xe00 /* Load */
+#define XIVE_ESB_SET_PQ_11	0xf00 /* Load */
+
+#define XIVE_ESB_VAL_P		0x2
+#define XIVE_ESB_VAL_Q		0x1
+
 /*
  * Thread Management (aka "TM") registers
  */
arch/powerpc/include/asm/xive.h +0 -35
index 11d5edeb5c22..f786617ea8b7 100644
@@ -72,41 +72,6 @@ struct xive_q {
 	atomic_t		pending_count;
 };
 
-/*
- * "magic" Event State Buffer (ESB) MMIO offsets.
- *
- * Each interrupt source has a 2-bit state machine called ESB
- * which can be controlled by MMIO. It's made of 2 bits, P and
- * Q. P indicates that an interrupt is pending (has been sent
- * to a queue and is waiting for an EOI). Q indicates that the
- * interrupt has been triggered while pending.
- *
- * This acts as a coalescing mechanism in order to guarantee
- * that a given interrupt only occurs at most once in a queue.
- *
- * When doing an EOI, the Q bit will indicate if the interrupt
- * needs to be re-triggered.
- *
- * The following offsets into the ESB MMIO allow to read or
- * manipulate the PQ bits. They must be used with an 8-bytes
- * load instruction. They all return the previous state of the
- * interrupt (atomically).
- *
- * Additionally, some ESB pages support doing an EOI via a
- * store at 0 and some ESBs support doing a trigger via a
- * separate trigger page.
- */
-#define XIVE_ESB_STORE_EOI	0x400 /* Store */
-#define XIVE_ESB_LOAD_EOI	0x000 /* Load */
-#define XIVE_ESB_GET		0x800 /* Load */
-#define XIVE_ESB_SET_PQ_00	0xc00 /* Load */
-#define XIVE_ESB_SET_PQ_01	0xd00 /* Load */
-#define XIVE_ESB_SET_PQ_10	0xe00 /* Load */
-#define XIVE_ESB_SET_PQ_11	0xf00 /* Load */
-
-#define XIVE_ESB_VAL_P		0x2
-#define XIVE_ESB_VAL_Q		0x1
-
 /* Global enable flags for the XIVE support */
 extern bool __xive_enabled;
 
Signature · 1 line
2.14.3
#9 lore raw

PATCH v3 10/16 powerpc/xive: Add interrupt flag to disable automatic EOI

In reply to Benjamin Herrenschmidt

This will be used by KVM in order to keep escalation interrupts in the non-EOI (masked) state after they fire. They will be re-enabled directly in HW by KVM when needed.

---
 arch/powerpc/include/asm/xive.h   | 3 +++
 arch/powerpc/sysdev/xive/common.c | 3 ++-
 2 files changed, 5 insertions(+), 1 deletion(-)
arch/powerpc/include/asm/xive.h +3 -0
index f786617ea8b7..e602903c3029 100644
@@ -58,6 +58,9 @@ struct xive_irq_data {
 #define XIVE_IRQ_FLAG_EOI_FW	0x10
 #define XIVE_IRQ_FLAG_H_INT_ESB	0x20
 
+/* Special flag set by KVM for excalation interrupts */
+#define XIVE_IRQ_NO_EOI		0x80
+
 #define XIVE_INVALID_CHIP_ID	-1
 
 /* A queue tracking structure in a CPU */
arch/powerpc/sysdev/xive/common.c +2 -1
index 838ebdbfe4c5..40c06110821c 100644
@@ -367,7 +367,8 @@ static void xive_irq_eoi(struct irq_data *d)
 	 * EOI the source if it hasn't been disabled and hasn't
 	 * been passed-through to a KVM guest
 	 */
-	if (!irqd_irq_disabled(d) && !irqd_is_forwarded_to_vcpu(d))
+	if (!irqd_irq_disabled(d) && !irqd_is_forwarded_to_vcpu(d) &&
+	    !(xd->flags & XIVE_IRQ_NO_EOI))
 		xive_do_source_eoi(irqd_to_hwirq(d), xd);
 
 	/*
Signature · 1 line
2.14.3
#10 lore raw

PATCH v3 11/16 powerpc/kvm/xive: Keep escalation interrupt masked unless ceded

In reply to Benjamin Herrenschmidt

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.

---
 arch/powerpc/include/asm/kvm_host.h     |  2 ++
 arch/powerpc/kernel/asm-offsets.c       |  3 ++
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 64 +++++++++++++++++++++++++++++++--
 arch/powerpc/kvm/book3s_xive.c          | 30 ++++++++++++++++
 4 files changed, 97 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/kvm_host.h +2 -0
index 2cf2cc6b389a..fef8133becc8 100644
@@ -742,6 +742,8 @@ struct kvm_vcpu_arch {
 	u8 xive_pushed;		 /* Is the VP pushed on the physical CPU ? */
 	u8 xive_esc_on;		 /* Is the escalation irq enabled ? */
 	union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */
+	u64 xive_esc_raddr;	 /* Escalation interrupt ESB real addr */
+	u64 xive_esc_vaddr;	 /* Escalation interrupt ESB virt addr */
 #endif
 
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
arch/powerpc/kernel/asm-offsets.c +3 -0
index 825089cf3e23..1672dffd94e2 100644
@@ -734,6 +734,9 @@ int main(void)
 	DEFINE(VCPU_XIVE_CAM_WORD, offsetof(struct kvm_vcpu,
 					    arch.xive_cam_word));
 	DEFINE(VCPU_XIVE_PUSHED, offsetof(struct kvm_vcpu, arch.xive_pushed));
+	DEFINE(VCPU_XIVE_ESC_ON, offsetof(struct kvm_vcpu, arch.xive_esc_on));
+	DEFINE(VCPU_XIVE_ESC_RADDR, offsetof(struct kvm_vcpu, arch.xive_esc_raddr));
+	DEFINE(VCPU_XIVE_ESC_VADDR, offsetof(struct kvm_vcpu, arch.xive_esc_vaddr));
 #endif
 
 #ifdef CONFIG_KVM_EXIT_TIMING
arch/powerpc/kvm/book3s_hv_rmhandlers.S +62 -2

76 lines not on this page · raw message

arch/powerpc/kvm/book3s_xive.c +30 -0
index de78ac38f7ed..badfdbb857a2 100644
@@ -89,6 +89,17 @@ static irqreturn_t xive_esc_irq(int irq, void *data)
 	if (vcpu->arch.ceded)
 		kvmppc_fast_vcpu_kick(vcpu);
 
+	/* Since we have the no-EOI flag, the interrupt is effectively
+	 * disabled now. Clearing xive_esc_on means we won't bother
+	 * doing so on the next entry.
+	 *
+	 * This also allows the entry code to know that if a PQ combination
+	 * of 10 is observed while xive_esc_on is true, it means the queue
+	 * contains an unprocessed escalation interrupt. We don't make use of
+	 * that knowledge today but might (see comment in book3s_hv_rmhandler.S)
+	 */
+	vcpu->arch.xive_esc_on = false;
+
 	return IRQ_HANDLED;
 }
 
@@ -134,6 +145,25 @@ static int xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio)
 		goto error;
 	}
 	xc->esc_virq_names[prio] = name;
+
+	/* In single escalation mode, we grab the ESB MMIO of the
+	 * interrupt and mask it. Also populate the VCPU v/raddr
+	 * of the ESB page for use by asm entry/exit code. Finally
+	 * set the XIVE_IRQ_NO_EOI flag which will prevent the
+	 * core code from performing an EOI on the escalation
+	 * interrupt, thus leaving it effectively masked after
+	 * it fires once.
+	 */
+	if (xc->xive->single_escalation) {
+		struct irq_data *d = irq_get_irq_data(xc->esc_virq[prio]);
+		struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+
+		xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01);
+		vcpu->arch.xive_esc_raddr = xd->eoi_page;
+		vcpu->arch.xive_esc_vaddr = (__force u64)xd->eoi_mmio;
+		xd->flags |= XIVE_IRQ_NO_EOI;
+	}
+
 	return 0;
 error:
 	irq_dispose_mapping(xc->esc_virq[prio]);
Signature · 1 line
2.14.3
#11 lore raw

PATCH v3 12/16 powerpc/kvm: Make "no_xive:" label local

In reply to Benjamin Herrenschmidt
---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +2 -2
index b76878a648ef..a38df400c1b7 100644
@@ -1022,7 +1022,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 	/* We are entering the guest on that thread, push VCPU to XIVE */
 	ld	r10, HSTATE_XIVE_TIMA_PHYS(r13)
 	cmpldi	cr0, r10, 0
-	beq	no_xive
+	beq	.Lno_xive
 	ld	r11, VCPU_XIVE_SAVED_STATE(r4)
 	li	r9, TM_QW1_OS
 	eieio
@@ -1078,7 +1078,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 	li	r0, 0
 	stb	r0, VCPU_XIVE_ESC_ON(r4)
 1:
-no_xive:
+.Lno_xive:
 #endif /* CONFIG_KVM_XICS */
 
 deliver_guest_interrupt:
Signature · 1 line
2.14.3
#12 lore raw

PATCH v3 13/16 powerpc: Use the TRAP macro whenever comparing a trap number

In reply to Benjamin Herrenschmidt

Trap numbers can have extra bits at the bottom that need to be filtered out. There are a few cases where we don't do that.

It's possible that we got lucky but better safe than sorry.

---
 arch/powerpc/kernel/process.c | 2 +-
 arch/powerpc/kernel/traps.c   | 2 +-
 arch/powerpc/mm/fault.c       | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
arch/powerpc/kernel/process.c +1 -1
index 72be0c32e902..397d6e64e3df 100644
@@ -1409,7 +1409,7 @@ void show_regs(struct pt_regs * regs)
 	print_msr_bits(regs->msr);
 	pr_cont("  CR: %08lx  XER: %08lx\n", regs->ccr, regs->xer);
 	trap = TRAP(regs);
-	if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
+	if ((TRAP(regs) != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
 		pr_cont("CFAR: "REG" ", regs->orig_gpr3);
 	if (trap = 0x200 || trap = 0x300 || trap = 0x600)
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
arch/powerpc/kernel/traps.c +1 -1
index f3eb61be0d30..d61989be28e1 100644
@@ -1564,7 +1564,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
 	u8 status;
 	bool hv;
 
-	hv = (regs->trap = 0xf80);
+	hv = (TRAP(regs) = 0xf80);
 	if (hv)
 		value = mfspr(SPRN_HFSCR);
 	else
arch/powerpc/mm/fault.c +1 -1
index 6e1e39035380..7b15fe2ac986 100644
@@ -576,7 +576,7 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 
 	/* kernel has accessed a bad area */
 
-	switch (regs->trap) {
+	switch (TRAP(regs)) {
 	case 0x300:
 	case 0x380:
 		printk(KERN_ALERT "Unable to handle kernel paging request for "
Signature · 1 line
2.14.3
#13 lore raw

PATCH v3 14/16 powerpc: Remove useless EXC_COMMON_HV

In reply to Benjamin Herrenschmidt

The only difference between EXC_COMMON_HV and EXC_COMMON is that the former adds "2" to the trap number which is supposed to represent the fact that this is an "HV" interrupt which uses HSRR0/1.

However KVM is the only one who cares and it has its own separate macros.

In fact, we only have one user of EXC_COMMON_HV and it's for an unknown interrupt case. All the other ones already using EXC_COMMON.

---
 arch/powerpc/include/asm/head-64.h   | 7 +------
 arch/powerpc/kernel/exceptions-64s.S | 2 +-
 2 files changed, 2 insertions(+), 7 deletions(-)
arch/powerpc/include/asm/head-64.h +1 -6
index fdcff76e9a25..0a663dfc28b5 100644
@@ -178,7 +178,7 @@ end_##sname:
  * TRAMP_REAL_*   - real, unrelocated helpers (virt can call these)
  * TRAMP_VIRT_*   - virt, unreloc helpers (in practice, real can use)
  * TRAMP_KVM      - KVM handlers that get put into real, unrelocated
- * EXC_COMMON_*   - virt, relocated common handlers
+ * EXC_COMMON     - virt, relocated common handlers
  *
  * The EXC handlers are given a name, and branch to name_common, or the
  * appropriate KVM or masking function. Vector handler verieties are as
@@ -211,7 +211,6 @@ end_##sname:
  * EXC_COMMON_BEGIN/END - used to open-code the handler
  * EXC_COMMON
  * EXC_COMMON_ASYNC
- * EXC_COMMON_HV
  *
  * TRAMP_REAL and TRAMP_VIRT can be used with BEGIN/END. KVM
  * and OOL handlers are implemented as types of TRAMP and TRAMP_VIRT handlers.
@@ -413,10 +412,6 @@ end_##sname:
 	EXC_COMMON_BEGIN(name);						\
 	STD_EXCEPTION_COMMON_ASYNC(realvec, name, hdlr);		\
 
-#define EXC_COMMON_HV(name, realvec, hdlr)				\
-	EXC_COMMON_BEGIN(name);						\
-	STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr);		\
-
 #endif /* __ASSEMBLY__ */
 
 #endif	/* _ASM_POWERPC_HEAD_64_H */
arch/powerpc/kernel/exceptions-64s.S +1 -1
index e441b469dc8f..175891c6909c 100644
@@ -1318,7 +1318,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
 	b	.
 #endif
 
-EXC_COMMON_HV(denorm_common, 0x1500, unknown_exception)
+EXC_COMMON(denorm_common, 0x1500, unknown_exception)
 
 
 #ifdef CONFIG_CBE_RAS
Signature · 1 line
2.14.3
#14 lore raw

PATCH v3 15/16 powerpc/kvm: Store the MMU mode in the PACA on KVM exit

In reply to Benjamin Herrenschmidt

This stores the MMU mode (real vs. virt) in the PACA on exceptions by passing bit 0x4000 to the KVM trampoline. This unfortunately forces us to add a few more trampolines due to how our macros work.

---
 arch/powerpc/include/asm/exception-64s.h  | 35 +++++++++++++++----------
 arch/powerpc/include/asm/head-64.h        |  8 ++++++
 arch/powerpc/include/asm/kvm_book3s_asm.h |  1 +
 arch/powerpc/kernel/asm-offsets.c         |  1 +
 arch/powerpc/kernel/exceptions-64s.S      | 43 +++++++++++++++++++++++++++----
 arch/powerpc/kvm/book3s_hv_rmhandlers.S   |  9 +++++--
 6 files changed, 76 insertions(+), 21 deletions(-)
arch/powerpc/include/asm/exception-64s.h +21 -14
index b27205297e1d..64936a89c79c 100644
@@ -243,10 +243,10 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 	EXCEPTION_PROLOG_1(area, extra, vec);				\
 	EXCEPTION_PROLOG_PSERIES_1(label, h);
 
-#define __KVMTEST(h, n)							\
+#define __KVMTEST(h, n, v)						\
 	lbz	r10,HSTATE_IN_GUEST(r13);				\
 	cmpwi	r10,0;							\
-	bne	do_kvm_##h##n
+	bne	do_kvm_##h##n##v
 
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 /*
@@ -353,12 +353,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 	b	kvmppc_skip_##h##interrupt
 
 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-#define KVMTEST(h, n)			__KVMTEST(h, n)
+#define KVMTEST(h, n, v)		__KVMTEST(h, n, v)
 #define KVM_HANDLER(area, h, n)		__KVM_HANDLER(area, h, n)
 #define KVM_HANDLER_SKIP(area, h, n)	__KVM_HANDLER_SKIP(area, h, n)
 
 #else
-#define KVMTEST(h, n)
+#define KVMTEST(h, n, v)
 #define KVM_HANDLER(area, h, n)
 #define KVM_HANDLER_SKIP(area, h, n)
 #endif
@@ -479,13 +479,13 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);		\
 	EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_STD)
 
-#define STD_RELON_EXCEPTION_HV(loc, vec, label)		\
-	SET_SCRATCH0(r13);	/* save r13 */		\
+#define STD_RELON_EXCEPTION_HV(loc, vec, label)			\
+	SET_SCRATCH0(r13);	/* save r13 */			\
 	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label,	\
-				       EXC_HV, KVMTEST_HV, vec);
+				       EXC_HV, KVMTEST_HV_VIRT, vec);
 
 #define STD_RELON_EXCEPTION_HV_OOL(vec, label)			\
-	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec);	\
+	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV_VIRT, vec);	\
 	EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_HV)
 
 /* This associate vector numbers with bits in paca->irq_happened */
@@ -506,18 +506,25 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 #define _SOFTEN_TEST(h, vec)	__SOFTEN_TEST(h, vec)
 
 #define SOFTEN_TEST_PR(vec)						\
-	KVMTEST(EXC_STD, vec);						\
+	KVMTEST(EXC_STD, vec,);						\
 	_SOFTEN_TEST(EXC_STD, vec)
 
 #define SOFTEN_TEST_HV(vec)						\
-	KVMTEST(EXC_HV, vec);						\
+	KVMTEST(EXC_HV, vec,);						\
+	_SOFTEN_TEST(EXC_HV, vec)
+
+#define SOFTEN_TEST_HV_VIRT(vec)					\
+	KVMTEST(EXC_HV, vec, _VIRT);					\
 	_SOFTEN_TEST(EXC_HV, vec)
 
 #define KVMTEST_PR(vec)							\
-	KVMTEST(EXC_STD, vec)
+	KVMTEST(EXC_STD, vec,)
 
 #define KVMTEST_HV(vec)							\
-	KVMTEST(EXC_HV, vec)
+	KVMTEST(EXC_HV, vec,)
+
+#define KVMTEST_HV_VIRT(vec)						\
+	KVMTEST(EXC_HV, vec, _VIRT)
 
 #define SOFTEN_NOTEST_PR(vec)		_SOFTEN_TEST(EXC_STD, vec)
 #define SOFTEN_NOTEST_HV(vec)		_SOFTEN_TEST(EXC_HV, vec)
@@ -562,10 +569,10 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 
 #define MASKABLE_RELON_EXCEPTION_HV(loc, vec, label)			\
 	_MASKABLE_RELON_EXCEPTION_PSERIES(vec, label,			\
-					  EXC_HV, SOFTEN_TEST_HV)
+					  EXC_HV, SOFTEN_TEST_HV_VIRT)
 
 #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label)			\
-	EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec);		\
+	EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV_VIRT, vec);	\
 	EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_HV)
 
 /*
arch/powerpc/include/asm/head-64.h +8 -0
index 0a663dfc28b5..faf8d03f0797 100644
@@ -404,6 +404,14 @@ end_##sname:
 	TRAMP_KVM_BEGIN(do_kvm_H##n);					\
 	KVM_HANDLER_SKIP(area, EXC_HV, n + 0x2);			\
 
+#define TRAMP_KVM_HV_VIRT(area, n)					\
+	TRAMP_KVM_BEGIN(do_kvm_H##n##_VIRT);				\
+	KVM_HANDLER(area, EXC_HV, n + 0x4002);				\
+
+#define TRAMP_KVM_HV_VIRT_SKIP(area, n)					\
+	TRAMP_KVM_BEGIN(do_kvm_H##n##_VIRT);				\
+	KVM_HANDLER_SKIP(area, EXC_HV, n + 0x4002);			\
+
 #define EXC_COMMON(name, realvec, hdlr)					\
 	EXC_COMMON_BEGIN(name);						\
 	STD_EXCEPTION_COMMON(realvec, name, hdlr);			\
arch/powerpc/include/asm/kvm_book3s_asm.h +1 -0
index ab386af2904f..c6afd99d91fb 100644
@@ -125,6 +125,7 @@ struct kvmppc_host_state {
 	void __iomem *xive_tima_phys;
 	void __iomem *xive_tima_virt;
 	u32 saved_xirr;
+	u32 exit_virt;
 	u64 dabr;
 	u64 host_mmcr[7];	/* MMCR 0,1,A, SIAR, SDAR, MMCR2, SIER */
 	u32 host_pmc[8];
arch/powerpc/kernel/asm-offsets.c +1 -0
index 1672dffd94e2..25ee619531c2 100644
@@ -641,6 +641,7 @@ int main(void)
 	HSTATE_FIELD(HSTATE_XIVE_TIMA_PHYS, xive_tima_phys);
 	HSTATE_FIELD(HSTATE_XIVE_TIMA_VIRT, xive_tima_virt);
 	HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr);
+	HSTATE_FIELD(HSTATE_EXIT_VIRT, exit_virt);
 	HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi);
 	HSTATE_FIELD(HSTATE_PTID, ptid);
 	HSTATE_FIELD(HSTATE_TID, tid);
arch/powerpc/kernel/exceptions-64s.S +38 -5

127 lines not on this page · raw message

arch/powerpc/kvm/book3s_hv_rmhandlers.S +7 -2
index a38df400c1b7..1e32e188ba17 100644
@@ -95,6 +95,8 @@ BEGIN_FTR_SECTION
 46:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 
+	li	r0,0
+	stw	r0,HSTATE_EXIT_VIRT(r13)
 	ld	r4, HSTATE_KVM_VCPU(r13)
 	bl	kvmppc_hv_entry
 
@@ -1312,8 +1314,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 	mfspr	r11, SPRN_SRR1
 	std	r10, VCPU_SRR0(r9)
 	std	r11, VCPU_SRR1(r9)
-	/* trap is in the low half of r12, clear CR from the high half */
-	clrldi	r12, r12, 32
+	/* Recover bit 0x4000 from trap (virt vs real mode) */
+	rlwinm	r0,r12,18,31,31
+	stw	r0,HSTATE_EXIT_VIRT(r13)
+	/* trap is in the low half of r12, clear CR in high half and virt mode bit */
+	clrldi	r12, r12, 50
 	andi.	r0, r12, 2		/* need to read HSRR0/1? */
 	beq	1f
 	mfspr	r10, SPRN_HSRR0
Signature · 1 line
2.14.3
#15 lore raw

PATCH v3 16/16 powerpc/kvm: Use the PACA virt/real mode info instead of mfmsr

In reply to Benjamin Herrenschmidt

This shaves off a bunch of cycles from the KVM exit path and the XIVE related hypercall.

---
 arch/powerpc/kvm/book3s_hv_builtin.c    |  5 ++---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 14 ++++++++------
 2 files changed, 10 insertions(+), 9 deletions(-)
arch/powerpc/kvm/book3s_hv_builtin.c +2 -3
index 49a2c7825e04..5fbaa8710e0c 100644
@@ -209,8 +209,7 @@ long kvmppc_h_random(struct kvm_vcpu *vcpu)
 {
 	int r;
 
-	/* Only need to do the expensive mfmsr() on radix */
-	if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
+	if (local_paca->kvm_hstate.exit_virt)
 		r = powernv_get_random_long(&vcpu->arch.gpr[4]);
 	else
 		r = powernv_get_random_real_mode(&vcpu->arch.gpr[4]);
@@ -541,7 +540,7 @@ static long kvmppc_read_one_intr(bool *again)
 #ifdef CONFIG_KVM_XICS
 static inline bool is_rm(void)
 {
-	return !(mfmsr() & MSR_DR);
+	return !local_paca->kvm_hstate.exit_virt;
 }
 
 unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +8 -6
index 1e32e188ba17..0024c449340b 100644
@@ -190,8 +190,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	 * we will be in virtual mode at this point, which makes it a
 	 * little easier to get back to the caller.
 	 */
-	mfmsr	r0
-	andi.	r0, r0, MSR_IR		/* in real mode? */
+	lbz	r0,HSTATE_EXIT_VIRT(r13)
+	cmpwi	r0,0
 	bne	.Lvirt_return
 
 	/* RFI into the highmem handler */
@@ -1481,8 +1481,9 @@ guest_exit_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 	beq	1f
 	li	r7, TM_SPC_PULL_OS_CTX
 	li	r6, TM_QW1_OS
-	mfmsr	r0
-	andi.	r0, r0, MSR_DR		/* in real mode? */
+	/* Are we in virtual or real mode ? */
+	lbz	r0,HSTATE_EXIT_VIRT(r13)
+	cmpwi	r0,0
 	beq	2f
 	ld	r10, HSTATE_XIVE_TIMA_VIRT(r13)
 	cmpldi	cr0, r10, 0
@@ -2804,8 +2805,9 @@ kvm_cede_exit:
 	stb	r0, VCPU_CEDED(r9)
 1:	/* Enable XIVE escalation */
 	li	r5, XIVE_ESB_SET_PQ_00
-	mfmsr	r0
-	andi.	r0, r0, MSR_DR		/* in real mode? */
+	/* Are we in virtual or real mode ? */
+	lbz	r0,HSTATE_EXIT_VIRT(r13)
+	cmpwi	r0,0
 	beq	1f
 	ld	r10, VCPU_XIVE_ESC_VADDR(r9)
 	cmpdi	r10, 0
Signature · 1 line
2.14.3