Commit f3c18e93 authored by Paul Mackerras's avatar Paul Mackerras Committed by Michael Ellerman
Browse files

KVM: PPC: Book3S HV: Use XICS hypercalls when running as a nested hypervisor



This adds code to call the H_IPI and H_EOI hypercalls when we are
running as a nested hypervisor (i.e. without the CPU_FTR_HVMODE cpu
feature) and we would otherwise access the XICS interrupt controller
directly or via an OPAL call.

Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 360cae31
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -173,6 +173,10 @@ static bool kvmppc_ipi_thread(int cpu)
{
	unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);

	/* If we're a nested hypervisor, fall back to ordinary IPIs for now */
	if (kvmhv_on_pseries())
		return false;

	/* On POWER9 we can use msgsnd to IPI any cpu */
	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
		msg |= get_hard_smp_processor_id(cpu);
@@ -5177,7 +5181,8 @@ static int kvmppc_book3s_init_hv(void)
	 * indirectly, via OPAL.
	 */
#ifdef CONFIG_SMP
	if (!xive_enabled() && !local_paca->kvm_hstate.xics_phys) {
	if (!xive_enabled() && !kvmhv_on_pseries() &&
	    !local_paca->kvm_hstate.xics_phys) {
		struct device_node *np;

		np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc");
+36 −8
Original line number Diff line number Diff line
@@ -231,6 +231,15 @@ void kvmhv_rm_send_ipi(int cpu)
	void __iomem *xics_phys;
	unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);

	/* For a nested hypervisor, use the XICS via hcall */
	if (kvmhv_on_pseries()) {
		unsigned long retbuf[PLPAR_HCALL_BUFSIZE];

		plpar_hcall_raw(H_IPI, retbuf, get_hard_smp_processor_id(cpu),
				IPI_PRIORITY);
		return;
	}

	/* On POWER9 we can use msgsnd for any destination cpu. */
	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
		msg |= get_hard_smp_processor_id(cpu);
@@ -460,12 +469,19 @@ static long kvmppc_read_one_intr(bool *again)
		return 1;

	/* Now read the interrupt from the ICP */
	if (kvmhv_on_pseries()) {
		unsigned long retbuf[PLPAR_HCALL_BUFSIZE];

		rc = plpar_hcall_raw(H_XIRR, retbuf, 0xFF);
		xirr = cpu_to_be32(retbuf[0]);
	} else {
		xics_phys = local_paca->kvm_hstate.xics_phys;
		rc = 0;
		if (!xics_phys)
			rc = opal_int_get_xirr(&xirr, false);
		else
			xirr = __raw_rm_readl(xics_phys + XICS_XIRR);
	}
	if (rc < 0)
		return 1;

@@ -494,7 +510,13 @@ static long kvmppc_read_one_intr(bool *again)
	 */
	if (xisr == XICS_IPI) {
		rc = 0;
		if (xics_phys) {
		if (kvmhv_on_pseries()) {
			unsigned long retbuf[PLPAR_HCALL_BUFSIZE];

			plpar_hcall_raw(H_IPI, retbuf,
					hard_smp_processor_id(), 0xff);
			plpar_hcall_raw(H_EOI, retbuf, h_xirr);
		} else if (xics_phys) {
			__raw_rm_writeb(0xff, xics_phys + XICS_MFRR);
			__raw_rm_writel(xirr, xics_phys + XICS_XIRR);
		} else {
@@ -520,7 +542,13 @@ static long kvmppc_read_one_intr(bool *again)
			/* We raced with the host,
			 * we need to resend that IPI, bummer
			 */
			if (xics_phys)
			if (kvmhv_on_pseries()) {
				unsigned long retbuf[PLPAR_HCALL_BUFSIZE];

				plpar_hcall_raw(H_IPI, retbuf,
						hard_smp_processor_id(),
						IPI_PRIORITY);
			} else if (xics_phys)
				__raw_rm_writeb(IPI_PRIORITY,
						xics_phys + XICS_MFRR);
			else
+8 −0
Original line number Diff line number Diff line
@@ -767,6 +767,14 @@ static void icp_eoi(struct irq_chip *c, u32 hwirq, __be32 xirr, bool *again)
	void __iomem *xics_phys;
	int64_t rc;

	if (kvmhv_on_pseries()) {
		unsigned long retbuf[PLPAR_HCALL_BUFSIZE];

		iosync();
		plpar_hcall_raw(H_EOI, retbuf, hwirq);
		return;
	}

	rc = pnv_opal_pci_msi_eoi(c, hwirq);

	if (rc)