Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4868ff5 authored by Cédric Le Goater's avatar Cédric Le Goater Committed by Michael Ellerman
Browse files

powerpc/xive: Fix dump of XIVE interrupt under pseries



The xmon 'dxi' command calls OPAL to query the XIVE configuration of a
interrupt. This can only be done on baremetal (PowerNV) and it will
crash a pseries machine.

Introduce a new XIVE get_irq_config() operation which implements a
different query depending on the platform, PowerNV or pseries, and
modify xmon to use a top level wrapper.

Signed-off-by: default avatarCédric Le Goater <clg@kaod.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190814154754.23682-3-clg@kaod.org
parent c3e0dbd7
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -99,6 +99,8 @@ extern void xive_flush_interrupt(void);

/* xmon hook */
extern void xmon_xive_do_dump(int cpu);
extern int xmon_xive_get_irq_config(u32 irq, u32 *target, u8 *prio,
				    u32 *sw_irq);

/* APIs used by KVM */
extern u32 xive_native_default_eq_shift(void);
+7 −0
Original line number Diff line number Diff line
@@ -257,6 +257,13 @@ notrace void xmon_xive_do_dump(int cpu)
	}
#endif
}

int xmon_xive_get_irq_config(u32 irq, u32 *target, u8 *prio,
			     u32 *sw_irq)
{
	return xive_ops->get_irq_config(irq, target, prio, sw_irq);
}

#endif /* CONFIG_XMON */

static unsigned int xive_get_irq(void)
+15 −0
Original line number Diff line number Diff line
@@ -111,6 +111,20 @@ int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
}
EXPORT_SYMBOL_GPL(xive_native_configure_irq);

static int xive_native_get_irq_config(u32 hw_irq, u32 *target, u8 *prio,
				      u32 *sw_irq)
{
	s64 rc;
	__be64 vp;
	__be32 lirq;

	rc = opal_xive_get_irq_config(hw_irq, &vp, prio, &lirq);

	*target = be64_to_cpu(vp);
	*sw_irq = be32_to_cpu(lirq);

	return rc == 0 ? 0 : -ENXIO;
}

/* This can be called multiple time to change a queue configuration */
int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio,
@@ -442,6 +456,7 @@ EXPORT_SYMBOL_GPL(xive_native_sync_queue);
static const struct xive_ops xive_native_ops = {
	.populate_irq_data	= xive_native_populate_irq_data,
	.configure_irq		= xive_native_configure_irq,
	.get_irq_config		= xive_native_get_irq_config,
	.setup_queue		= xive_native_setup_queue,
	.cleanup_queue		= xive_native_cleanup_queue,
	.match			= xive_native_match,
+51 −0
Original line number Diff line number Diff line
@@ -215,6 +215,38 @@ static long plpar_int_set_source_config(unsigned long flags,
	return 0;
}

static long plpar_int_get_source_config(unsigned long flags,
					unsigned long lisn,
					unsigned long *target,
					unsigned long *prio,
					unsigned long *sw_irq)
{
	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
	long rc;

	pr_devel("H_INT_GET_SOURCE_CONFIG flags=%lx lisn=%lx\n", flags, lisn);

	do {
		rc = plpar_hcall(H_INT_GET_SOURCE_CONFIG, retbuf, flags, lisn,
				 target, prio, sw_irq);
	} while (plpar_busy_delay(rc));

	if (rc) {
		pr_err("H_INT_GET_SOURCE_CONFIG lisn=%ld failed %ld\n",
		       lisn, rc);
		return rc;
	}

	*target = retbuf[0];
	*prio   = retbuf[1];
	*sw_irq = retbuf[2];

	pr_devel("H_INT_GET_SOURCE_CONFIG target=%lx prio=%lx sw_irq=%lx\n",
		retbuf[0], retbuf[1], retbuf[2]);

	return 0;
}

static long plpar_int_get_queue_info(unsigned long flags,
				     unsigned long target,
				     unsigned long priority,
@@ -398,6 +430,24 @@ static int xive_spapr_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
	return rc == 0 ? 0 : -ENXIO;
}

static int xive_spapr_get_irq_config(u32 hw_irq, u32 *target, u8 *prio,
				     u32 *sw_irq)
{
	long rc;
	unsigned long h_target;
	unsigned long h_prio;
	unsigned long h_sw_irq;

	rc = plpar_int_get_source_config(0, hw_irq, &h_target, &h_prio,
					 &h_sw_irq);

	*target = h_target;
	*prio = h_prio;
	*sw_irq = h_sw_irq;

	return rc == 0 ? 0 : -ENXIO;
}

/* This can be called multiple time to change a queue configuration */
static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio,
				   __be32 *qpage, u32 order)
@@ -590,6 +640,7 @@ static void xive_spapr_sync_source(u32 hw_irq)
static const struct xive_ops xive_spapr_ops = {
	.populate_irq_data	= xive_spapr_populate_irq_data,
	.configure_irq		= xive_spapr_configure_irq,
	.get_irq_config		= xive_spapr_get_irq_config,
	.setup_queue		= xive_spapr_setup_queue,
	.cleanup_queue		= xive_spapr_cleanup_queue,
	.match			= xive_spapr_match,
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ struct xive_cpu {
struct xive_ops {
	int	(*populate_irq_data)(u32 hw_irq, struct xive_irq_data *data);
	int 	(*configure_irq)(u32 hw_irq, u32 target, u8 prio, u32 sw_irq);
	int	(*get_irq_config)(u32 hw_irq, u32 *target, u8 *prio,
				  u32 *sw_irq);
	int	(*setup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio);
	void	(*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio);
	void	(*setup_cpu)(unsigned int cpu, struct xive_cpu *xc);
Loading