2019-06-04 15:11:33 +07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2017-04-05 14:54:56 +07:00
|
|
|
/*
|
|
|
|
* Copyright 2017 Benjamin Herrenschmidt, IBM Corporation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define pr_fmt(fmt) "xive-kvm: " fmt
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/kvm_host.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/gfp.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/percpu.h>
|
|
|
|
#include <linux/cpumask.h>
|
2017-12-05 02:43:20 +07:00
|
|
|
#include <linux/uaccess.h>
|
2017-04-05 14:54:56 +07:00
|
|
|
#include <asm/kvm_book3s.h>
|
|
|
|
#include <asm/kvm_ppc.h>
|
|
|
|
#include <asm/hvcall.h>
|
|
|
|
#include <asm/xics.h>
|
|
|
|
#include <asm/xive.h>
|
|
|
|
#include <asm/xive-regs.h>
|
|
|
|
#include <asm/debug.h>
|
2017-05-09 16:50:01 +07:00
|
|
|
#include <asm/debugfs.h>
|
2017-04-05 14:54:56 +07:00
|
|
|
#include <asm/time.h>
|
|
|
|
#include <asm/opal.h>
|
|
|
|
|
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
|
|
|
#include "book3s_xive.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Virtual mode variants of the hcalls for use on radix/radix
|
|
|
|
* with AIL. They require the VCPU's VP to be "pushed"
|
|
|
|
*
|
2018-08-24 07:00:52 +07:00
|
|
|
* We still instantiate them here because we use some of the
|
2017-04-05 14:54:56 +07:00
|
|
|
* generated utility functions as well in this file.
|
|
|
|
*/
|
|
|
|
#define XIVE_RUNTIME_CHECKS
|
|
|
|
#define X_PFX xive_vm_
|
|
|
|
#define X_STATIC static
|
|
|
|
#define X_STAT_PFX stat_vm_
|
|
|
|
#define __x_tima xive_tima
|
|
|
|
#define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_mmio))
|
|
|
|
#define __x_trig_page(xd) ((void __iomem *)((xd)->trig_mmio))
|
|
|
|
#define __x_writeb __raw_writeb
|
|
|
|
#define __x_readw __raw_readw
|
|
|
|
#define __x_readq __raw_readq
|
|
|
|
#define __x_writeq __raw_writeq
|
|
|
|
|
|
|
|
#include "book3s_xive_template.c"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We leave a gap of a couple of interrupts in the queue to
|
|
|
|
* account for the IPI and additional safety guard.
|
|
|
|
*/
|
|
|
|
#define XIVE_Q_GAP 2
|
|
|
|
|
2018-10-08 12:30:55 +07:00
|
|
|
/*
|
|
|
|
* Push a vcpu's context to the XIVE on guest entry.
|
|
|
|
* This assumes we are in virtual mode (MMU on)
|
|
|
|
*/
|
|
|
|
void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
void __iomem *tima = local_paca->kvm_hstate.xive_tima_virt;
|
|
|
|
u64 pq;
|
|
|
|
|
2019-08-13 17:01:00 +07:00
|
|
|
/*
|
|
|
|
* Nothing to do if the platform doesn't have a XIVE
|
|
|
|
* or this vCPU doesn't have its own XIVE context
|
|
|
|
* (e.g. because it's not using an in-kernel interrupt controller).
|
|
|
|
*/
|
|
|
|
if (!tima || !vcpu->arch.xive_cam_word)
|
2018-10-08 12:30:55 +07:00
|
|
|
return;
|
2019-08-13 17:01:00 +07:00
|
|
|
|
2018-10-08 12:30:55 +07:00
|
|
|
eieio();
|
|
|
|
__raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS);
|
|
|
|
__raw_writel(vcpu->arch.xive_cam_word, tima + TM_QW1_OS + TM_WORD2);
|
|
|
|
vcpu->arch.xive_pushed = 1;
|
|
|
|
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 spurious wakeup on the next H_CEDE, which is not an
|
|
|
|
* issue.
|
|
|
|
*/
|
|
|
|
vcpu->arch.irq_pending = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In single escalation mode, if the escalation interrupt is
|
|
|
|
* on, we mask it.
|
|
|
|
*/
|
|
|
|
if (vcpu->arch.xive_esc_on) {
|
|
|
|
pq = __raw_readq((void __iomem *)(vcpu->arch.xive_esc_vaddr +
|
|
|
|
XIVE_ESB_SET_PQ_01));
|
|
|
|
mb();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have a possible subtle race here: The escalation
|
|
|
|
* interrupt might have fired and be on its way to the
|
|
|
|
* host queue while we mask it, and if we unmask it
|
|
|
|
* early enough (re-cede right away), there is a
|
|
|
|
* theorical possibility that it fires again, thus
|
|
|
|
* landing in the target queue more than once which is
|
|
|
|
* a big no-no.
|
|
|
|
*
|
|
|
|
* Fortunately, solving this is rather easy. If the
|
|
|
|
* above load setting PQ to 01 returns a previous
|
|
|
|
* value where P is set, then we know the escalation
|
|
|
|
* interrupt is somewhere on its way to the host. In
|
|
|
|
* that case we simply don't clear the xive_esc_on
|
|
|
|
* flag below. It will be eventually cleared by the
|
|
|
|
* handler for the escalation interrupt.
|
|
|
|
*
|
|
|
|
* Then, when doing a cede, we check that flag again
|
|
|
|
* before re-enabling the escalation interrupt, and if
|
|
|
|
* set, we abort the cede.
|
|
|
|
*/
|
|
|
|
if (!(pq & XIVE_ESB_VAL_P))
|
|
|
|
/* Now P is 0, we can clear the flag */
|
|
|
|
vcpu->arch.xive_esc_on = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(kvmppc_xive_push_vcpu);
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
/*
|
|
|
|
* This is a simple trigger for a generic XIVE IRQ. This must
|
|
|
|
* only be called for interrupts that support a trigger page
|
|
|
|
*/
|
|
|
|
static bool xive_irq_trigger(struct xive_irq_data *xd)
|
|
|
|
{
|
|
|
|
/* This should be only for MSIs */
|
|
|
|
if (WARN_ON(xd->flags & XIVE_IRQ_FLAG_LSI))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Those interrupts should always have a trigger page */
|
|
|
|
if (WARN_ON(!xd->trig_mmio))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
out_be64(xd->trig_mmio, 0);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static irqreturn_t xive_esc_irq(int irq, void *data)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu = data;
|
|
|
|
|
2018-01-12 09:37:13 +07:00
|
|
|
vcpu->arch.irq_pending = 1;
|
2017-04-05 14:54:56 +07:00
|
|
|
smp_mb();
|
|
|
|
if (vcpu->arch.ceded)
|
|
|
|
kvmppc_fast_vcpu_kick(vcpu);
|
|
|
|
|
2018-01-12 09:37:16 +07:00
|
|
|
/* 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;
|
|
|
|
|
powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race
Testing has revealed the existence of a race condition where a XIVE
interrupt being shut down can be in one of the XIVE interrupt queues
(of which there are up to 8 per CPU, one for each priority) at the
point where free_irq() is called. If this happens, can return an
interrupt number which has been shut down. This can lead to various
symptoms:
- irq_to_desc(irq) can be NULL. In this case, no end-of-interrupt
function gets called, resulting in the CPU's elevated interrupt
priority (numerically lowered CPPR) never gets reset. That then
means that the CPU stops processing interrupts, causing device
timeouts and other errors in various device drivers.
- The irq descriptor or related data structures can be in the process
of being freed as the interrupt code is using them. This typically
leads to crashes due to bad pointer dereferences.
This race is basically what commit 62e0468650c3 ("genirq: Add optional
hardware synchronization for shutdown", 2019-06-28) is intended to
fix, given a get_irqchip_state() method for the interrupt controller
being used. It works by polling the interrupt controller when an
interrupt is being freed until the controller says it is not pending.
With XIVE, the PQ bits of the interrupt source indicate the state of
the interrupt source, and in particular the P bit goes from 0 to 1 at
the point where the hardware writes an entry into the interrupt queue
that this interrupt is directed towards. Normally, the code will then
process the interrupt and do an end-of-interrupt (EOI) operation which
will reset PQ to 00 (assuming another interrupt hasn't been generated
in the meantime). However, there are situations where the code resets
P even though a queue entry exists (for example, by setting PQ to 01,
which disables the interrupt source), and also situations where the
code leaves P at 1 after removing the queue entry (for example, this
is done for escalation interrupts so they cannot fire again until
they are explicitly re-enabled).
The code already has a 'saved_p' flag for the interrupt source which
indicates that a queue entry exists, although it isn't maintained
consistently. This patch adds a 'stale_p' flag to indicate that
P has been left at 1 after processing a queue entry, and adds code
to set and clear saved_p and stale_p as necessary to maintain a
consistent indication of whether a queue entry may or may not exist.
With this, we can implement xive_get_irqchip_state() by looking at
stale_p, saved_p and the ESB PQ bits for the interrupt.
There is some additional code to handle escalation interrupts
properly; because they are enabled and disabled in KVM assembly code,
which does not have access to the xive_irq_data struct for the
escalation interrupt. Hence, stale_p may be incorrect when the
escalation interrupt is freed in kvmppc_xive_{,native_}cleanup_vcpu().
Fortunately, we can fix it up by looking at vcpu->arch.xive_esc_on,
with some careful attention to barriers in order to ensure the correct
result if xive_esc_irq() races with kvmppc_xive_cleanup_vcpu().
Finally, this adds code to make noise on the console (pr_crit and
WARN_ON(1)) if we find an interrupt queue entry for an interrupt
which does not have a descriptor. While this won't catch the race
reliably, if it does get triggered it will be an indication that
the race is occurring and needs to be debugged.
Fixes: 243e25112d06 ("powerpc/xive: Native exploitation of the XIVE interrupt controller")
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190813100648.GE9567@blackberry
2019-08-13 17:06:48 +07:00
|
|
|
/* This orders xive_esc_on = false vs. subsequent stale_p = true */
|
|
|
|
smp_wmb(); /* goes with smp_mb() in cleanup_single_escalation */
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:31 +07:00
|
|
|
int kvmppc_xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio,
|
|
|
|
bool single_escalation)
|
2017-04-05 14:54:56 +07:00
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct xive_q *q = &xc->queues[prio];
|
|
|
|
char *name = NULL;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/* Already there ? */
|
|
|
|
if (xc->esc_virq[prio])
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Hook up the escalation interrupt */
|
|
|
|
xc->esc_virq[prio] = irq_create_mapping(NULL, q->esc_irq);
|
|
|
|
if (!xc->esc_virq[prio]) {
|
|
|
|
pr_err("Failed to map escalation interrupt for queue %d of VCPU %d\n",
|
|
|
|
prio, xc->server_num);
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:31 +07:00
|
|
|
if (single_escalation)
|
2018-01-12 09:37:12 +07:00
|
|
|
name = kasprintf(GFP_KERNEL, "kvm-%d-%d",
|
|
|
|
vcpu->kvm->arch.lpid, xc->server_num);
|
|
|
|
else
|
|
|
|
name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d",
|
|
|
|
vcpu->kvm->arch.lpid, xc->server_num, prio);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (!name) {
|
|
|
|
pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n",
|
|
|
|
prio, xc->server_num);
|
|
|
|
rc = -ENOMEM;
|
|
|
|
goto error;
|
|
|
|
}
|
2018-01-12 09:37:12 +07:00
|
|
|
|
|
|
|
pr_devel("Escalation %s irq %d (prio %d)\n", name, xc->esc_virq[prio], prio);
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
rc = request_irq(xc->esc_virq[prio], xive_esc_irq,
|
|
|
|
IRQF_NO_THREAD, name, vcpu);
|
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to request escalation interrupt for queue %d of VCPU %d\n",
|
|
|
|
prio, xc->server_num);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
xc->esc_virq_names[prio] = name;
|
2018-01-12 09:37:16 +07:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2019-04-18 17:39:31 +07:00
|
|
|
if (single_escalation) {
|
2018-01-12 09:37:16 +07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
irq_dispose_mapping(xc->esc_virq[prio]);
|
|
|
|
xc->esc_virq[prio] = 0;
|
|
|
|
kfree(name);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_provision_queue(struct kvm_vcpu *vcpu, u8 prio)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct kvmppc_xive *xive = xc->xive;
|
|
|
|
struct xive_q *q = &xc->queues[prio];
|
|
|
|
void *qpage;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (WARN_ON(q->qpage))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Allocate the queue and retrieve infos on current node for now */
|
|
|
|
qpage = (__be32 *)__get_free_pages(GFP_KERNEL, xive->q_page_order);
|
|
|
|
if (!qpage) {
|
|
|
|
pr_err("Failed to allocate queue %d for VCPU %d\n",
|
|
|
|
prio, xc->server_num);
|
2018-02-22 16:54:55 +07:00
|
|
|
return -ENOMEM;
|
2017-04-05 14:54:56 +07:00
|
|
|
}
|
|
|
|
memset(qpage, 0, 1 << xive->q_order);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reconfigure the queue. This will set q->qpage only once the
|
|
|
|
* queue is fully configured. This is a requirement for prio 0
|
|
|
|
* as we will stop doing EOIs for every IPI as soon as we observe
|
|
|
|
* qpage being non-NULL, and instead will only EOI when we receive
|
|
|
|
* corresponding queue 0 entries
|
|
|
|
*/
|
|
|
|
rc = xive_native_configure_queue(xc->vp_id, q, prio, qpage,
|
|
|
|
xive->q_order, true);
|
|
|
|
if (rc)
|
|
|
|
pr_err("Failed to configure queue %d for VCPU %d\n",
|
|
|
|
prio, xc->server_num);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
/* Called with xive->lock held */
|
2017-04-05 14:54:56 +07:00
|
|
|
static int xive_check_provisioning(struct kvm *kvm, u8 prio)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
int i, rc;
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
lockdep_assert_held(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
/* Already provisioned ? */
|
|
|
|
if (xive->qmap & (1 << prio))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pr_devel("Provisioning prio... %d\n", prio);
|
|
|
|
|
2018-01-12 09:37:12 +07:00
|
|
|
/* Provision each VCPU and enable escalations if needed */
|
2017-04-05 14:54:56 +07:00
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
if (!vcpu->arch.xive_vcpu)
|
|
|
|
continue;
|
|
|
|
rc = xive_provision_queue(vcpu, prio);
|
2018-01-12 09:37:12 +07:00
|
|
|
if (rc == 0 && !xive->single_escalation)
|
2019-04-18 17:39:31 +07:00
|
|
|
kvmppc_xive_attach_escalation(vcpu, prio,
|
|
|
|
xive->single_escalation);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Order previous stores and mark it as provisioned */
|
|
|
|
mb();
|
|
|
|
xive->qmap |= (1 << prio);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_inc_q_pending(struct kvm *kvm, u32 server, u8 prio)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
struct kvmppc_xive_vcpu *xc;
|
|
|
|
struct xive_q *q;
|
|
|
|
|
|
|
|
/* Locate target server */
|
|
|
|
vcpu = kvmppc_xive_find_server(kvm, server);
|
|
|
|
if (!vcpu) {
|
|
|
|
pr_warn("%s: Can't find server %d\n", __func__, server);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
xc = vcpu->arch.xive_vcpu;
|
|
|
|
if (WARN_ON(!xc))
|
|
|
|
return;
|
|
|
|
|
|
|
|
q = &xc->queues[prio];
|
|
|
|
atomic_inc(&q->pending_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_try_pick_queue(struct kvm_vcpu *vcpu, u8 prio)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct xive_q *q;
|
|
|
|
u32 max;
|
|
|
|
|
|
|
|
if (WARN_ON(!xc))
|
|
|
|
return -ENXIO;
|
|
|
|
if (!xc->valid)
|
|
|
|
return -ENXIO;
|
|
|
|
|
|
|
|
q = &xc->queues[prio];
|
|
|
|
if (WARN_ON(!q->qpage))
|
|
|
|
return -ENXIO;
|
|
|
|
|
|
|
|
/* Calculate max number of interrupts in that queue. */
|
|
|
|
max = (q->msk + 1) - XIVE_Q_GAP;
|
|
|
|
return atomic_add_unless(&q->count, 1, max) ? 0 : -EBUSY;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:30 +07:00
|
|
|
int kvmppc_xive_select_target(struct kvm *kvm, u32 *server, u8 prio)
|
2017-04-05 14:54:56 +07:00
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
int i, rc;
|
|
|
|
|
|
|
|
/* Locate target server */
|
|
|
|
vcpu = kvmppc_xive_find_server(kvm, *server);
|
|
|
|
if (!vcpu) {
|
|
|
|
pr_devel("Can't find server %d\n", *server);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pr_devel("Finding irq target on 0x%x/%d...\n", *server, prio);
|
|
|
|
|
|
|
|
/* Try pick it */
|
|
|
|
rc = xive_try_pick_queue(vcpu, prio);
|
|
|
|
if (rc == 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
pr_devel(" .. failed, looking up candidate...\n");
|
|
|
|
|
|
|
|
/* Failed, pick another VCPU */
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
if (!vcpu->arch.xive_vcpu)
|
|
|
|
continue;
|
|
|
|
rc = xive_try_pick_queue(vcpu, prio);
|
|
|
|
if (rc == 0) {
|
|
|
|
*server = vcpu->arch.xive_vcpu->server_num;
|
|
|
|
pr_devel(" found on 0x%x/%d\n", *server, prio);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pr_devel(" no available target !\n");
|
|
|
|
|
|
|
|
/* No available target ! */
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u8 xive_lock_and_mask(struct kvmppc_xive *xive,
|
|
|
|
struct kvmppc_xive_src_block *sb,
|
|
|
|
struct kvmppc_xive_irq_state *state)
|
|
|
|
{
|
|
|
|
struct xive_irq_data *xd;
|
|
|
|
u32 hw_num;
|
|
|
|
u8 old_prio;
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take the lock, set masked, try again if racing
|
|
|
|
* with H_EOI
|
|
|
|
*/
|
|
|
|
for (;;) {
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
old_prio = state->guest_priority;
|
|
|
|
state->guest_priority = MASKED;
|
|
|
|
mb();
|
|
|
|
if (!state->in_eoi)
|
|
|
|
break;
|
|
|
|
state->guest_priority = old_prio;
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No change ? Bail */
|
|
|
|
if (old_prio == MASKED)
|
|
|
|
return old_prio;
|
|
|
|
|
|
|
|
/* Get the right irq */
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, &xd);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the interrupt is marked as needing masking via
|
|
|
|
* firmware, we do it here. Firmware masking however
|
|
|
|
* is "lossy", it won't return the old p and q bits
|
|
|
|
* and won't set the interrupt to a state where it will
|
|
|
|
* record queued ones. If this is an issue we should do
|
|
|
|
* lazy masking instead.
|
|
|
|
*
|
|
|
|
* For now, we work around this in unmask by forcing
|
|
|
|
* an interrupt whenever we unmask a non-LSI via FW
|
|
|
|
* (if ever).
|
|
|
|
*/
|
|
|
|
if (xd->flags & OPAL_XIVE_IRQ_MASK_VIA_FW) {
|
|
|
|
xive_native_configure_irq(hw_num,
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_vp(xive, state->act_server),
|
|
|
|
MASKED, state->number);
|
2017-04-05 14:54:56 +07:00
|
|
|
/* set old_p so we can track if an H_EOI was done */
|
|
|
|
state->old_p = true;
|
|
|
|
state->old_q = false;
|
|
|
|
} else {
|
|
|
|
/* Set PQ to 10, return old P and old Q and remember them */
|
|
|
|
val = xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_10);
|
|
|
|
state->old_p = !!(val & 2);
|
|
|
|
state->old_q = !!(val & 1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Synchronize hardware to sensure the queues are updated
|
|
|
|
* when masking
|
|
|
|
*/
|
|
|
|
xive_native_sync_source(hw_num);
|
|
|
|
}
|
|
|
|
|
|
|
|
return old_prio;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_lock_for_unmask(struct kvmppc_xive_src_block *sb,
|
|
|
|
struct kvmppc_xive_irq_state *state)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Take the lock try again if racing with H_EOI
|
|
|
|
*/
|
|
|
|
for (;;) {
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
if (!state->in_eoi)
|
|
|
|
break;
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_finish_unmask(struct kvmppc_xive *xive,
|
|
|
|
struct kvmppc_xive_src_block *sb,
|
|
|
|
struct kvmppc_xive_irq_state *state,
|
|
|
|
u8 prio)
|
|
|
|
{
|
|
|
|
struct xive_irq_data *xd;
|
|
|
|
u32 hw_num;
|
|
|
|
|
|
|
|
/* If we aren't changing a thing, move on */
|
|
|
|
if (state->guest_priority != MASKED)
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
/* Get the right irq */
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, &xd);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See command in xive_lock_and_mask() concerning masking
|
|
|
|
* via firmware.
|
|
|
|
*/
|
|
|
|
if (xd->flags & OPAL_XIVE_IRQ_MASK_VIA_FW) {
|
|
|
|
xive_native_configure_irq(hw_num,
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_vp(xive, state->act_server),
|
|
|
|
state->act_priority, state->number);
|
2017-04-05 14:54:56 +07:00
|
|
|
/* If an EOI is needed, do it here */
|
|
|
|
if (!state->old_p)
|
|
|
|
xive_vm_source_eoi(hw_num, xd);
|
|
|
|
/* If this is not an LSI, force a trigger */
|
|
|
|
if (!(xd->flags & OPAL_XIVE_IRQ_LSI))
|
|
|
|
xive_irq_trigger(xd);
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Old Q set, set PQ to 11 */
|
|
|
|
if (state->old_q)
|
|
|
|
xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_11);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If not old P, then perform an "effective" EOI,
|
|
|
|
* on the source. This will handle the cases where
|
|
|
|
* FW EOI is needed.
|
|
|
|
*/
|
|
|
|
if (!state->old_p)
|
|
|
|
xive_vm_source_eoi(hw_num, xd);
|
|
|
|
|
|
|
|
/* Synchronize ordering and mark unmasked */
|
|
|
|
mb();
|
|
|
|
bail:
|
|
|
|
state->guest_priority = prio;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Target an interrupt to a given server/prio, this will fallback
|
|
|
|
* to another server if necessary and perform the HW targetting
|
|
|
|
* updates as needed
|
|
|
|
*
|
|
|
|
* NOTE: Must be called with the state lock held
|
|
|
|
*/
|
|
|
|
static int xive_target_interrupt(struct kvm *kvm,
|
|
|
|
struct kvmppc_xive_irq_state *state,
|
|
|
|
u32 server, u8 prio)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
u32 hw_num;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This will return a tentative server and actual
|
|
|
|
* priority. The count for that new target will have
|
|
|
|
* already been incremented.
|
|
|
|
*/
|
2019-04-18 17:39:30 +07:00
|
|
|
rc = kvmppc_xive_select_target(kvm, &server, prio);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We failed to find a target ? Not much we can do
|
|
|
|
* at least until we support the GIQ.
|
|
|
|
*/
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Increment the old queue pending count if there
|
|
|
|
* was one so that the old queue count gets adjusted later
|
|
|
|
* when observed to be empty.
|
|
|
|
*/
|
|
|
|
if (state->act_priority != MASKED)
|
|
|
|
xive_inc_q_pending(kvm,
|
|
|
|
state->act_server,
|
|
|
|
state->act_priority);
|
|
|
|
/*
|
|
|
|
* Update state and HW
|
|
|
|
*/
|
|
|
|
state->act_priority = prio;
|
|
|
|
state->act_server = server;
|
|
|
|
|
|
|
|
/* Get the right irq */
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, NULL);
|
|
|
|
|
|
|
|
return xive_native_configure_irq(hw_num,
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_vp(xive, server),
|
2017-04-05 14:54:56 +07:00
|
|
|
prio, state->number);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Targetting rules: In order to avoid losing track of
|
|
|
|
* pending interrupts accross mask and unmask, which would
|
|
|
|
* allow queue overflows, we implement the following rules:
|
|
|
|
*
|
|
|
|
* - Unless it was never enabled (or we run out of capacity)
|
|
|
|
* an interrupt is always targetted at a valid server/queue
|
|
|
|
* pair even when "masked" by the guest. This pair tends to
|
|
|
|
* be the last one used but it can be changed under some
|
|
|
|
* circumstances. That allows us to separate targetting
|
|
|
|
* from masking, we only handle accounting during (re)targetting,
|
|
|
|
* this also allows us to let an interrupt drain into its target
|
|
|
|
* queue after masking, avoiding complex schemes to remove
|
|
|
|
* interrupts out of remote processor queues.
|
|
|
|
*
|
|
|
|
* - When masking, we set PQ to 10 and save the previous value
|
|
|
|
* of P and Q.
|
|
|
|
*
|
|
|
|
* - When unmasking, if saved Q was set, we set PQ to 11
|
|
|
|
* otherwise we leave PQ to the HW state which will be either
|
|
|
|
* 10 if nothing happened or 11 if the interrupt fired while
|
|
|
|
* masked. Effectively we are OR'ing the previous Q into the
|
|
|
|
* HW Q.
|
|
|
|
*
|
|
|
|
* Then if saved P is clear, we do an effective EOI (Q->P->Trigger)
|
|
|
|
* which will unmask the interrupt and shoot a new one if Q was
|
|
|
|
* set.
|
|
|
|
*
|
|
|
|
* Otherwise (saved P is set) we leave PQ unchanged (so 10 or 11,
|
|
|
|
* effectively meaning an H_EOI from the guest is still expected
|
|
|
|
* for that interrupt).
|
|
|
|
*
|
|
|
|
* - If H_EOI occurs while masked, we clear the saved P.
|
|
|
|
*
|
|
|
|
* - When changing target, we account on the new target and
|
|
|
|
* increment a separate "pending" counter on the old one.
|
|
|
|
* This pending counter will be used to decrement the old
|
|
|
|
* target's count when its queue has been observed empty.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
|
|
|
|
u32 priority)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u8 new_act_prio;
|
|
|
|
int rc = 0;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
pr_devel("set_xive ! irq 0x%x server 0x%x prio %d\n",
|
|
|
|
irq, server, priority);
|
|
|
|
|
|
|
|
/* First, check provisioning of queues */
|
2019-05-24 20:20:30 +07:00
|
|
|
if (priority != MASKED) {
|
|
|
|
mutex_lock(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
rc = xive_check_provisioning(xive->kvm,
|
|
|
|
xive_prio_from_guest(priority));
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
|
|
|
}
|
2017-04-05 14:54:56 +07:00
|
|
|
if (rc) {
|
|
|
|
pr_devel(" provisioning failure %d !\n", rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We first handle masking/unmasking since the locking
|
|
|
|
* might need to be retried due to EOIs, we'll handle
|
|
|
|
* targetting changes later. These functions will return
|
|
|
|
* with the SB lock held.
|
|
|
|
*
|
|
|
|
* xive_lock_and_mask() will also set state->guest_priority
|
|
|
|
* but won't otherwise change other fields of the state.
|
|
|
|
*
|
|
|
|
* xive_lock_for_unmask will not actually unmask, this will
|
|
|
|
* be done later by xive_finish_unmask() once the targetting
|
|
|
|
* has been done, so we don't try to unmask an interrupt
|
|
|
|
* that hasn't yet been targetted.
|
|
|
|
*/
|
|
|
|
if (priority == MASKED)
|
|
|
|
xive_lock_and_mask(xive, sb, state);
|
|
|
|
else
|
|
|
|
xive_lock_for_unmask(sb, state);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Then we handle targetting.
|
|
|
|
*
|
|
|
|
* First calculate a new "actual priority"
|
|
|
|
*/
|
|
|
|
new_act_prio = state->act_priority;
|
|
|
|
if (priority != MASKED)
|
|
|
|
new_act_prio = xive_prio_from_guest(priority);
|
|
|
|
|
|
|
|
pr_devel(" new_act_prio=%x act_server=%x act_prio=%x\n",
|
|
|
|
new_act_prio, state->act_server, state->act_priority);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Then check if we actually need to change anything,
|
|
|
|
*
|
|
|
|
* The condition for re-targetting the interrupt is that
|
|
|
|
* we have a valid new priority (new_act_prio is not 0xff)
|
|
|
|
* and either the server or the priority changed.
|
|
|
|
*
|
|
|
|
* Note: If act_priority was ff and the new priority is
|
|
|
|
* also ff, we don't do anything and leave the interrupt
|
|
|
|
* untargetted. An attempt of doing an int_on on an
|
|
|
|
* untargetted interrupt will fail. If that is a problem
|
|
|
|
* we could initialize interrupts with valid default
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (new_act_prio != MASKED &&
|
|
|
|
(state->act_server != server ||
|
|
|
|
state->act_priority != new_act_prio))
|
|
|
|
rc = xive_target_interrupt(kvm, state, server, new_act_prio);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform the final unmasking of the interrupt source
|
|
|
|
* if necessary
|
|
|
|
*/
|
|
|
|
if (priority != MASKED)
|
|
|
|
xive_finish_unmask(xive, sb, state, priority);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally Update saved_priority to match. Only int_on/off
|
|
|
|
* set this field to a different value.
|
|
|
|
*/
|
|
|
|
state->saved_priority = priority;
|
|
|
|
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
|
|
|
|
u32 *priority)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
arch_spin_lock(&sb->lock);
|
2017-09-26 13:47:04 +07:00
|
|
|
*server = state->act_server;
|
2017-04-05 14:54:56 +07:00
|
|
|
*priority = state->guest_priority;
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_int_on(struct kvm *kvm, u32 irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
pr_devel("int_on(irq=0x%x)\n", irq);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if interrupt was not targetted
|
|
|
|
*/
|
|
|
|
if (state->act_priority == MASKED) {
|
|
|
|
pr_devel("int_on on untargetted interrupt\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If saved_priority is 0xff, do nothing */
|
|
|
|
if (state->saved_priority == MASKED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock and unmask it.
|
|
|
|
*/
|
|
|
|
xive_lock_for_unmask(sb, state);
|
|
|
|
xive_finish_unmask(xive, sb, state, state->saved_priority);
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_int_off(struct kvm *kvm, u32 irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
pr_devel("int_off(irq=0x%x)\n", irq);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock and mask
|
|
|
|
*/
|
|
|
|
state->saved_priority = xive_lock_and_mask(xive, sb, state);
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool xive_restore_pending_irq(struct kvmppc_xive *xive, u32 irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return false;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
if (!state->valid)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Trigger the IPI. This assumes we never restore a pass-through
|
|
|
|
* interrupt which should be safe enough
|
|
|
|
*/
|
|
|
|
xive_irq_trigger(&state->ipi_data);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Return the per-cpu state for state saving/migration */
|
|
|
|
return (u64)xc->cppr << KVM_REG_PPC_ICP_CPPR_SHIFT |
|
2017-12-13 00:23:56 +07:00
|
|
|
(u64)xc->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT |
|
|
|
|
(u64)0xff << KVM_REG_PPC_ICP_PPRI_SHIFT;
|
2017-04-05 14:54:56 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
|
|
|
|
u8 cppr, mfrr;
|
|
|
|
u32 xisr;
|
|
|
|
|
|
|
|
if (!xc || !xive)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
/* Grab individual state fields. We don't use pending_pri */
|
|
|
|
cppr = icpval >> KVM_REG_PPC_ICP_CPPR_SHIFT;
|
|
|
|
xisr = (icpval >> KVM_REG_PPC_ICP_XISR_SHIFT) &
|
|
|
|
KVM_REG_PPC_ICP_XISR_MASK;
|
|
|
|
mfrr = icpval >> KVM_REG_PPC_ICP_MFRR_SHIFT;
|
|
|
|
|
|
|
|
pr_devel("set_icp vcpu %d cppr=0x%x mfrr=0x%x xisr=0x%x\n",
|
|
|
|
xc->server_num, cppr, mfrr, xisr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We can't update the state of a "pushed" VCPU, but that
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
* shouldn't happen because the vcpu->mutex makes running a
|
|
|
|
* vcpu mutually exclusive with doing one_reg get/set on it.
|
2017-04-05 14:54:56 +07:00
|
|
|
*/
|
|
|
|
if (WARN_ON(vcpu->arch.xive_pushed))
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
/* Update VCPU HW saved state */
|
|
|
|
vcpu->arch.xive_saved_state.cppr = cppr;
|
|
|
|
xc->hw_cppr = xc->cppr = cppr;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update MFRR state. If it's not 0xff, we mark the VCPU as
|
|
|
|
* having a pending MFRR change, which will re-evaluate the
|
|
|
|
* target. The VCPU will thus potentially get a spurious
|
|
|
|
* interrupt but that's not a big deal.
|
|
|
|
*/
|
|
|
|
xc->mfrr = mfrr;
|
|
|
|
if (mfrr < cppr)
|
|
|
|
xive_irq_trigger(&xc->vp_ipi_data);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now saved XIRR is "interesting". It means there's something in
|
|
|
|
* the legacy "1 element" queue... for an IPI we simply ignore it,
|
|
|
|
* as the MFRR restore will handle that. For anything else we need
|
|
|
|
* to force a resend of the source.
|
|
|
|
* However the source may not have been setup yet. If that's the
|
|
|
|
* case, we keep that info and increment a counter in the xive to
|
|
|
|
* tell subsequent xive_set_source() to go look.
|
|
|
|
*/
|
|
|
|
if (xisr > XICS_IPI && !xive_restore_pending_irq(xive, xisr)) {
|
|
|
|
xc->delayed_irq = xisr;
|
|
|
|
xive->delayed_irqs++;
|
|
|
|
pr_devel(" xisr restore delayed\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
|
|
|
|
struct irq_desc *host_desc)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
struct irq_data *host_data = irq_desc_get_irq_data(host_desc);
|
|
|
|
unsigned int host_irq = irq_desc_get_irq(host_desc);
|
|
|
|
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(host_data);
|
|
|
|
u16 idx;
|
|
|
|
u8 prio;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
pr_devel("set_mapped girq 0x%lx host HW irq 0x%x...\n",guest_irq, hw_irq);
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, guest_irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mark the passed-through interrupt as going to a VCPU,
|
|
|
|
* this will prevent further EOIs and similar operations
|
|
|
|
* from the XIVE code. It will also mask the interrupt
|
|
|
|
* to either PQ=10 or 11 state, the latter if the interrupt
|
|
|
|
* is pending. This will allow us to unmask or retrigger it
|
|
|
|
* after routing it to the guest with a simple EOI.
|
|
|
|
*
|
|
|
|
* The "state" argument is a "token", all it needs is to be
|
|
|
|
* non-NULL to switch to passed-through or NULL for the
|
|
|
|
* other way around. We may not yet have an actual VCPU
|
|
|
|
* target here and we don't really care.
|
|
|
|
*/
|
|
|
|
rc = irq_set_vcpu_affinity(host_irq, state);
|
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to set VCPU affinity for irq %d\n", host_irq);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mask and read state of IPI. We need to know if its P bit
|
|
|
|
* is set as that means it's potentially already using a
|
|
|
|
* queue entry in the target
|
|
|
|
*/
|
|
|
|
prio = xive_lock_and_mask(xive, sb, state);
|
|
|
|
pr_devel(" old IPI prio %02x P:%d Q:%d\n", prio,
|
|
|
|
state->old_p, state->old_q);
|
|
|
|
|
|
|
|
/* Turn the IPI hard off */
|
|
|
|
xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01);
|
|
|
|
|
KVM: PPC: Book3S HV: XIVE: Add passthrough support
The KVM XICS-over-XIVE device and the proposed KVM XIVE native device
implement an IRQ space for the guest using the generic IPI interrupts
of the XIVE IC controller. These interrupts are allocated at the OPAL
level and "mapped" into the guest IRQ number space in the range 0-0x1FFF.
Interrupt management is performed in the XIVE way: using loads and
stores on the addresses of the XIVE IPI interrupt ESB pages.
Both KVM devices share the same internal structure caching information
on the interrupts, among which the xive_irq_data struct containing the
addresses of the IPI ESB pages and an extra one in case of pass-through.
The later contains the addresses of the ESB pages of the underlying HW
controller interrupts, PHB4 in all cases for now.
A guest, when running in the XICS legacy interrupt mode, lets the KVM
XICS-over-XIVE device "handle" interrupt management, that is to
perform the loads and stores on the addresses of the ESB pages of the
guest interrupts. However, when running in XIVE native exploitation
mode, the KVM XIVE native device exposes the interrupt ESB pages to
the guest and lets the guest perform directly the loads and stores.
The VMA exposing the ESB pages make use of a custom VM fault handler
which role is to populate the VMA with appropriate pages. When a fault
occurs, the guest IRQ number is deduced from the offset, and the ESB
pages of associated XIVE IPI interrupt are inserted in the VMA (using
the internal structure caching information on the interrupts).
Supporting device passthrough in the guest running in XIVE native
exploitation mode adds some extra refinements because the ESB pages
of a different HW controller (PHB4) need to be exposed to the guest
along with the initial IPI ESB pages of the XIVE IC controller. But
the overall mechanic is the same.
When the device HW irqs are mapped into or unmapped from the guest
IRQ number space, the passthru_irq helpers, kvmppc_xive_set_mapped()
and kvmppc_xive_clr_mapped(), are called to record or clear the
passthrough interrupt information and to perform the switch.
The approach taken by this patch is to clear the ESB pages of the
guest IRQ number being mapped and let the VM fault handler repopulate.
The handler will insert the ESB page corresponding to the HW interrupt
of the device being passed-through or the initial IPI ESB page if the
device is being removed.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-18 17:39:39 +07:00
|
|
|
/*
|
|
|
|
* Reset ESB guest mapping. Needed when ESB pages are exposed
|
|
|
|
* to the guest in XIVE native mode
|
|
|
|
*/
|
|
|
|
if (xive->ops && xive->ops->reset_mapped)
|
|
|
|
xive->ops->reset_mapped(kvm, guest_irq);
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
/* Grab info about irq */
|
|
|
|
state->pt_number = hw_irq;
|
|
|
|
state->pt_data = irq_data_get_irq_handler_data(host_data);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Configure the IRQ to match the existing configuration of
|
|
|
|
* the IPI if it was already targetted. Otherwise this will
|
|
|
|
* mask the interrupt in a lossy way (act_priority is 0xff)
|
|
|
|
* which is fine for a never started interrupt.
|
|
|
|
*/
|
|
|
|
xive_native_configure_irq(hw_irq,
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_vp(xive, state->act_server),
|
2017-04-05 14:54:56 +07:00
|
|
|
state->act_priority, state->number);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We do an EOI to enable the interrupt (and retrigger if needed)
|
|
|
|
* if the guest has the interrupt unmasked and the P bit was *not*
|
|
|
|
* set in the IPI. If it was set, we know a slot may still be in
|
|
|
|
* use in the target queue thus we have to wait for a guest
|
|
|
|
* originated EOI
|
|
|
|
*/
|
|
|
|
if (prio != MASKED && !state->old_p)
|
|
|
|
xive_vm_source_eoi(hw_irq, state->pt_data);
|
|
|
|
|
|
|
|
/* Clear old_p/old_q as they are no longer relevant */
|
|
|
|
state->old_p = state->old_q = false;
|
|
|
|
|
|
|
|
/* Restore guest prio (unlocks EOI) */
|
|
|
|
mb();
|
|
|
|
state->guest_priority = prio;
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(kvmppc_xive_set_mapped);
|
|
|
|
|
|
|
|
int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
|
|
|
|
struct irq_desc *host_desc)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
unsigned int host_irq = irq_desc_get_irq(host_desc);
|
|
|
|
u16 idx;
|
|
|
|
u8 prio;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
pr_devel("clr_mapped girq 0x%lx...\n", guest_irq);
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, guest_irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mask and read state of IRQ. We need to know if its P bit
|
|
|
|
* is set as that means it's potentially already using a
|
|
|
|
* queue entry in the target
|
|
|
|
*/
|
|
|
|
prio = xive_lock_and_mask(xive, sb, state);
|
|
|
|
pr_devel(" old IRQ prio %02x P:%d Q:%d\n", prio,
|
|
|
|
state->old_p, state->old_q);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If old_p is set, the interrupt is pending, we switch it to
|
|
|
|
* PQ=11. This will force a resend in the host so the interrupt
|
|
|
|
* isn't lost to whatver host driver may pick it up
|
|
|
|
*/
|
|
|
|
if (state->old_p)
|
|
|
|
xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_11);
|
|
|
|
|
|
|
|
/* Release the passed-through interrupt to the host */
|
|
|
|
rc = irq_set_vcpu_affinity(host_irq, NULL);
|
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to clr VCPU affinity for irq %d\n", host_irq);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Forget about the IRQ */
|
|
|
|
state->pt_number = 0;
|
|
|
|
state->pt_data = NULL;
|
|
|
|
|
KVM: PPC: Book3S HV: XIVE: Add passthrough support
The KVM XICS-over-XIVE device and the proposed KVM XIVE native device
implement an IRQ space for the guest using the generic IPI interrupts
of the XIVE IC controller. These interrupts are allocated at the OPAL
level and "mapped" into the guest IRQ number space in the range 0-0x1FFF.
Interrupt management is performed in the XIVE way: using loads and
stores on the addresses of the XIVE IPI interrupt ESB pages.
Both KVM devices share the same internal structure caching information
on the interrupts, among which the xive_irq_data struct containing the
addresses of the IPI ESB pages and an extra one in case of pass-through.
The later contains the addresses of the ESB pages of the underlying HW
controller interrupts, PHB4 in all cases for now.
A guest, when running in the XICS legacy interrupt mode, lets the KVM
XICS-over-XIVE device "handle" interrupt management, that is to
perform the loads and stores on the addresses of the ESB pages of the
guest interrupts. However, when running in XIVE native exploitation
mode, the KVM XIVE native device exposes the interrupt ESB pages to
the guest and lets the guest perform directly the loads and stores.
The VMA exposing the ESB pages make use of a custom VM fault handler
which role is to populate the VMA with appropriate pages. When a fault
occurs, the guest IRQ number is deduced from the offset, and the ESB
pages of associated XIVE IPI interrupt are inserted in the VMA (using
the internal structure caching information on the interrupts).
Supporting device passthrough in the guest running in XIVE native
exploitation mode adds some extra refinements because the ESB pages
of a different HW controller (PHB4) need to be exposed to the guest
along with the initial IPI ESB pages of the XIVE IC controller. But
the overall mechanic is the same.
When the device HW irqs are mapped into or unmapped from the guest
IRQ number space, the passthru_irq helpers, kvmppc_xive_set_mapped()
and kvmppc_xive_clr_mapped(), are called to record or clear the
passthrough interrupt information and to perform the switch.
The approach taken by this patch is to clear the ESB pages of the
guest IRQ number being mapped and let the VM fault handler repopulate.
The handler will insert the ESB page corresponding to the HW interrupt
of the device being passed-through or the initial IPI ESB page if the
device is being removed.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-18 17:39:39 +07:00
|
|
|
/*
|
|
|
|
* Reset ESB guest mapping. Needed when ESB pages are exposed
|
|
|
|
* to the guest in XIVE native mode
|
|
|
|
*/
|
|
|
|
if (xive->ops && xive->ops->reset_mapped) {
|
|
|
|
xive->ops->reset_mapped(kvm, guest_irq);
|
|
|
|
}
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
/* Reconfigure the IPI */
|
|
|
|
xive_native_configure_irq(state->ipi_number,
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_vp(xive, state->act_server),
|
2017-04-05 14:54:56 +07:00
|
|
|
state->act_priority, state->number);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If old_p is set (we have a queue entry potentially
|
|
|
|
* occupied) or the interrupt is masked, we set the IPI
|
|
|
|
* to PQ=10 state. Otherwise we just re-enable it (PQ=00).
|
|
|
|
*/
|
|
|
|
if (prio == MASKED || state->old_p)
|
|
|
|
xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_10);
|
|
|
|
else
|
|
|
|
xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_00);
|
|
|
|
|
|
|
|
/* Restore guest prio (unlocks EOI) */
|
|
|
|
mb();
|
|
|
|
state->guest_priority = prio;
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(kvmppc_xive_clr_mapped);
|
|
|
|
|
2019-04-18 17:39:28 +07:00
|
|
|
void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu)
|
2017-04-05 14:54:56 +07:00
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct kvm *kvm = vcpu->kvm;
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
|
|
|
|
|
|
|
|
if (!sb)
|
|
|
|
continue;
|
|
|
|
for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) {
|
|
|
|
struct kvmppc_xive_irq_state *state = &sb->irq_state[j];
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
continue;
|
|
|
|
if (state->act_priority == MASKED)
|
|
|
|
continue;
|
|
|
|
if (state->act_server != xc->server_num)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Clean it up */
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
state->act_priority = MASKED;
|
|
|
|
xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01);
|
|
|
|
xive_native_configure_irq(state->ipi_number, 0, MASKED, 0);
|
|
|
|
if (state->pt_number) {
|
|
|
|
xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_01);
|
|
|
|
xive_native_configure_irq(state->pt_number, 0, MASKED, 0);
|
|
|
|
}
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
}
|
2019-04-26 13:54:14 +07:00
|
|
|
|
|
|
|
/* Disable vcpu's escalation interrupt */
|
|
|
|
if (vcpu->arch.xive_esc_on) {
|
|
|
|
__raw_readq((void __iomem *)(vcpu->arch.xive_esc_vaddr +
|
|
|
|
XIVE_ESB_SET_PQ_01));
|
|
|
|
vcpu->arch.xive_esc_on = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear pointers to escalation interrupt ESB.
|
|
|
|
* This is safe because the vcpu->mutex is held, preventing
|
|
|
|
* any other CPU from concurrently executing a KVM_RUN ioctl.
|
|
|
|
*/
|
|
|
|
vcpu->arch.xive_esc_vaddr = 0;
|
|
|
|
vcpu->arch.xive_esc_raddr = 0;
|
2017-04-05 14:54:56 +07:00
|
|
|
}
|
|
|
|
|
powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race
Testing has revealed the existence of a race condition where a XIVE
interrupt being shut down can be in one of the XIVE interrupt queues
(of which there are up to 8 per CPU, one for each priority) at the
point where free_irq() is called. If this happens, can return an
interrupt number which has been shut down. This can lead to various
symptoms:
- irq_to_desc(irq) can be NULL. In this case, no end-of-interrupt
function gets called, resulting in the CPU's elevated interrupt
priority (numerically lowered CPPR) never gets reset. That then
means that the CPU stops processing interrupts, causing device
timeouts and other errors in various device drivers.
- The irq descriptor or related data structures can be in the process
of being freed as the interrupt code is using them. This typically
leads to crashes due to bad pointer dereferences.
This race is basically what commit 62e0468650c3 ("genirq: Add optional
hardware synchronization for shutdown", 2019-06-28) is intended to
fix, given a get_irqchip_state() method for the interrupt controller
being used. It works by polling the interrupt controller when an
interrupt is being freed until the controller says it is not pending.
With XIVE, the PQ bits of the interrupt source indicate the state of
the interrupt source, and in particular the P bit goes from 0 to 1 at
the point where the hardware writes an entry into the interrupt queue
that this interrupt is directed towards. Normally, the code will then
process the interrupt and do an end-of-interrupt (EOI) operation which
will reset PQ to 00 (assuming another interrupt hasn't been generated
in the meantime). However, there are situations where the code resets
P even though a queue entry exists (for example, by setting PQ to 01,
which disables the interrupt source), and also situations where the
code leaves P at 1 after removing the queue entry (for example, this
is done for escalation interrupts so they cannot fire again until
they are explicitly re-enabled).
The code already has a 'saved_p' flag for the interrupt source which
indicates that a queue entry exists, although it isn't maintained
consistently. This patch adds a 'stale_p' flag to indicate that
P has been left at 1 after processing a queue entry, and adds code
to set and clear saved_p and stale_p as necessary to maintain a
consistent indication of whether a queue entry may or may not exist.
With this, we can implement xive_get_irqchip_state() by looking at
stale_p, saved_p and the ESB PQ bits for the interrupt.
There is some additional code to handle escalation interrupts
properly; because they are enabled and disabled in KVM assembly code,
which does not have access to the xive_irq_data struct for the
escalation interrupt. Hence, stale_p may be incorrect when the
escalation interrupt is freed in kvmppc_xive_{,native_}cleanup_vcpu().
Fortunately, we can fix it up by looking at vcpu->arch.xive_esc_on,
with some careful attention to barriers in order to ensure the correct
result if xive_esc_irq() races with kvmppc_xive_cleanup_vcpu().
Finally, this adds code to make noise on the console (pr_crit and
WARN_ON(1)) if we find an interrupt queue entry for an interrupt
which does not have a descriptor. While this won't catch the race
reliably, if it does get triggered it will be an indication that
the race is occurring and needs to be debugged.
Fixes: 243e25112d06 ("powerpc/xive: Native exploitation of the XIVE interrupt controller")
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190813100648.GE9567@blackberry
2019-08-13 17:06:48 +07:00
|
|
|
/*
|
|
|
|
* In single escalation mode, the escalation interrupt is marked so
|
|
|
|
* that EOI doesn't re-enable it, but just sets the stale_p flag to
|
|
|
|
* indicate that the P bit has already been dealt with. However, the
|
|
|
|
* assembly code that enters the guest sets PQ to 00 without clearing
|
|
|
|
* stale_p (because it has no easy way to address it). Hence we have
|
|
|
|
* to adjust stale_p before shutting down the interrupt.
|
|
|
|
*/
|
|
|
|
void xive_cleanup_single_escalation(struct kvm_vcpu *vcpu,
|
|
|
|
struct kvmppc_xive_vcpu *xc, int irq)
|
|
|
|
{
|
|
|
|
struct irq_data *d = irq_get_irq_data(irq);
|
|
|
|
struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This slightly odd sequence gives the right result
|
|
|
|
* (i.e. stale_p set if xive_esc_on is false) even if
|
|
|
|
* we race with xive_esc_irq() and xive_irq_eoi().
|
|
|
|
*/
|
|
|
|
xd->stale_p = false;
|
|
|
|
smp_mb(); /* paired with smb_wmb in xive_esc_irq */
|
|
|
|
if (!vcpu->arch.xive_esc_on)
|
|
|
|
xd->stale_p = true;
|
|
|
|
}
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
2019-04-18 17:39:42 +07:00
|
|
|
struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
|
2017-04-05 14:54:56 +07:00
|
|
|
int i;
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
if (!kvmppc_xics_enabled(vcpu))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
return;
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
pr_devel("cleanup_vcpu(cpu=%d)\n", xc->server_num);
|
|
|
|
|
|
|
|
/* Ensure no interrupt is still routed to that VP */
|
|
|
|
xc->valid = false;
|
|
|
|
kvmppc_xive_disable_vcpu_interrupts(vcpu);
|
|
|
|
|
|
|
|
/* Mask the VP IPI */
|
|
|
|
xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_01);
|
|
|
|
|
2019-08-07 00:25:38 +07:00
|
|
|
/* Free escalations */
|
2017-04-05 14:54:56 +07:00
|
|
|
for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
|
|
|
|
if (xc->esc_virq[i]) {
|
powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race
Testing has revealed the existence of a race condition where a XIVE
interrupt being shut down can be in one of the XIVE interrupt queues
(of which there are up to 8 per CPU, one for each priority) at the
point where free_irq() is called. If this happens, can return an
interrupt number which has been shut down. This can lead to various
symptoms:
- irq_to_desc(irq) can be NULL. In this case, no end-of-interrupt
function gets called, resulting in the CPU's elevated interrupt
priority (numerically lowered CPPR) never gets reset. That then
means that the CPU stops processing interrupts, causing device
timeouts and other errors in various device drivers.
- The irq descriptor or related data structures can be in the process
of being freed as the interrupt code is using them. This typically
leads to crashes due to bad pointer dereferences.
This race is basically what commit 62e0468650c3 ("genirq: Add optional
hardware synchronization for shutdown", 2019-06-28) is intended to
fix, given a get_irqchip_state() method for the interrupt controller
being used. It works by polling the interrupt controller when an
interrupt is being freed until the controller says it is not pending.
With XIVE, the PQ bits of the interrupt source indicate the state of
the interrupt source, and in particular the P bit goes from 0 to 1 at
the point where the hardware writes an entry into the interrupt queue
that this interrupt is directed towards. Normally, the code will then
process the interrupt and do an end-of-interrupt (EOI) operation which
will reset PQ to 00 (assuming another interrupt hasn't been generated
in the meantime). However, there are situations where the code resets
P even though a queue entry exists (for example, by setting PQ to 01,
which disables the interrupt source), and also situations where the
code leaves P at 1 after removing the queue entry (for example, this
is done for escalation interrupts so they cannot fire again until
they are explicitly re-enabled).
The code already has a 'saved_p' flag for the interrupt source which
indicates that a queue entry exists, although it isn't maintained
consistently. This patch adds a 'stale_p' flag to indicate that
P has been left at 1 after processing a queue entry, and adds code
to set and clear saved_p and stale_p as necessary to maintain a
consistent indication of whether a queue entry may or may not exist.
With this, we can implement xive_get_irqchip_state() by looking at
stale_p, saved_p and the ESB PQ bits for the interrupt.
There is some additional code to handle escalation interrupts
properly; because they are enabled and disabled in KVM assembly code,
which does not have access to the xive_irq_data struct for the
escalation interrupt. Hence, stale_p may be incorrect when the
escalation interrupt is freed in kvmppc_xive_{,native_}cleanup_vcpu().
Fortunately, we can fix it up by looking at vcpu->arch.xive_esc_on,
with some careful attention to barriers in order to ensure the correct
result if xive_esc_irq() races with kvmppc_xive_cleanup_vcpu().
Finally, this adds code to make noise on the console (pr_crit and
WARN_ON(1)) if we find an interrupt queue entry for an interrupt
which does not have a descriptor. While this won't catch the race
reliably, if it does get triggered it will be an indication that
the race is occurring and needs to be debugged.
Fixes: 243e25112d06 ("powerpc/xive: Native exploitation of the XIVE interrupt controller")
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190813100648.GE9567@blackberry
2019-08-13 17:06:48 +07:00
|
|
|
if (xc->xive->single_escalation)
|
|
|
|
xive_cleanup_single_escalation(vcpu, xc,
|
|
|
|
xc->esc_virq[i]);
|
2017-04-05 14:54:56 +07:00
|
|
|
free_irq(xc->esc_virq[i], vcpu);
|
|
|
|
irq_dispose_mapping(xc->esc_virq[i]);
|
|
|
|
kfree(xc->esc_virq_names[i]);
|
|
|
|
}
|
2019-08-07 00:25:38 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Disable the VP */
|
|
|
|
xive_native_disable_vp(xc->vp_id);
|
|
|
|
|
2019-08-13 17:01:00 +07:00
|
|
|
/* Clear the cam word so guest entry won't try to push context */
|
|
|
|
vcpu->arch.xive_cam_word = 0;
|
|
|
|
|
2019-08-07 00:25:38 +07:00
|
|
|
/* Free the queues */
|
|
|
|
for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
|
|
|
|
struct xive_q *q = &xc->queues[i];
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
xive_native_disable_queue(xc->vp_id, q, i);
|
|
|
|
if (q->qpage) {
|
|
|
|
free_pages((unsigned long)q->qpage,
|
|
|
|
xive->q_page_order);
|
|
|
|
q->qpage = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the IPI */
|
|
|
|
if (xc->vp_ipi) {
|
|
|
|
xive_cleanup_irq_data(&xc->vp_ipi_data);
|
|
|
|
xive_native_free_irq(xc->vp_ipi);
|
|
|
|
}
|
|
|
|
/* Free the VP */
|
|
|
|
kfree(xc);
|
2019-04-18 17:39:42 +07:00
|
|
|
|
|
|
|
/* Cleanup the vcpu */
|
|
|
|
vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
|
|
|
|
vcpu->arch.xive_vcpu = NULL;
|
2017-04-05 14:54:56 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
|
|
|
|
struct kvm_vcpu *vcpu, u32 cpu)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
struct kvmppc_xive_vcpu *xc;
|
|
|
|
int i, r = -EBUSY;
|
KVM: PPC: Book3S HV: XIVE: Ensure VP isn't already in use
Connecting a vCPU to a XIVE KVM device means establishing a 1:1
association between a vCPU id and the offset (VP id) of a VP
structure within a fixed size block of VPs. We currently try to
enforce the 1:1 relationship by checking that a vCPU with the
same id isn't already connected. This is good but unfortunately
not enough because we don't map VP ids to raw vCPU ids but to
packed vCPU ids, and the packing function kvmppc_pack_vcpu_id()
isn't bijective by design. We got away with it because QEMU passes
vCPU ids that fit well in the packing pattern. But nothing prevents
userspace to come up with a forged vCPU id resulting in a packed id
collision which causes the KVM device to associate two vCPUs to the
same VP. This greatly confuses the irq layer and ultimately crashes
the kernel, as shown below.
Example: a guest with 1 guest thread per core, a core stride of
8 and 300 vCPUs has vCPU ids 0,8,16...2392. If QEMU is patched to
inject at some point an invalid vCPU id 348, which is the packed
version of itself and 2392, we get:
genirq: Flags mismatch irq 199. 00010000 (kvm-2-2392) vs. 00010000 (kvm-2-348)
CPU: 24 PID: 88176 Comm: qemu-system-ppc Not tainted 5.3.0-xive-nr-servers-5.3-gku+ #38
Call Trace:
[c000003f7f9937e0] [c000000000c0110c] dump_stack+0xb0/0xf4 (unreliable)
[c000003f7f993820] [c0000000001cb480] __setup_irq+0xa70/0xad0
[c000003f7f9938d0] [c0000000001cb75c] request_threaded_irq+0x13c/0x260
[c000003f7f993940] [c00800000d44e7ac] kvmppc_xive_attach_escalation+0x104/0x270 [kvm]
[c000003f7f9939d0] [c00800000d45013c] kvmppc_xive_connect_vcpu+0x424/0x620 [kvm]
[c000003f7f993ac0] [c00800000d444428] kvm_arch_vcpu_ioctl+0x260/0x448 [kvm]
[c000003f7f993b90] [c00800000d43593c] kvm_vcpu_ioctl+0x154/0x7c8 [kvm]
[c000003f7f993d00] [c0000000004840f0] do_vfs_ioctl+0xe0/0xc30
[c000003f7f993db0] [c000000000484d44] ksys_ioctl+0x104/0x120
[c000003f7f993e00] [c000000000484d88] sys_ioctl+0x28/0x80
[c000003f7f993e20] [c00000000000b278] system_call+0x5c/0x68
xive-kvm: Failed to request escalation interrupt for queue 0 of VCPU 2392
------------[ cut here ]------------
remove_proc_entry: removing non-empty directory 'irq/199', leaking at least 'kvm-2-348'
WARNING: CPU: 24 PID: 88176 at /home/greg/Work/linux/kernel-kvm-ppc/fs/proc/generic.c:684 remove_proc_entry+0x1ec/0x200
Modules linked in: kvm_hv kvm dm_mod vhost_net vhost tap xt_CHECKSUM iptable_mangle xt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter squashfs loop fuse i2c_dev sg ofpart ocxl powernv_flash at24 xts mtd uio_pdrv_genirq vmx_crypto opal_prd ipmi_powernv uio ipmi_devintf ipmi_msghandler ibmpowernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables ext4 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq libcrc32c raid1 raid0 linear sd_mod ast i2c_algo_bit drm_vram_helper ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci libahci libata tg3 drm_panel_orientation_quirks [last unloaded: kvm]
CPU: 24 PID: 88176 Comm: qemu-system-ppc Not tainted 5.3.0-xive-nr-servers-5.3-gku+ #38
NIP: c00000000053b0cc LR: c00000000053b0c8 CTR: c0000000000ba3b0
REGS: c000003f7f9934b0 TRAP: 0700 Not tainted (5.3.0-xive-nr-servers-5.3-gku+)
MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 48228222 XER: 20040000
CFAR: c000000000131a50 IRQMASK: 0
GPR00: c00000000053b0c8 c000003f7f993740 c0000000015ec500 0000000000000057
GPR04: 0000000000000001 0000000000000000 000049fb98484262 0000000000001bcf
GPR08: 0000000000000007 0000000000000007 0000000000000001 9000000000001033
GPR12: 0000000000008000 c000003ffffeb800 0000000000000000 000000012f4ce5a1
GPR16: 000000012ef5a0c8 0000000000000000 000000012f113bb0 0000000000000000
GPR20: 000000012f45d918 c000003f863758b0 c000003f86375870 0000000000000006
GPR24: c000003f86375a30 0000000000000007 c0002039373d9020 c0000000014c4a48
GPR28: 0000000000000001 c000003fe62a4f6b c00020394b2e9fab c000003fe62a4ec0
NIP [c00000000053b0cc] remove_proc_entry+0x1ec/0x200
LR [c00000000053b0c8] remove_proc_entry+0x1e8/0x200
Call Trace:
[c000003f7f993740] [c00000000053b0c8] remove_proc_entry+0x1e8/0x200 (unreliable)
[c000003f7f9937e0] [c0000000001d3654] unregister_irq_proc+0x114/0x150
[c000003f7f993880] [c0000000001c6284] free_desc+0x54/0xb0
[c000003f7f9938c0] [c0000000001c65ec] irq_free_descs+0xac/0x100
[c000003f7f993910] [c0000000001d1ff8] irq_dispose_mapping+0x68/0x80
[c000003f7f993940] [c00800000d44e8a4] kvmppc_xive_attach_escalation+0x1fc/0x270 [kvm]
[c000003f7f9939d0] [c00800000d45013c] kvmppc_xive_connect_vcpu+0x424/0x620 [kvm]
[c000003f7f993ac0] [c00800000d444428] kvm_arch_vcpu_ioctl+0x260/0x448 [kvm]
[c000003f7f993b90] [c00800000d43593c] kvm_vcpu_ioctl+0x154/0x7c8 [kvm]
[c000003f7f993d00] [c0000000004840f0] do_vfs_ioctl+0xe0/0xc30
[c000003f7f993db0] [c000000000484d44] ksys_ioctl+0x104/0x120
[c000003f7f993e00] [c000000000484d88] sys_ioctl+0x28/0x80
[c000003f7f993e20] [c00000000000b278] system_call+0x5c/0x68
Instruction dump:
2c230000 41820008 3923ff78 e8e900a0 3c82ff69 3c62ff8d 7fa6eb78 7fc5f378
3884f080 3863b948 4bbf6925 60000000 <0fe00000> 4bffff7c fba10088 4bbf6e41
---[ end trace b925b67a74a1d8d1 ]---
BUG: Kernel NULL pointer dereference at 0x00000010
Faulting instruction address: 0xc00800000d44fc04
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Radix MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
Modules linked in: kvm_hv kvm dm_mod vhost_net vhost tap xt_CHECKSUM iptable_mangle xt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter squashfs loop fuse i2c_dev sg ofpart ocxl powernv_flash at24 xts mtd uio_pdrv_genirq vmx_crypto opal_prd ipmi_powernv uio ipmi_devintf ipmi_msghandler ibmpowernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables ext4 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq libcrc32c raid1 raid0 linear sd_mod ast i2c_algo_bit drm_vram_helper ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci libahci libata tg3 drm_panel_orientation_quirks [last unloaded: kvm]
CPU: 24 PID: 88176 Comm: qemu-system-ppc Tainted: G W 5.3.0-xive-nr-servers-5.3-gku+ #38
NIP: c00800000d44fc04 LR: c00800000d44fc00 CTR: c0000000001cd970
REGS: c000003f7f9938e0 TRAP: 0300 Tainted: G W (5.3.0-xive-nr-servers-5.3-gku+)
MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24228882 XER: 20040000
CFAR: c0000000001cd9ac DAR: 0000000000000010 DSISR: 40000000 IRQMASK: 0
GPR00: c00800000d44fc00 c000003f7f993b70 c00800000d468300 0000000000000000
GPR04: 00000000000000c7 0000000000000000 0000000000000000 c000003ffacd06d8
GPR08: 0000000000000000 c000003ffacd0738 0000000000000000 fffffffffffffffd
GPR12: 0000000000000040 c000003ffffeb800 0000000000000000 000000012f4ce5a1
GPR16: 000000012ef5a0c8 0000000000000000 000000012f113bb0 0000000000000000
GPR20: 000000012f45d918 00007ffffe0d9a80 000000012f4f5df0 000000012ef8c9f8
GPR24: 0000000000000001 0000000000000000 c000003fe4501ed0 c000003f8b1d0000
GPR28: c0000033314689c0 c000003fe4501c00 c000003fe4501e70 c000003fe4501e90
NIP [c00800000d44fc04] kvmppc_xive_cleanup_vcpu+0xfc/0x210 [kvm]
LR [c00800000d44fc00] kvmppc_xive_cleanup_vcpu+0xf8/0x210 [kvm]
Call Trace:
[c000003f7f993b70] [c00800000d44fc00] kvmppc_xive_cleanup_vcpu+0xf8/0x210 [kvm] (unreliable)
[c000003f7f993bd0] [c00800000d450bd4] kvmppc_xive_release+0xdc/0x1b0 [kvm]
[c000003f7f993c30] [c00800000d436a98] kvm_device_release+0xb0/0x110 [kvm]
[c000003f7f993c70] [c00000000046730c] __fput+0xec/0x320
[c000003f7f993cd0] [c000000000164ae0] task_work_run+0x150/0x1c0
[c000003f7f993d30] [c000000000025034] do_notify_resume+0x304/0x440
[c000003f7f993e20] [c00000000000dcc4] ret_from_except_lite+0x70/0x74
Instruction dump:
3bff0008 7fbfd040 419e0054 847e0004 2fa30000 419effec e93d0000 8929203c
2f890000 419effb8 4800821d e8410018 <e9230010> e9490008 9b2a0039 7c0004ac
---[ end trace b925b67a74a1d8d2 ]---
Kernel panic - not syncing: Fatal exception
This affects both XIVE and XICS-on-XIVE devices since the beginning.
Check the VP id instead of the vCPU id when a new vCPU is connected.
The allocation of the XIVE CPU structure in kvmppc_xive_connect_vcpu()
is moved after the check to avoid the need for rollback.
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-09-27 18:53:43 +07:00
|
|
|
u32 vp_id;
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
pr_devel("connect_vcpu(cpu=%d)\n", cpu);
|
|
|
|
|
|
|
|
if (dev->ops != &kvm_xive_ops) {
|
|
|
|
pr_devel("Wrong ops !\n");
|
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
if (xive->kvm != vcpu->kvm)
|
|
|
|
return -EPERM;
|
2019-04-18 17:39:42 +07:00
|
|
|
if (vcpu->arch.irq_type != KVMPPC_IRQ_DEFAULT)
|
2017-04-05 14:54:56 +07:00
|
|
|
return -EBUSY;
|
KVM: PPC: Book3S HV: Pack VCORE IDs to access full VCPU ID space
It is not currently possible to create the full number of possible
VCPUs (KVM_MAX_VCPUS) on Power9 with KVM-HV when the guest uses fewer
threads per core than its core stride (or "VSMT mode"). This is
because the VCORE ID and XIVE offsets grow beyond KVM_MAX_VCPUS
even though the VCPU ID is less than KVM_MAX_VCPU_ID.
To address this, "pack" the VCORE ID and XIVE offsets by using
knowledge of the way the VCPU IDs will be used when there are fewer
guest threads per core than the core stride. The primary thread of
each core will always be used first. Then, if the guest uses more than
one thread per core, these secondary threads will sequentially follow
the primary in each core.
So, the only way an ID above KVM_MAX_VCPUS can be seen, is if the
VCPUs are being spaced apart, so at least half of each core is empty,
and IDs between KVM_MAX_VCPUS and (KVM_MAX_VCPUS * 2) can be mapped
into the second half of each core (4..7, in an 8-thread core).
Similarly, if IDs above KVM_MAX_VCPUS * 2 are seen, at least 3/4 of
each core is being left empty, and we can map down into the second and
third quarters of each core (2, 3 and 5, 6 in an 8-thread core).
Lastly, if IDs above KVM_MAX_VCPUS * 4 are seen, only the primary
threads are being used and 7/8 of the core is empty, allowing use of
the 1, 5, 3 and 7 thread slots.
(Strides less than 8 are handled similarly.)
This allows the VCORE ID or offset to be calculated quickly from the
VCPU ID or XIVE server numbers, without access to the VCPU structure.
[paulus@ozlabs.org - tidied up comment a little, changed some WARN_ONCE
to pr_devel, wrapped line, fixed id check.]
Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2018-07-25 13:12:02 +07:00
|
|
|
if (cpu >= (KVM_MAX_VCPUS * vcpu->kvm->arch.emul_smt_mode)) {
|
2017-04-05 14:54:56 +07:00
|
|
|
pr_devel("Out of bounds !\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We need to synchronize with queue provisioning */
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_lock(&xive->lock);
|
KVM: PPC: Book3S HV: XIVE: Ensure VP isn't already in use
Connecting a vCPU to a XIVE KVM device means establishing a 1:1
association between a vCPU id and the offset (VP id) of a VP
structure within a fixed size block of VPs. We currently try to
enforce the 1:1 relationship by checking that a vCPU with the
same id isn't already connected. This is good but unfortunately
not enough because we don't map VP ids to raw vCPU ids but to
packed vCPU ids, and the packing function kvmppc_pack_vcpu_id()
isn't bijective by design. We got away with it because QEMU passes
vCPU ids that fit well in the packing pattern. But nothing prevents
userspace to come up with a forged vCPU id resulting in a packed id
collision which causes the KVM device to associate two vCPUs to the
same VP. This greatly confuses the irq layer and ultimately crashes
the kernel, as shown below.
Example: a guest with 1 guest thread per core, a core stride of
8 and 300 vCPUs has vCPU ids 0,8,16...2392. If QEMU is patched to
inject at some point an invalid vCPU id 348, which is the packed
version of itself and 2392, we get:
genirq: Flags mismatch irq 199. 00010000 (kvm-2-2392) vs. 00010000 (kvm-2-348)
CPU: 24 PID: 88176 Comm: qemu-system-ppc Not tainted 5.3.0-xive-nr-servers-5.3-gku+ #38
Call Trace:
[c000003f7f9937e0] [c000000000c0110c] dump_stack+0xb0/0xf4 (unreliable)
[c000003f7f993820] [c0000000001cb480] __setup_irq+0xa70/0xad0
[c000003f7f9938d0] [c0000000001cb75c] request_threaded_irq+0x13c/0x260
[c000003f7f993940] [c00800000d44e7ac] kvmppc_xive_attach_escalation+0x104/0x270 [kvm]
[c000003f7f9939d0] [c00800000d45013c] kvmppc_xive_connect_vcpu+0x424/0x620 [kvm]
[c000003f7f993ac0] [c00800000d444428] kvm_arch_vcpu_ioctl+0x260/0x448 [kvm]
[c000003f7f993b90] [c00800000d43593c] kvm_vcpu_ioctl+0x154/0x7c8 [kvm]
[c000003f7f993d00] [c0000000004840f0] do_vfs_ioctl+0xe0/0xc30
[c000003f7f993db0] [c000000000484d44] ksys_ioctl+0x104/0x120
[c000003f7f993e00] [c000000000484d88] sys_ioctl+0x28/0x80
[c000003f7f993e20] [c00000000000b278] system_call+0x5c/0x68
xive-kvm: Failed to request escalation interrupt for queue 0 of VCPU 2392
------------[ cut here ]------------
remove_proc_entry: removing non-empty directory 'irq/199', leaking at least 'kvm-2-348'
WARNING: CPU: 24 PID: 88176 at /home/greg/Work/linux/kernel-kvm-ppc/fs/proc/generic.c:684 remove_proc_entry+0x1ec/0x200
Modules linked in: kvm_hv kvm dm_mod vhost_net vhost tap xt_CHECKSUM iptable_mangle xt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter squashfs loop fuse i2c_dev sg ofpart ocxl powernv_flash at24 xts mtd uio_pdrv_genirq vmx_crypto opal_prd ipmi_powernv uio ipmi_devintf ipmi_msghandler ibmpowernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables ext4 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq libcrc32c raid1 raid0 linear sd_mod ast i2c_algo_bit drm_vram_helper ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci libahci libata tg3 drm_panel_orientation_quirks [last unloaded: kvm]
CPU: 24 PID: 88176 Comm: qemu-system-ppc Not tainted 5.3.0-xive-nr-servers-5.3-gku+ #38
NIP: c00000000053b0cc LR: c00000000053b0c8 CTR: c0000000000ba3b0
REGS: c000003f7f9934b0 TRAP: 0700 Not tainted (5.3.0-xive-nr-servers-5.3-gku+)
MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 48228222 XER: 20040000
CFAR: c000000000131a50 IRQMASK: 0
GPR00: c00000000053b0c8 c000003f7f993740 c0000000015ec500 0000000000000057
GPR04: 0000000000000001 0000000000000000 000049fb98484262 0000000000001bcf
GPR08: 0000000000000007 0000000000000007 0000000000000001 9000000000001033
GPR12: 0000000000008000 c000003ffffeb800 0000000000000000 000000012f4ce5a1
GPR16: 000000012ef5a0c8 0000000000000000 000000012f113bb0 0000000000000000
GPR20: 000000012f45d918 c000003f863758b0 c000003f86375870 0000000000000006
GPR24: c000003f86375a30 0000000000000007 c0002039373d9020 c0000000014c4a48
GPR28: 0000000000000001 c000003fe62a4f6b c00020394b2e9fab c000003fe62a4ec0
NIP [c00000000053b0cc] remove_proc_entry+0x1ec/0x200
LR [c00000000053b0c8] remove_proc_entry+0x1e8/0x200
Call Trace:
[c000003f7f993740] [c00000000053b0c8] remove_proc_entry+0x1e8/0x200 (unreliable)
[c000003f7f9937e0] [c0000000001d3654] unregister_irq_proc+0x114/0x150
[c000003f7f993880] [c0000000001c6284] free_desc+0x54/0xb0
[c000003f7f9938c0] [c0000000001c65ec] irq_free_descs+0xac/0x100
[c000003f7f993910] [c0000000001d1ff8] irq_dispose_mapping+0x68/0x80
[c000003f7f993940] [c00800000d44e8a4] kvmppc_xive_attach_escalation+0x1fc/0x270 [kvm]
[c000003f7f9939d0] [c00800000d45013c] kvmppc_xive_connect_vcpu+0x424/0x620 [kvm]
[c000003f7f993ac0] [c00800000d444428] kvm_arch_vcpu_ioctl+0x260/0x448 [kvm]
[c000003f7f993b90] [c00800000d43593c] kvm_vcpu_ioctl+0x154/0x7c8 [kvm]
[c000003f7f993d00] [c0000000004840f0] do_vfs_ioctl+0xe0/0xc30
[c000003f7f993db0] [c000000000484d44] ksys_ioctl+0x104/0x120
[c000003f7f993e00] [c000000000484d88] sys_ioctl+0x28/0x80
[c000003f7f993e20] [c00000000000b278] system_call+0x5c/0x68
Instruction dump:
2c230000 41820008 3923ff78 e8e900a0 3c82ff69 3c62ff8d 7fa6eb78 7fc5f378
3884f080 3863b948 4bbf6925 60000000 <0fe00000> 4bffff7c fba10088 4bbf6e41
---[ end trace b925b67a74a1d8d1 ]---
BUG: Kernel NULL pointer dereference at 0x00000010
Faulting instruction address: 0xc00800000d44fc04
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Radix MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
Modules linked in: kvm_hv kvm dm_mod vhost_net vhost tap xt_CHECKSUM iptable_mangle xt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter squashfs loop fuse i2c_dev sg ofpart ocxl powernv_flash at24 xts mtd uio_pdrv_genirq vmx_crypto opal_prd ipmi_powernv uio ipmi_devintf ipmi_msghandler ibmpowernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables ext4 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq libcrc32c raid1 raid0 linear sd_mod ast i2c_algo_bit drm_vram_helper ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci libahci libata tg3 drm_panel_orientation_quirks [last unloaded: kvm]
CPU: 24 PID: 88176 Comm: qemu-system-ppc Tainted: G W 5.3.0-xive-nr-servers-5.3-gku+ #38
NIP: c00800000d44fc04 LR: c00800000d44fc00 CTR: c0000000001cd970
REGS: c000003f7f9938e0 TRAP: 0300 Tainted: G W (5.3.0-xive-nr-servers-5.3-gku+)
MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24228882 XER: 20040000
CFAR: c0000000001cd9ac DAR: 0000000000000010 DSISR: 40000000 IRQMASK: 0
GPR00: c00800000d44fc00 c000003f7f993b70 c00800000d468300 0000000000000000
GPR04: 00000000000000c7 0000000000000000 0000000000000000 c000003ffacd06d8
GPR08: 0000000000000000 c000003ffacd0738 0000000000000000 fffffffffffffffd
GPR12: 0000000000000040 c000003ffffeb800 0000000000000000 000000012f4ce5a1
GPR16: 000000012ef5a0c8 0000000000000000 000000012f113bb0 0000000000000000
GPR20: 000000012f45d918 00007ffffe0d9a80 000000012f4f5df0 000000012ef8c9f8
GPR24: 0000000000000001 0000000000000000 c000003fe4501ed0 c000003f8b1d0000
GPR28: c0000033314689c0 c000003fe4501c00 c000003fe4501e70 c000003fe4501e90
NIP [c00800000d44fc04] kvmppc_xive_cleanup_vcpu+0xfc/0x210 [kvm]
LR [c00800000d44fc00] kvmppc_xive_cleanup_vcpu+0xf8/0x210 [kvm]
Call Trace:
[c000003f7f993b70] [c00800000d44fc00] kvmppc_xive_cleanup_vcpu+0xf8/0x210 [kvm] (unreliable)
[c000003f7f993bd0] [c00800000d450bd4] kvmppc_xive_release+0xdc/0x1b0 [kvm]
[c000003f7f993c30] [c00800000d436a98] kvm_device_release+0xb0/0x110 [kvm]
[c000003f7f993c70] [c00000000046730c] __fput+0xec/0x320
[c000003f7f993cd0] [c000000000164ae0] task_work_run+0x150/0x1c0
[c000003f7f993d30] [c000000000025034] do_notify_resume+0x304/0x440
[c000003f7f993e20] [c00000000000dcc4] ret_from_except_lite+0x70/0x74
Instruction dump:
3bff0008 7fbfd040 419e0054 847e0004 2fa30000 419effec e93d0000 8929203c
2f890000 419effb8 4800821d e8410018 <e9230010> e9490008 9b2a0039 7c0004ac
---[ end trace b925b67a74a1d8d2 ]---
Kernel panic - not syncing: Fatal exception
This affects both XIVE and XICS-on-XIVE devices since the beginning.
Check the VP id instead of the vCPU id when a new vCPU is connected.
The allocation of the XIVE CPU structure in kvmppc_xive_connect_vcpu()
is moved after the check to avoid the need for rollback.
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-09-27 18:53:43 +07:00
|
|
|
|
|
|
|
vp_id = kvmppc_xive_vp(xive, cpu);
|
|
|
|
if (kvmppc_xive_vp_in_use(xive->kvm, vp_id)) {
|
|
|
|
pr_devel("Duplicate !\n");
|
|
|
|
r = -EEXIST;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
|
|
|
xc = kzalloc(sizeof(*xc), GFP_KERNEL);
|
|
|
|
if (!xc) {
|
|
|
|
r = -ENOMEM;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
vcpu->arch.xive_vcpu = xc;
|
|
|
|
xc->xive = xive;
|
|
|
|
xc->vcpu = vcpu;
|
|
|
|
xc->server_num = cpu;
|
KVM: PPC: Book3S HV: XIVE: Ensure VP isn't already in use
Connecting a vCPU to a XIVE KVM device means establishing a 1:1
association between a vCPU id and the offset (VP id) of a VP
structure within a fixed size block of VPs. We currently try to
enforce the 1:1 relationship by checking that a vCPU with the
same id isn't already connected. This is good but unfortunately
not enough because we don't map VP ids to raw vCPU ids but to
packed vCPU ids, and the packing function kvmppc_pack_vcpu_id()
isn't bijective by design. We got away with it because QEMU passes
vCPU ids that fit well in the packing pattern. But nothing prevents
userspace to come up with a forged vCPU id resulting in a packed id
collision which causes the KVM device to associate two vCPUs to the
same VP. This greatly confuses the irq layer and ultimately crashes
the kernel, as shown below.
Example: a guest with 1 guest thread per core, a core stride of
8 and 300 vCPUs has vCPU ids 0,8,16...2392. If QEMU is patched to
inject at some point an invalid vCPU id 348, which is the packed
version of itself and 2392, we get:
genirq: Flags mismatch irq 199. 00010000 (kvm-2-2392) vs. 00010000 (kvm-2-348)
CPU: 24 PID: 88176 Comm: qemu-system-ppc Not tainted 5.3.0-xive-nr-servers-5.3-gku+ #38
Call Trace:
[c000003f7f9937e0] [c000000000c0110c] dump_stack+0xb0/0xf4 (unreliable)
[c000003f7f993820] [c0000000001cb480] __setup_irq+0xa70/0xad0
[c000003f7f9938d0] [c0000000001cb75c] request_threaded_irq+0x13c/0x260
[c000003f7f993940] [c00800000d44e7ac] kvmppc_xive_attach_escalation+0x104/0x270 [kvm]
[c000003f7f9939d0] [c00800000d45013c] kvmppc_xive_connect_vcpu+0x424/0x620 [kvm]
[c000003f7f993ac0] [c00800000d444428] kvm_arch_vcpu_ioctl+0x260/0x448 [kvm]
[c000003f7f993b90] [c00800000d43593c] kvm_vcpu_ioctl+0x154/0x7c8 [kvm]
[c000003f7f993d00] [c0000000004840f0] do_vfs_ioctl+0xe0/0xc30
[c000003f7f993db0] [c000000000484d44] ksys_ioctl+0x104/0x120
[c000003f7f993e00] [c000000000484d88] sys_ioctl+0x28/0x80
[c000003f7f993e20] [c00000000000b278] system_call+0x5c/0x68
xive-kvm: Failed to request escalation interrupt for queue 0 of VCPU 2392
------------[ cut here ]------------
remove_proc_entry: removing non-empty directory 'irq/199', leaking at least 'kvm-2-348'
WARNING: CPU: 24 PID: 88176 at /home/greg/Work/linux/kernel-kvm-ppc/fs/proc/generic.c:684 remove_proc_entry+0x1ec/0x200
Modules linked in: kvm_hv kvm dm_mod vhost_net vhost tap xt_CHECKSUM iptable_mangle xt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter squashfs loop fuse i2c_dev sg ofpart ocxl powernv_flash at24 xts mtd uio_pdrv_genirq vmx_crypto opal_prd ipmi_powernv uio ipmi_devintf ipmi_msghandler ibmpowernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables ext4 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq libcrc32c raid1 raid0 linear sd_mod ast i2c_algo_bit drm_vram_helper ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci libahci libata tg3 drm_panel_orientation_quirks [last unloaded: kvm]
CPU: 24 PID: 88176 Comm: qemu-system-ppc Not tainted 5.3.0-xive-nr-servers-5.3-gku+ #38
NIP: c00000000053b0cc LR: c00000000053b0c8 CTR: c0000000000ba3b0
REGS: c000003f7f9934b0 TRAP: 0700 Not tainted (5.3.0-xive-nr-servers-5.3-gku+)
MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 48228222 XER: 20040000
CFAR: c000000000131a50 IRQMASK: 0
GPR00: c00000000053b0c8 c000003f7f993740 c0000000015ec500 0000000000000057
GPR04: 0000000000000001 0000000000000000 000049fb98484262 0000000000001bcf
GPR08: 0000000000000007 0000000000000007 0000000000000001 9000000000001033
GPR12: 0000000000008000 c000003ffffeb800 0000000000000000 000000012f4ce5a1
GPR16: 000000012ef5a0c8 0000000000000000 000000012f113bb0 0000000000000000
GPR20: 000000012f45d918 c000003f863758b0 c000003f86375870 0000000000000006
GPR24: c000003f86375a30 0000000000000007 c0002039373d9020 c0000000014c4a48
GPR28: 0000000000000001 c000003fe62a4f6b c00020394b2e9fab c000003fe62a4ec0
NIP [c00000000053b0cc] remove_proc_entry+0x1ec/0x200
LR [c00000000053b0c8] remove_proc_entry+0x1e8/0x200
Call Trace:
[c000003f7f993740] [c00000000053b0c8] remove_proc_entry+0x1e8/0x200 (unreliable)
[c000003f7f9937e0] [c0000000001d3654] unregister_irq_proc+0x114/0x150
[c000003f7f993880] [c0000000001c6284] free_desc+0x54/0xb0
[c000003f7f9938c0] [c0000000001c65ec] irq_free_descs+0xac/0x100
[c000003f7f993910] [c0000000001d1ff8] irq_dispose_mapping+0x68/0x80
[c000003f7f993940] [c00800000d44e8a4] kvmppc_xive_attach_escalation+0x1fc/0x270 [kvm]
[c000003f7f9939d0] [c00800000d45013c] kvmppc_xive_connect_vcpu+0x424/0x620 [kvm]
[c000003f7f993ac0] [c00800000d444428] kvm_arch_vcpu_ioctl+0x260/0x448 [kvm]
[c000003f7f993b90] [c00800000d43593c] kvm_vcpu_ioctl+0x154/0x7c8 [kvm]
[c000003f7f993d00] [c0000000004840f0] do_vfs_ioctl+0xe0/0xc30
[c000003f7f993db0] [c000000000484d44] ksys_ioctl+0x104/0x120
[c000003f7f993e00] [c000000000484d88] sys_ioctl+0x28/0x80
[c000003f7f993e20] [c00000000000b278] system_call+0x5c/0x68
Instruction dump:
2c230000 41820008 3923ff78 e8e900a0 3c82ff69 3c62ff8d 7fa6eb78 7fc5f378
3884f080 3863b948 4bbf6925 60000000 <0fe00000> 4bffff7c fba10088 4bbf6e41
---[ end trace b925b67a74a1d8d1 ]---
BUG: Kernel NULL pointer dereference at 0x00000010
Faulting instruction address: 0xc00800000d44fc04
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Radix MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
Modules linked in: kvm_hv kvm dm_mod vhost_net vhost tap xt_CHECKSUM iptable_mangle xt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter squashfs loop fuse i2c_dev sg ofpart ocxl powernv_flash at24 xts mtd uio_pdrv_genirq vmx_crypto opal_prd ipmi_powernv uio ipmi_devintf ipmi_msghandler ibmpowernv ib_iser rdma_cm iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables ext4 mbcache jbd2 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq libcrc32c raid1 raid0 linear sd_mod ast i2c_algo_bit drm_vram_helper ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm ahci libahci libata tg3 drm_panel_orientation_quirks [last unloaded: kvm]
CPU: 24 PID: 88176 Comm: qemu-system-ppc Tainted: G W 5.3.0-xive-nr-servers-5.3-gku+ #38
NIP: c00800000d44fc04 LR: c00800000d44fc00 CTR: c0000000001cd970
REGS: c000003f7f9938e0 TRAP: 0300 Tainted: G W (5.3.0-xive-nr-servers-5.3-gku+)
MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24228882 XER: 20040000
CFAR: c0000000001cd9ac DAR: 0000000000000010 DSISR: 40000000 IRQMASK: 0
GPR00: c00800000d44fc00 c000003f7f993b70 c00800000d468300 0000000000000000
GPR04: 00000000000000c7 0000000000000000 0000000000000000 c000003ffacd06d8
GPR08: 0000000000000000 c000003ffacd0738 0000000000000000 fffffffffffffffd
GPR12: 0000000000000040 c000003ffffeb800 0000000000000000 000000012f4ce5a1
GPR16: 000000012ef5a0c8 0000000000000000 000000012f113bb0 0000000000000000
GPR20: 000000012f45d918 00007ffffe0d9a80 000000012f4f5df0 000000012ef8c9f8
GPR24: 0000000000000001 0000000000000000 c000003fe4501ed0 c000003f8b1d0000
GPR28: c0000033314689c0 c000003fe4501c00 c000003fe4501e70 c000003fe4501e90
NIP [c00800000d44fc04] kvmppc_xive_cleanup_vcpu+0xfc/0x210 [kvm]
LR [c00800000d44fc00] kvmppc_xive_cleanup_vcpu+0xf8/0x210 [kvm]
Call Trace:
[c000003f7f993b70] [c00800000d44fc00] kvmppc_xive_cleanup_vcpu+0xf8/0x210 [kvm] (unreliable)
[c000003f7f993bd0] [c00800000d450bd4] kvmppc_xive_release+0xdc/0x1b0 [kvm]
[c000003f7f993c30] [c00800000d436a98] kvm_device_release+0xb0/0x110 [kvm]
[c000003f7f993c70] [c00000000046730c] __fput+0xec/0x320
[c000003f7f993cd0] [c000000000164ae0] task_work_run+0x150/0x1c0
[c000003f7f993d30] [c000000000025034] do_notify_resume+0x304/0x440
[c000003f7f993e20] [c00000000000dcc4] ret_from_except_lite+0x70/0x74
Instruction dump:
3bff0008 7fbfd040 419e0054 847e0004 2fa30000 419effec e93d0000 8929203c
2f890000 419effb8 4800821d e8410018 <e9230010> e9490008 9b2a0039 7c0004ac
---[ end trace b925b67a74a1d8d2 ]---
Kernel panic - not syncing: Fatal exception
This affects both XIVE and XICS-on-XIVE devices since the beginning.
Check the VP id instead of the vCPU id when a new vCPU is connected.
The allocation of the XIVE CPU structure in kvmppc_xive_connect_vcpu()
is moved after the check to avoid the need for rollback.
Cc: stable@vger.kernel.org # v4.12+
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-09-27 18:53:43 +07:00
|
|
|
xc->vp_id = vp_id;
|
2017-04-05 14:54:56 +07:00
|
|
|
xc->mfrr = 0xff;
|
|
|
|
xc->valid = true;
|
|
|
|
|
|
|
|
r = xive_native_get_vp_info(xc->vp_id, &xc->vp_cam, &xc->vp_chip_id);
|
|
|
|
if (r)
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
/* Configure VCPU fields for use by assembly push/pull */
|
|
|
|
vcpu->arch.xive_saved_state.w01 = cpu_to_be64(0xff000000);
|
|
|
|
vcpu->arch.xive_cam_word = cpu_to_be32(xc->vp_cam | TM_QW1W2_VO);
|
|
|
|
|
|
|
|
/* Allocate IPI */
|
|
|
|
xc->vp_ipi = xive_native_alloc_irq();
|
|
|
|
if (!xc->vp_ipi) {
|
2018-01-12 09:37:12 +07:00
|
|
|
pr_err("Failed to allocate xive irq for VCPU IPI\n");
|
2017-04-05 14:54:56 +07:00
|
|
|
r = -EIO;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
pr_devel(" IPI=0x%x\n", xc->vp_ipi);
|
|
|
|
|
|
|
|
r = xive_native_populate_irq_data(xc->vp_ipi, &xc->vp_ipi_data);
|
|
|
|
if (r)
|
|
|
|
goto bail;
|
|
|
|
|
2018-01-12 09:37:12 +07:00
|
|
|
/*
|
|
|
|
* Enable the VP first as the single escalation mode will
|
|
|
|
* affect escalation interrupts numbering
|
|
|
|
*/
|
|
|
|
r = xive_native_enable_vp(xc->vp_id, xive->single_escalation);
|
|
|
|
if (r) {
|
|
|
|
pr_err("Failed to enable VP in OPAL, err %d\n", r);
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
/*
|
|
|
|
* Initialize queues. Initially we set them all for no queueing
|
|
|
|
* and we enable escalation for queue 0 only which we'll use for
|
|
|
|
* our mfrr change notifications. If the VCPU is hot-plugged, we
|
2018-01-12 09:37:12 +07:00
|
|
|
* do handle provisioning however based on the existing "map"
|
|
|
|
* of enabled queues.
|
2017-04-05 14:54:56 +07:00
|
|
|
*/
|
|
|
|
for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
|
|
|
|
struct xive_q *q = &xc->queues[i];
|
|
|
|
|
2018-01-12 09:37:12 +07:00
|
|
|
/* Single escalation, no queue 7 */
|
|
|
|
if (i == 7 && xive->single_escalation)
|
|
|
|
break;
|
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
/* Is queue already enabled ? Provision it */
|
|
|
|
if (xive->qmap & (1 << i)) {
|
|
|
|
r = xive_provision_queue(vcpu, i);
|
2018-01-12 09:37:12 +07:00
|
|
|
if (r == 0 && !xive->single_escalation)
|
2019-04-18 17:39:31 +07:00
|
|
|
kvmppc_xive_attach_escalation(
|
|
|
|
vcpu, i, xive->single_escalation);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (r)
|
|
|
|
goto bail;
|
|
|
|
} else {
|
|
|
|
r = xive_native_configure_queue(xc->vp_id,
|
|
|
|
q, i, NULL, 0, true);
|
|
|
|
if (r) {
|
|
|
|
pr_err("Failed to configure queue %d for VCPU %d\n",
|
|
|
|
i, cpu);
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If not done above, attach priority 0 escalation */
|
2019-04-18 17:39:31 +07:00
|
|
|
r = kvmppc_xive_attach_escalation(vcpu, 0, xive->single_escalation);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (r)
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
/* Route the IPI */
|
|
|
|
r = xive_native_configure_irq(xc->vp_ipi, xc->vp_id, 0, XICS_IPI);
|
|
|
|
if (!r)
|
|
|
|
xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_00);
|
|
|
|
|
|
|
|
bail:
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (r) {
|
|
|
|
kvmppc_xive_cleanup_vcpu(vcpu);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcpu->arch.irq_type = KVMPPC_IRQ_XICS;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Scanning of queues before/after migration save
|
|
|
|
*/
|
|
|
|
static void xive_pre_save_set_queued(struct kvmppc_xive *xive, u32 irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
/* Some sanity checking */
|
|
|
|
if (!state->valid) {
|
|
|
|
pr_err("invalid irq 0x%x in cpu queue!\n", irq);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the interrupt is in a queue it should have P set.
|
|
|
|
* We warn so that gets reported. A backtrace isn't useful
|
|
|
|
* so no need to use a WARN_ON.
|
|
|
|
*/
|
|
|
|
if (!state->saved_p)
|
|
|
|
pr_err("Interrupt 0x%x is marked in a queue but P not set !\n", irq);
|
|
|
|
|
|
|
|
/* Set flag */
|
|
|
|
state->in_queue = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_pre_save_mask_irq(struct kvmppc_xive *xive,
|
|
|
|
struct kvmppc_xive_src_block *sb,
|
|
|
|
u32 irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_irq_state *state = &sb->irq_state[irq];
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Mask and save state, this will also sync HW queues */
|
|
|
|
state->saved_scan_prio = xive_lock_and_mask(xive, sb, state);
|
|
|
|
|
|
|
|
/* Transfer P and Q */
|
|
|
|
state->saved_p = state->old_p;
|
|
|
|
state->saved_q = state->old_q;
|
|
|
|
|
|
|
|
/* Unlock */
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_pre_save_unmask_irq(struct kvmppc_xive *xive,
|
|
|
|
struct kvmppc_xive_src_block *sb,
|
|
|
|
u32 irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_irq_state *state = &sb->irq_state[irq];
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock / exclude EOI (not technically necessary if the
|
|
|
|
* guest isn't running concurrently. If this becomes a
|
|
|
|
* performance issue we can probably remove the lock.
|
|
|
|
*/
|
|
|
|
xive_lock_for_unmask(sb, state);
|
|
|
|
|
|
|
|
/* Restore mask/prio if it wasn't masked */
|
|
|
|
if (state->saved_scan_prio != MASKED)
|
|
|
|
xive_finish_unmask(xive, sb, state, state->saved_scan_prio);
|
|
|
|
|
|
|
|
/* Unlock */
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_pre_save_queue(struct kvmppc_xive *xive, struct xive_q *q)
|
|
|
|
{
|
|
|
|
u32 idx = q->idx;
|
|
|
|
u32 toggle = q->toggle;
|
|
|
|
u32 irq;
|
|
|
|
|
|
|
|
do {
|
|
|
|
irq = __xive_read_eq(q->qpage, q->msk, &idx, &toggle);
|
|
|
|
if (irq > XICS_IPI)
|
|
|
|
xive_pre_save_set_queued(xive, irq);
|
|
|
|
} while(irq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_pre_save_scan(struct kvmppc_xive *xive)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu = NULL;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See comment in xive_get_source() about how this
|
|
|
|
* work. Collect a stable state for all interrupts
|
|
|
|
*/
|
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
|
|
|
|
if (!sb)
|
|
|
|
continue;
|
|
|
|
for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++)
|
|
|
|
xive_pre_save_mask_irq(xive, sb, j);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Then scan the queues and update the "in_queue" flag */
|
|
|
|
kvm_for_each_vcpu(i, vcpu, xive->kvm) {
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
if (!xc)
|
|
|
|
continue;
|
|
|
|
for (j = 0; j < KVMPPC_XIVE_Q_COUNT; j++) {
|
KVM: PPC: Book3S: Fix typo in XICS-on-XIVE state saving code
This fixes a typo where the wrong loop index was used to index
the kvmppc_xive_vcpu.queues[] array in xive_pre_save_scan().
The variable i contains the vcpu number; we need to index queues[]
using j, which iterates from 0 to KVMPPC_XIVE_Q_COUNT-1.
The effect of this bug is that things that save the interrupt
controller state, such as "virsh dump", on a VM with more than
8 vCPUs, result in xive_pre_save_queue() getting called on a
bogus queue structure, usually resulting in a crash like this:
[ 501.821107] Unable to handle kernel paging request for data at address 0x00000084
[ 501.821212] Faulting instruction address: 0xc008000004c7c6f8
[ 501.821234] Oops: Kernel access of bad area, sig: 11 [#1]
[ 501.821305] SMP NR_CPUS=1024
[ 501.821307] NUMA
[ 501.821376] PowerNV
[ 501.821470] Modules linked in: vhost_net vhost tap xt_CHECKSUM ipt_MASQUERADE nf_nat_masquerade_ipv4 ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_mangle ip6table_security ip6table_raw iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack libcrc32c iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables ses enclosure scsi_transport_sas ipmi_powernv ipmi_devintf ipmi_msghandler powernv_op_panel kvm_hv nfsd auth_rpcgss oid_registry nfs_acl lockd grace sunrpc kvm tg3 ptp pps_core
[ 501.822477] CPU: 3 PID: 3934 Comm: live_migration Not tainted 4.11.0-4.git8caa70f.el7.centos.ppc64le #1
[ 501.822633] task: c0000003f9e3ae80 task.stack: c0000003f9ed4000
[ 501.822745] NIP: c008000004c7c6f8 LR: c008000004c7c628 CTR: 0000000030058018
[ 501.822877] REGS: c0000003f9ed7980 TRAP: 0300 Not tainted (4.11.0-4.git8caa70f.el7.centos.ppc64le)
[ 501.823030] MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE>
[ 501.823047] CR: 28022244 XER: 00000000
[ 501.823203] CFAR: c008000004c7c77c DAR: 0000000000000084 DSISR: 40000000 SOFTE: 1
[ 501.823203] GPR00: c008000004c7c628 c0000003f9ed7c00 c008000004c91450 00000000000000ff
[ 501.823203] GPR04: c0000003f5580000 c0000003f559bf98 9000000000009033 0000000000000000
[ 501.823203] GPR08: 0000000000000084 0000000000000000 00000000000001e0 9000000000001003
[ 501.823203] GPR12: c00000000008a7d0 c00000000fdc1b00 000000000a9a0000 0000000000000000
[ 501.823203] GPR16: 00000000402954e8 000000000a9a0000 0000000000000004 0000000000000000
[ 501.823203] GPR20: 0000000000000008 c000000002e8f180 c000000002e8f1e0 0000000000000001
[ 501.823203] GPR24: 0000000000000008 c0000003f5580008 c0000003f4564018 c000000002e8f1e8
[ 501.823203] GPR28: 00003ff6e58bdc28 c0000003f4564000 0000000000000000 0000000000000000
[ 501.825441] NIP [c008000004c7c6f8] xive_get_attr+0x3b8/0x5b0 [kvm]
[ 501.825671] LR [c008000004c7c628] xive_get_attr+0x2e8/0x5b0 [kvm]
[ 501.825887] Call Trace:
[ 501.825991] [c0000003f9ed7c00] [c008000004c7c628] xive_get_attr+0x2e8/0x5b0 [kvm] (unreliable)
[ 501.826312] [c0000003f9ed7cd0] [c008000004c62ec4] kvm_device_ioctl_attr+0x64/0xa0 [kvm]
[ 501.826581] [c0000003f9ed7d20] [c008000004c62fcc] kvm_device_ioctl+0xcc/0xf0 [kvm]
[ 501.826843] [c0000003f9ed7d40] [c000000000350c70] do_vfs_ioctl+0xd0/0x8c0
[ 501.827060] [c0000003f9ed7de0] [c000000000351534] SyS_ioctl+0xd4/0xf0
[ 501.827282] [c0000003f9ed7e30] [c00000000000b8e0] system_call+0x38/0xfc
[ 501.827496] Instruction dump:
[ 501.827632] 419e0078 3b760008 e9160008 83fb000c 83db0010 80fb0008 2f280000 60000000
[ 501.827901] 60000000 60420000 419a0050 7be91764 <7d284c2c> 552a0ffe 7f8af040 419e003c
[ 501.828176] ---[ end trace 2d0529a5bbbbafed ]---
Cc: stable@vger.kernel.org
Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE interrupt controller")
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2017-06-30 13:39:55 +07:00
|
|
|
if (xc->queues[j].qpage)
|
|
|
|
xive_pre_save_queue(xive, &xc->queues[j]);
|
2017-04-05 14:54:56 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally restore interrupt states */
|
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
|
|
|
|
if (!sb)
|
|
|
|
continue;
|
|
|
|
for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++)
|
|
|
|
xive_pre_save_unmask_irq(xive, sb, j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xive_post_save_scan(struct kvmppc_xive *xive)
|
|
|
|
{
|
|
|
|
u32 i, j;
|
|
|
|
|
|
|
|
/* Clear all the in_queue flags */
|
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
|
|
|
|
if (!sb)
|
|
|
|
continue;
|
|
|
|
for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++)
|
|
|
|
sb->irq_state[j].in_queue = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Next get_source() will do a new scan */
|
|
|
|
xive->saved_src_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This returns the source configuration and state to user space.
|
|
|
|
*/
|
|
|
|
static int xive_get_source(struct kvmppc_xive *xive, long irq, u64 addr)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u64 __user *ubufp = (u64 __user *) addr;
|
|
|
|
u64 val, prio;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
pr_devel("get_source(%ld)...\n", irq);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* So to properly save the state into something that looks like a
|
|
|
|
* XICS migration stream we cannot treat interrupts individually.
|
|
|
|
*
|
|
|
|
* We need, instead, mask them all (& save their previous PQ state)
|
|
|
|
* to get a stable state in the HW, then sync them to ensure that
|
|
|
|
* any interrupt that had already fired hits its queue, and finally
|
|
|
|
* scan all the queues to collect which interrupts are still present
|
|
|
|
* in the queues, so we can set the "pending" flag on them and
|
|
|
|
* they can be resent on restore.
|
|
|
|
*
|
|
|
|
* So we do it all when the "first" interrupt gets saved, all the
|
|
|
|
* state is collected at that point, the rest of xive_get_source()
|
|
|
|
* will merely collect and convert that state to the expected
|
|
|
|
* userspace bit mask.
|
|
|
|
*/
|
|
|
|
if (xive->saved_src_count == 0)
|
|
|
|
xive_pre_save_scan(xive);
|
|
|
|
xive->saved_src_count++;
|
|
|
|
|
|
|
|
/* Convert saved state into something compatible with xics */
|
2017-09-26 13:47:04 +07:00
|
|
|
val = state->act_server;
|
2017-04-05 14:54:56 +07:00
|
|
|
prio = state->saved_scan_prio;
|
|
|
|
|
|
|
|
if (prio == MASKED) {
|
|
|
|
val |= KVM_XICS_MASKED;
|
|
|
|
prio = state->saved_priority;
|
|
|
|
}
|
|
|
|
val |= prio << KVM_XICS_PRIORITY_SHIFT;
|
|
|
|
if (state->lsi) {
|
|
|
|
val |= KVM_XICS_LEVEL_SENSITIVE;
|
|
|
|
if (state->saved_p)
|
|
|
|
val |= KVM_XICS_PENDING;
|
|
|
|
} else {
|
|
|
|
if (state->saved_p)
|
|
|
|
val |= KVM_XICS_PRESENTED;
|
|
|
|
|
|
|
|
if (state->saved_q)
|
|
|
|
val |= KVM_XICS_QUEUED;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We mark it pending (which will attempt a re-delivery)
|
|
|
|
* if we are in a queue *or* we were masked and had
|
|
|
|
* Q set which is equivalent to the XICS "masked pending"
|
|
|
|
* state
|
|
|
|
*/
|
|
|
|
if (state->in_queue || (prio == MASKED && state->saved_q))
|
|
|
|
val |= KVM_XICS_PENDING;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If that was the last interrupt saved, reset the
|
|
|
|
* in_queue flags
|
|
|
|
*/
|
|
|
|
if (xive->saved_src_count == xive->src_count)
|
|
|
|
xive_post_save_scan(xive);
|
|
|
|
|
|
|
|
/* Copy the result to userspace */
|
|
|
|
if (put_user(val, ubufp))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:29 +07:00
|
|
|
struct kvmppc_xive_src_block *kvmppc_xive_create_src_block(
|
|
|
|
struct kvmppc_xive *xive, int irq)
|
2017-04-05 14:54:56 +07:00
|
|
|
{
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
int i, bid;
|
|
|
|
|
|
|
|
bid = irq >> KVMPPC_XICS_ICS_SHIFT;
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_lock(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
/* block already exists - somebody else got here first */
|
|
|
|
if (xive->src_blocks[bid])
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Create the ICS */
|
|
|
|
sb = kzalloc(sizeof(*sb), GFP_KERNEL);
|
|
|
|
if (!sb)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
sb->id = bid;
|
|
|
|
|
|
|
|
for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
|
|
|
|
sb->irq_state[i].number = (bid << KVMPPC_XICS_ICS_SHIFT) | i;
|
2019-04-18 17:39:30 +07:00
|
|
|
sb->irq_state[i].eisn = 0;
|
2017-04-05 14:54:56 +07:00
|
|
|
sb->irq_state[i].guest_priority = MASKED;
|
|
|
|
sb->irq_state[i].saved_priority = MASKED;
|
|
|
|
sb->irq_state[i].act_priority = MASKED;
|
|
|
|
}
|
|
|
|
smp_wmb();
|
|
|
|
xive->src_blocks[bid] = sb;
|
|
|
|
|
|
|
|
if (bid > xive->max_sbid)
|
|
|
|
xive->max_sbid = bid;
|
|
|
|
|
|
|
|
out:
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
return xive->src_blocks[bid];
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool xive_check_delayed_irq(struct kvmppc_xive *xive, u32 irq)
|
|
|
|
{
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
struct kvm_vcpu *vcpu = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (xc->delayed_irq == irq) {
|
|
|
|
xc->delayed_irq = 0;
|
|
|
|
xive->delayed_irqs--;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u64 __user *ubufp = (u64 __user *) addr;
|
|
|
|
u16 idx;
|
|
|
|
u64 val;
|
|
|
|
u8 act_prio, guest_prio;
|
|
|
|
u32 server;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (irq < KVMPPC_XICS_FIRST_IRQ || irq >= KVMPPC_XICS_NR_IRQS)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
pr_devel("set_source(irq=0x%lx)\n", irq);
|
|
|
|
|
|
|
|
/* Find the source */
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb) {
|
|
|
|
pr_devel("No source, creating source block...\n");
|
2019-04-18 17:39:29 +07:00
|
|
|
sb = kvmppc_xive_create_src_block(xive, irq);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (!sb) {
|
|
|
|
pr_devel("Failed to create block...\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
/* Read user passed data */
|
|
|
|
if (get_user(val, ubufp)) {
|
|
|
|
pr_devel("fault getting user info !\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
server = val & KVM_XICS_DESTINATION_MASK;
|
|
|
|
guest_prio = val >> KVM_XICS_PRIORITY_SHIFT;
|
|
|
|
|
|
|
|
pr_devel(" val=0x016%llx (server=0x%x, guest_prio=%d)\n",
|
|
|
|
val, server, guest_prio);
|
2018-01-12 09:37:12 +07:00
|
|
|
|
2017-04-05 14:54:56 +07:00
|
|
|
/*
|
|
|
|
* If the source doesn't already have an IPI, allocate
|
|
|
|
* one and get the corresponding data
|
|
|
|
*/
|
|
|
|
if (!state->ipi_number) {
|
|
|
|
state->ipi_number = xive_native_alloc_irq();
|
|
|
|
if (state->ipi_number == 0) {
|
|
|
|
pr_devel("Failed to allocate IPI !\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
xive_native_populate_irq_data(state->ipi_number, &state->ipi_data);
|
|
|
|
pr_devel(" src_ipi=0x%x\n", state->ipi_number);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We use lock_and_mask() to set us in the right masked
|
|
|
|
* state. We will override that state from the saved state
|
|
|
|
* further down, but this will handle the cases of interrupts
|
|
|
|
* that need FW masking. We set the initial guest_priority to
|
|
|
|
* 0 before calling it to ensure it actually performs the masking.
|
|
|
|
*/
|
|
|
|
state->guest_priority = 0;
|
|
|
|
xive_lock_and_mask(xive, sb, state);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, we select a target if we have one. If we don't we
|
|
|
|
* leave the interrupt untargetted. It means that an interrupt
|
|
|
|
* can become "untargetted" accross migration if it was masked
|
|
|
|
* by set_xive() but there is little we can do about it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* First convert prio and mark interrupt as untargetted */
|
|
|
|
act_prio = xive_prio_from_guest(guest_prio);
|
|
|
|
state->act_priority = MASKED;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to drop the lock due to the mutex below. Hopefully
|
|
|
|
* nothing is touching that interrupt yet since it hasn't been
|
|
|
|
* advertized to a running guest yet
|
|
|
|
*/
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
/* If we have a priority target the interrupt */
|
|
|
|
if (act_prio != MASKED) {
|
|
|
|
/* First, check provisioning of queues */
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_lock(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
rc = xive_check_provisioning(xive->kvm, act_prio);
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
/* Target interrupt */
|
|
|
|
if (rc == 0)
|
|
|
|
rc = xive_target_interrupt(xive->kvm, state,
|
|
|
|
server, act_prio);
|
|
|
|
/*
|
|
|
|
* If provisioning or targetting failed, leave it
|
|
|
|
* alone and masked. It will remain disabled until
|
|
|
|
* the guest re-targets it.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find out if this was a delayed irq stashed in an ICP,
|
|
|
|
* in which case, treat it as pending
|
|
|
|
*/
|
|
|
|
if (xive->delayed_irqs && xive_check_delayed_irq(xive, irq)) {
|
|
|
|
val |= KVM_XICS_PENDING;
|
|
|
|
pr_devel(" Found delayed ! forcing PENDING !\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup the SW state */
|
|
|
|
state->old_p = false;
|
|
|
|
state->old_q = false;
|
|
|
|
state->lsi = false;
|
|
|
|
state->asserted = false;
|
|
|
|
|
|
|
|
/* Restore LSI state */
|
|
|
|
if (val & KVM_XICS_LEVEL_SENSITIVE) {
|
|
|
|
state->lsi = true;
|
|
|
|
if (val & KVM_XICS_PENDING)
|
|
|
|
state->asserted = true;
|
|
|
|
pr_devel(" LSI ! Asserted=%d\n", state->asserted);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore P and Q. If the interrupt was pending, we
|
2017-12-12 19:02:04 +07:00
|
|
|
* force Q and !P, which will trigger a resend.
|
2017-04-05 14:54:56 +07:00
|
|
|
*
|
|
|
|
* That means that a guest that had both an interrupt
|
|
|
|
* pending (queued) and Q set will restore with only
|
|
|
|
* one instance of that interrupt instead of 2, but that
|
|
|
|
* is perfectly fine as coalescing interrupts that haven't
|
|
|
|
* been presented yet is always allowed.
|
|
|
|
*/
|
2017-12-12 19:02:04 +07:00
|
|
|
if (val & KVM_XICS_PRESENTED && !(val & KVM_XICS_PENDING))
|
2017-04-05 14:54:56 +07:00
|
|
|
state->old_p = true;
|
|
|
|
if (val & KVM_XICS_QUEUED || val & KVM_XICS_PENDING)
|
|
|
|
state->old_q = true;
|
|
|
|
|
|
|
|
pr_devel(" P=%d, Q=%d\n", state->old_p, state->old_q);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the interrupt was unmasked, update guest priority and
|
|
|
|
* perform the appropriate state transition and do a
|
|
|
|
* re-trigger if necessary.
|
|
|
|
*/
|
|
|
|
if (val & KVM_XICS_MASKED) {
|
|
|
|
pr_devel(" masked, saving prio\n");
|
|
|
|
state->guest_priority = MASKED;
|
|
|
|
state->saved_priority = guest_prio;
|
|
|
|
} else {
|
|
|
|
pr_devel(" unmasked, restoring to prio %d\n", guest_prio);
|
|
|
|
xive_finish_unmask(xive, sb, state, guest_prio);
|
|
|
|
state->saved_priority = guest_prio;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Increment the number of valid sources and mark this one valid */
|
|
|
|
if (!state->valid)
|
|
|
|
xive->src_count++;
|
|
|
|
state->valid = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
|
|
|
bool line_status)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
u16 idx;
|
|
|
|
|
|
|
|
if (!xive)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Perform locklessly .... (we need to do some RCUisms here...) */
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
if (!state->valid)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* We don't allow a trigger on a passed-through interrupt */
|
|
|
|
if (state->pt_number)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL)
|
|
|
|
state->asserted = 1;
|
|
|
|
else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
|
|
|
|
state->asserted = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Trigger the IPI */
|
|
|
|
xive_irq_trigger(&state->ipi_data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
|
|
|
|
/* We honor the existing XICS ioctl */
|
|
|
|
switch (attr->group) {
|
|
|
|
case KVM_DEV_XICS_GRP_SOURCES:
|
|
|
|
return xive_set_source(xive, attr->attr, attr->addr);
|
|
|
|
}
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
|
|
|
|
/* We honor the existing XICS ioctl */
|
|
|
|
switch (attr->group) {
|
|
|
|
case KVM_DEV_XICS_GRP_SOURCES:
|
|
|
|
return xive_get_source(xive, attr->attr, attr->addr);
|
|
|
|
}
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
/* We honor the same limits as XICS, at least for now */
|
|
|
|
switch (attr->group) {
|
|
|
|
case KVM_DEV_XICS_GRP_SOURCES:
|
|
|
|
if (attr->attr >= KVMPPC_XICS_FIRST_IRQ &&
|
|
|
|
attr->attr < KVMPPC_XICS_NR_IRQS)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kvmppc_xive_cleanup_irq(u32 hw_num, struct xive_irq_data *xd)
|
|
|
|
{
|
|
|
|
xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01);
|
|
|
|
xive_native_configure_irq(hw_num, 0, MASKED, 0);
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:29 +07:00
|
|
|
void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb)
|
2017-04-05 14:54:56 +07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
|
|
|
|
struct kvmppc_xive_irq_state *state = &sb->irq_state[i];
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
kvmppc_xive_cleanup_irq(state->ipi_number, &state->ipi_data);
|
KVM: PPC: Book3S HV: XIVE: Do not clear IRQ data of passthrough interrupts
The passthrough interrupts are defined at the host level and their IRQ
data should not be cleared unless specifically deconfigured (shutdown)
by the host. They differ from the IPI interrupts which are allocated
by the XIVE KVM device and reserved to the guest usage only.
This fixes a host crash when destroying a VM in which a PCI adapter
was passed-through. In this case, the interrupt is cleared and freed
by the KVM device and then shutdown by vfio at the host level.
[ 1007.360265] BUG: Kernel NULL pointer dereference at 0x00000d00
[ 1007.360285] Faulting instruction address: 0xc00000000009da34
[ 1007.360296] Oops: Kernel access of bad area, sig: 7 [#1]
[ 1007.360303] LE PAGE_SIZE=64K MMU=Radix MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
[ 1007.360314] Modules linked in: vhost_net vhost iptable_mangle ipt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc kvm_hv kvm xt_tcpudp iptable_filter squashfs fuse binfmt_misc vmx_crypto ib_iser rdma_cm iw_cm ib_cm libiscsi scsi_transport_iscsi nfsd ip_tables x_tables autofs4 btrfs zstd_decompress zstd_compress lzo_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq multipath mlx5_ib ib_uverbs ib_core crc32c_vpmsum mlx5_core
[ 1007.360425] CPU: 9 PID: 15576 Comm: CPU 18/KVM Kdump: loaded Not tainted 5.1.0-gad7e7d0ef #4
[ 1007.360454] NIP: c00000000009da34 LR: c00000000009e50c CTR: c00000000009e5d0
[ 1007.360482] REGS: c000007f24ccf330 TRAP: 0300 Not tainted (5.1.0-gad7e7d0ef)
[ 1007.360500] MSR: 900000000280b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 24002484 XER: 00000000
[ 1007.360532] CFAR: c00000000009da10 DAR: 0000000000000d00 DSISR: 00080000 IRQMASK: 1
[ 1007.360532] GPR00: c00000000009e62c c000007f24ccf5c0 c000000001510600 c000007fe7f947c0
[ 1007.360532] GPR04: 0000000000000d00 0000000000000000 0000000000000000 c000005eff02d200
[ 1007.360532] GPR08: 0000000000400000 0000000000000000 0000000000000000 fffffffffffffffd
[ 1007.360532] GPR12: c00000000009e5d0 c000007fffff7b00 0000000000000031 000000012c345718
[ 1007.360532] GPR16: 0000000000000000 0000000000000008 0000000000418004 0000000000040100
[ 1007.360532] GPR20: 0000000000000000 0000000008430000 00000000003c0000 0000000000000027
[ 1007.360532] GPR24: 00000000000000ff 0000000000000000 00000000000000ff c000007faa90d98c
[ 1007.360532] GPR28: c000007faa90da40 00000000000fe040 ffffffffffffffff c000007fe7f947c0
[ 1007.360689] NIP [c00000000009da34] xive_esb_read+0x34/0x120
[ 1007.360706] LR [c00000000009e50c] xive_do_source_set_mask.part.0+0x2c/0x50
[ 1007.360732] Call Trace:
[ 1007.360738] [c000007f24ccf5c0] [c000000000a6383c] snooze_loop+0x15c/0x270 (unreliable)
[ 1007.360775] [c000007f24ccf5f0] [c00000000009e62c] xive_irq_shutdown+0x5c/0xe0
[ 1007.360795] [c000007f24ccf630] [c00000000019e4a0] irq_shutdown+0x60/0xe0
[ 1007.360813] [c000007f24ccf660] [c000000000198c44] __free_irq+0x3a4/0x420
[ 1007.360831] [c000007f24ccf700] [c000000000198dc8] free_irq+0x78/0xe0
[ 1007.360849] [c000007f24ccf730] [c00000000096c5a8] vfio_msi_set_vector_signal+0xa8/0x350
[ 1007.360878] [c000007f24ccf7f0] [c00000000096c938] vfio_msi_set_block+0xe8/0x1e0
[ 1007.360899] [c000007f24ccf850] [c00000000096cae0] vfio_msi_disable+0xb0/0x110
[ 1007.360912] [c000007f24ccf8a0] [c00000000096cd04] vfio_pci_set_msi_trigger+0x1c4/0x3d0
[ 1007.360922] [c000007f24ccf910] [c00000000096d910] vfio_pci_set_irqs_ioctl+0xa0/0x170
[ 1007.360941] [c000007f24ccf930] [c00000000096b400] vfio_pci_disable+0x80/0x5e0
[ 1007.360963] [c000007f24ccfa10] [c00000000096b9bc] vfio_pci_release+0x5c/0x90
[ 1007.360991] [c000007f24ccfa40] [c000000000963a9c] vfio_device_fops_release+0x3c/0x70
[ 1007.361012] [c000007f24ccfa70] [c0000000003b5668] __fput+0xc8/0x2b0
[ 1007.361040] [c000007f24ccfac0] [c0000000001409b0] task_work_run+0x140/0x1b0
[ 1007.361059] [c000007f24ccfb20] [c000000000118f8c] do_exit+0x3ac/0xd00
[ 1007.361076] [c000007f24ccfc00] [c0000000001199b0] do_group_exit+0x60/0x100
[ 1007.361094] [c000007f24ccfc40] [c00000000012b514] get_signal+0x1a4/0x8f0
[ 1007.361112] [c000007f24ccfd30] [c000000000021cc8] do_notify_resume+0x1a8/0x430
[ 1007.361141] [c000007f24ccfe20] [c00000000000e444] ret_from_except_lite+0x70/0x74
[ 1007.361159] Instruction dump:
[ 1007.361175] 38422c00 e9230000 712a0004 41820010 548a2036 7d442378 78840020 71290020
[ 1007.361194] 4082004c e9230010 7c892214 7c0004ac <e9240000> 0c090000 4c00012c 792a0022
Cc: stable@vger.kernel.org # v4.12+
Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE interrupt controller")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-05-28 19:17:15 +07:00
|
|
|
xive_cleanup_irq_data(&state->ipi_data);
|
2017-04-05 14:54:56 +07:00
|
|
|
xive_native_free_irq(state->ipi_number);
|
|
|
|
|
KVM: PPC: Book3S HV: XIVE: Do not clear IRQ data of passthrough interrupts
The passthrough interrupts are defined at the host level and their IRQ
data should not be cleared unless specifically deconfigured (shutdown)
by the host. They differ from the IPI interrupts which are allocated
by the XIVE KVM device and reserved to the guest usage only.
This fixes a host crash when destroying a VM in which a PCI adapter
was passed-through. In this case, the interrupt is cleared and freed
by the KVM device and then shutdown by vfio at the host level.
[ 1007.360265] BUG: Kernel NULL pointer dereference at 0x00000d00
[ 1007.360285] Faulting instruction address: 0xc00000000009da34
[ 1007.360296] Oops: Kernel access of bad area, sig: 7 [#1]
[ 1007.360303] LE PAGE_SIZE=64K MMU=Radix MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
[ 1007.360314] Modules linked in: vhost_net vhost iptable_mangle ipt_MASQUERADE iptable_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 tun bridge stp llc kvm_hv kvm xt_tcpudp iptable_filter squashfs fuse binfmt_misc vmx_crypto ib_iser rdma_cm iw_cm ib_cm libiscsi scsi_transport_iscsi nfsd ip_tables x_tables autofs4 btrfs zstd_decompress zstd_compress lzo_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq multipath mlx5_ib ib_uverbs ib_core crc32c_vpmsum mlx5_core
[ 1007.360425] CPU: 9 PID: 15576 Comm: CPU 18/KVM Kdump: loaded Not tainted 5.1.0-gad7e7d0ef #4
[ 1007.360454] NIP: c00000000009da34 LR: c00000000009e50c CTR: c00000000009e5d0
[ 1007.360482] REGS: c000007f24ccf330 TRAP: 0300 Not tainted (5.1.0-gad7e7d0ef)
[ 1007.360500] MSR: 900000000280b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 24002484 XER: 00000000
[ 1007.360532] CFAR: c00000000009da10 DAR: 0000000000000d00 DSISR: 00080000 IRQMASK: 1
[ 1007.360532] GPR00: c00000000009e62c c000007f24ccf5c0 c000000001510600 c000007fe7f947c0
[ 1007.360532] GPR04: 0000000000000d00 0000000000000000 0000000000000000 c000005eff02d200
[ 1007.360532] GPR08: 0000000000400000 0000000000000000 0000000000000000 fffffffffffffffd
[ 1007.360532] GPR12: c00000000009e5d0 c000007fffff7b00 0000000000000031 000000012c345718
[ 1007.360532] GPR16: 0000000000000000 0000000000000008 0000000000418004 0000000000040100
[ 1007.360532] GPR20: 0000000000000000 0000000008430000 00000000003c0000 0000000000000027
[ 1007.360532] GPR24: 00000000000000ff 0000000000000000 00000000000000ff c000007faa90d98c
[ 1007.360532] GPR28: c000007faa90da40 00000000000fe040 ffffffffffffffff c000007fe7f947c0
[ 1007.360689] NIP [c00000000009da34] xive_esb_read+0x34/0x120
[ 1007.360706] LR [c00000000009e50c] xive_do_source_set_mask.part.0+0x2c/0x50
[ 1007.360732] Call Trace:
[ 1007.360738] [c000007f24ccf5c0] [c000000000a6383c] snooze_loop+0x15c/0x270 (unreliable)
[ 1007.360775] [c000007f24ccf5f0] [c00000000009e62c] xive_irq_shutdown+0x5c/0xe0
[ 1007.360795] [c000007f24ccf630] [c00000000019e4a0] irq_shutdown+0x60/0xe0
[ 1007.360813] [c000007f24ccf660] [c000000000198c44] __free_irq+0x3a4/0x420
[ 1007.360831] [c000007f24ccf700] [c000000000198dc8] free_irq+0x78/0xe0
[ 1007.360849] [c000007f24ccf730] [c00000000096c5a8] vfio_msi_set_vector_signal+0xa8/0x350
[ 1007.360878] [c000007f24ccf7f0] [c00000000096c938] vfio_msi_set_block+0xe8/0x1e0
[ 1007.360899] [c000007f24ccf850] [c00000000096cae0] vfio_msi_disable+0xb0/0x110
[ 1007.360912] [c000007f24ccf8a0] [c00000000096cd04] vfio_pci_set_msi_trigger+0x1c4/0x3d0
[ 1007.360922] [c000007f24ccf910] [c00000000096d910] vfio_pci_set_irqs_ioctl+0xa0/0x170
[ 1007.360941] [c000007f24ccf930] [c00000000096b400] vfio_pci_disable+0x80/0x5e0
[ 1007.360963] [c000007f24ccfa10] [c00000000096b9bc] vfio_pci_release+0x5c/0x90
[ 1007.360991] [c000007f24ccfa40] [c000000000963a9c] vfio_device_fops_release+0x3c/0x70
[ 1007.361012] [c000007f24ccfa70] [c0000000003b5668] __fput+0xc8/0x2b0
[ 1007.361040] [c000007f24ccfac0] [c0000000001409b0] task_work_run+0x140/0x1b0
[ 1007.361059] [c000007f24ccfb20] [c000000000118f8c] do_exit+0x3ac/0xd00
[ 1007.361076] [c000007f24ccfc00] [c0000000001199b0] do_group_exit+0x60/0x100
[ 1007.361094] [c000007f24ccfc40] [c00000000012b514] get_signal+0x1a4/0x8f0
[ 1007.361112] [c000007f24ccfd30] [c000000000021cc8] do_notify_resume+0x1a8/0x430
[ 1007.361141] [c000007f24ccfe20] [c00000000000e444] ret_from_except_lite+0x70/0x74
[ 1007.361159] Instruction dump:
[ 1007.361175] 38422c00 e9230000 712a0004 41820010 548a2036 7d442378 78840020 71290020
[ 1007.361194] 4082004c e9230010 7c892214 7c0004ac <e9240000> 0c090000 4c00012c 792a0022
Cc: stable@vger.kernel.org # v4.12+
Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE interrupt controller")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-05-28 19:17:15 +07:00
|
|
|
/* Pass-through, cleanup too but keep IRQ hw data */
|
2017-04-05 14:54:56 +07:00
|
|
|
if (state->pt_number)
|
|
|
|
kvmppc_xive_cleanup_irq(state->pt_number, state->pt_data);
|
|
|
|
|
|
|
|
state->valid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
/*
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
* Called when device fd is closed. kvm->lock is held.
|
2019-04-18 17:39:42 +07:00
|
|
|
*/
|
|
|
|
static void kvmppc_xive_release(struct kvm_device *dev)
|
2017-04-05 14:54:56 +07:00
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
struct kvm *kvm = xive->kvm;
|
2019-04-18 17:39:42 +07:00
|
|
|
struct kvm_vcpu *vcpu;
|
2017-04-05 14:54:56 +07:00
|
|
|
int i;
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
pr_devel("Releasing xive device\n");
|
|
|
|
|
|
|
|
/*
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
* Since this is the device release function, we know that
|
|
|
|
* userspace does not have any open fd referring to the
|
|
|
|
* device. Therefore there can not be any of the device
|
|
|
|
* attribute set/get functions being executed concurrently,
|
|
|
|
* and similarly, the connect_vcpu and set/clr_mapped
|
|
|
|
* functions also cannot be being executed.
|
2019-04-18 17:39:42 +07:00
|
|
|
*/
|
KVM: PPC: Book3S HV: Avoid touching arch.mmu_ready in XIVE release functions
Currently, kvmppc_xive_release() and kvmppc_xive_native_release() clear
kvm->arch.mmu_ready and call kick_all_cpus_sync() as a way of ensuring
that no vcpus are executing in the guest. However, future patches will
change the mutex associated with kvm->arch.mmu_ready to a new mutex that
nests inside the vcpu mutexes, making it difficult to continue to use
this method.
In fact, taking the vcpu mutex for a vcpu excludes execution of that
vcpu, and we already take the vcpu mutex around the call to
kvmppc_xive_[native_]cleanup_vcpu(). Once the cleanup function is
done and we release the vcpu mutex, the vcpu can execute once again,
but because we have cleared vcpu->arch.xive_vcpu, vcpu->arch.irq_type,
vcpu->arch.xive_esc_vaddr and vcpu->arch.xive_esc_raddr, that vcpu will
not be going into XIVE code any more. Thus, once we have cleaned up
all of the vcpus, we are safe to clean up the rest of the XIVE state,
and we don't need to use kvm->arch.mmu_ready to hold off vcpu execution.
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-05-23 13:35:07 +07:00
|
|
|
|
|
|
|
debugfs_remove(xive->dentry);
|
2019-04-18 17:39:42 +07:00
|
|
|
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
/*
|
|
|
|
* We should clean up the vCPU interrupt presenters first.
|
|
|
|
*/
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
/*
|
|
|
|
* Take vcpu->mutex to ensure that no one_reg get/set ioctl
|
|
|
|
* (i.e. kvmppc_xive_[gs]et_icp) can be done concurrently.
|
KVM: PPC: Book3S HV: Avoid touching arch.mmu_ready in XIVE release functions
Currently, kvmppc_xive_release() and kvmppc_xive_native_release() clear
kvm->arch.mmu_ready and call kick_all_cpus_sync() as a way of ensuring
that no vcpus are executing in the guest. However, future patches will
change the mutex associated with kvm->arch.mmu_ready to a new mutex that
nests inside the vcpu mutexes, making it difficult to continue to use
this method.
In fact, taking the vcpu mutex for a vcpu excludes execution of that
vcpu, and we already take the vcpu mutex around the call to
kvmppc_xive_[native_]cleanup_vcpu(). Once the cleanup function is
done and we release the vcpu mutex, the vcpu can execute once again,
but because we have cleared vcpu->arch.xive_vcpu, vcpu->arch.irq_type,
vcpu->arch.xive_esc_vaddr and vcpu->arch.xive_esc_raddr, that vcpu will
not be going into XIVE code any more. Thus, once we have cleaned up
all of the vcpus, we are safe to clean up the rest of the XIVE state,
and we don't need to use kvm->arch.mmu_ready to hold off vcpu execution.
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-05-23 13:35:07 +07:00
|
|
|
* Holding the vcpu->mutex also means that the vcpu cannot
|
|
|
|
* be executing the KVM_RUN ioctl, and therefore it cannot
|
|
|
|
* be executing the XIVE push or pull code or accessing
|
|
|
|
* the XIVE MMIO regions.
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
*/
|
|
|
|
mutex_lock(&vcpu->mutex);
|
|
|
|
kvmppc_xive_cleanup_vcpu(vcpu);
|
|
|
|
mutex_unlock(&vcpu->mutex);
|
|
|
|
}
|
2017-04-05 14:54:56 +07:00
|
|
|
|
KVM: PPC: Book3S HV: Avoid touching arch.mmu_ready in XIVE release functions
Currently, kvmppc_xive_release() and kvmppc_xive_native_release() clear
kvm->arch.mmu_ready and call kick_all_cpus_sync() as a way of ensuring
that no vcpus are executing in the guest. However, future patches will
change the mutex associated with kvm->arch.mmu_ready to a new mutex that
nests inside the vcpu mutexes, making it difficult to continue to use
this method.
In fact, taking the vcpu mutex for a vcpu excludes execution of that
vcpu, and we already take the vcpu mutex around the call to
kvmppc_xive_[native_]cleanup_vcpu(). Once the cleanup function is
done and we release the vcpu mutex, the vcpu can execute once again,
but because we have cleared vcpu->arch.xive_vcpu, vcpu->arch.irq_type,
vcpu->arch.xive_esc_vaddr and vcpu->arch.xive_esc_raddr, that vcpu will
not be going into XIVE code any more. Thus, once we have cleaned up
all of the vcpus, we are safe to clean up the rest of the XIVE state,
and we don't need to use kvm->arch.mmu_ready to hold off vcpu execution.
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-05-23 13:35:07 +07:00
|
|
|
/*
|
|
|
|
* Now that we have cleared vcpu->arch.xive_vcpu, vcpu->arch.irq_type
|
|
|
|
* and vcpu->arch.xive_esc_[vr]addr on each vcpu, we are safe
|
|
|
|
* against xive code getting called during vcpu execution or
|
|
|
|
* set/get one_reg operations.
|
|
|
|
*/
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
kvm->arch.xive = NULL;
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
/* Mask and free interrupts */
|
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
if (xive->src_blocks[i])
|
|
|
|
kvmppc_xive_free_sources(xive->src_blocks[i]);
|
|
|
|
kfree(xive->src_blocks[i]);
|
|
|
|
xive->src_blocks[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xive->vp_base != XIVE_INVALID_VP)
|
|
|
|
xive_native_free_vp_block(xive->vp_base);
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
/*
|
|
|
|
* A reference of the kvmppc_xive pointer is now kept under
|
|
|
|
* the xive_devices struct of the machine for reuse. It is
|
|
|
|
* freed when the VM is destroyed for now until we fix all the
|
|
|
|
* execution paths.
|
|
|
|
*/
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
kfree(dev);
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
/*
|
|
|
|
* When the guest chooses the interrupt mode (XICS legacy or XIVE
|
|
|
|
* native), the VM will switch of KVM device. The previous device will
|
|
|
|
* be "released" before the new one is created.
|
|
|
|
*
|
|
|
|
* Until we are sure all execution paths are well protected, provide a
|
|
|
|
* fail safe (transitional) method for device destruction, in which
|
|
|
|
* the XIVE device pointer is recycled and not directly freed.
|
|
|
|
*/
|
|
|
|
struct kvmppc_xive *kvmppc_xive_get_device(struct kvm *kvm, u32 type)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive **kvm_xive_device = type == KVM_DEV_TYPE_XIVE ?
|
|
|
|
&kvm->arch.xive_devices.native :
|
|
|
|
&kvm->arch.xive_devices.xics_on_xive;
|
|
|
|
struct kvmppc_xive *xive = *kvm_xive_device;
|
|
|
|
|
|
|
|
if (!xive) {
|
|
|
|
xive = kzalloc(sizeof(*xive), GFP_KERNEL);
|
|
|
|
*kvm_xive_device = xive;
|
|
|
|
} else {
|
|
|
|
memset(xive, 0, sizeof(*xive));
|
|
|
|
}
|
|
|
|
|
|
|
|
return xive;
|
|
|
|
}
|
|
|
|
|
KVM: PPC: Book3S HV: XIVE: Prevent races when releasing device
Now that we have the possibility of a XIVE or XICS-on-XIVE device being
released while the VM is still running, we need to be careful about
races and potential use-after-free bugs. Although the kvmppc_xive
struct is not freed, but kept around for re-use, the kvmppc_xive_vcpu
structs are freed, and they are used extensively in both the XIVE native
and XICS-on-XIVE code.
There are various ways in which XIVE code gets invoked:
- VCPU entry and exit, which do push and pull operations on the XIVE hardware
- one_reg get and set functions (vcpu->mutex is held)
- XICS hypercalls (but only inside guest execution, not from
kvmppc_pseries_do_hcall)
- device creation calls (kvm->lock is held)
- device callbacks - get/set attribute, mmap, pagefault, release/destroy
- set_mapped/clr_mapped calls (kvm->lock is held)
- connect_vcpu calls
- debugfs file read callbacks
Inside a device release function, we know that userspace cannot have an
open file descriptor referring to the device, nor can it have any mmapped
regions from the device. Therefore the device callbacks are excluded,
as are the connect_vcpu calls (since they need a fd for the device).
Further, since the caller holds the kvm->lock mutex, no other device
creation calls or set/clr_mapped calls can be executing concurrently.
To exclude VCPU execution and XICS hypercalls, we temporarily set
kvm->arch.mmu_ready to 0. This forces any VCPU task that is trying to
enter the guest to take the kvm->lock mutex, which is held by the caller
of the release function. Then, sending an IPI to all other CPUs forces
any VCPU currently executing in the guest to exit.
Finally, we take the vcpu->mutex for each VCPU around the process of
cleaning up and freeing its XIVE data structures, in order to exclude
any one_reg get/set calls.
To exclude the debugfs read callbacks, we just need to ensure that
debugfs_remove is called before freeing any data structures. Once it
returns we know that no CPU can be executing the callbacks (for our
kvmppc_xive instance).
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2019-04-29 08:24:03 +07:00
|
|
|
/*
|
|
|
|
* Create a XICS device with XIVE backend. kvm->lock is held.
|
|
|
|
*/
|
2017-04-05 14:54:56 +07:00
|
|
|
static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive;
|
|
|
|
struct kvm *kvm = dev->kvm;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
pr_devel("Creating xive for partition\n");
|
|
|
|
|
2019-09-27 18:53:38 +07:00
|
|
|
/* Already there ? */
|
|
|
|
if (kvm->arch.xive)
|
|
|
|
return -EEXIST;
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
xive = kvmppc_xive_get_device(kvm, type);
|
2017-04-05 14:54:56 +07:00
|
|
|
if (!xive)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
dev->private = xive;
|
|
|
|
xive->dev = dev;
|
|
|
|
xive->kvm = kvm;
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_init(&xive->lock);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
/* We use the default queue size set by the host */
|
|
|
|
xive->q_order = xive_native_default_eq_shift();
|
|
|
|
if (xive->q_order < PAGE_SHIFT)
|
|
|
|
xive->q_page_order = 0;
|
|
|
|
else
|
|
|
|
xive->q_page_order = xive->q_order - PAGE_SHIFT;
|
|
|
|
|
|
|
|
/* Allocate a bunch of VPs */
|
|
|
|
xive->vp_base = xive_native_alloc_vp_block(KVM_MAX_VCPUS);
|
|
|
|
pr_devel("VP_Base=%x\n", xive->vp_base);
|
|
|
|
|
|
|
|
if (xive->vp_base == XIVE_INVALID_VP)
|
|
|
|
ret = -ENOMEM;
|
|
|
|
|
2018-01-12 09:37:12 +07:00
|
|
|
xive->single_escalation = xive_native_has_single_escalation();
|
|
|
|
|
2019-07-19 04:51:54 +07:00
|
|
|
if (ret)
|
2017-04-05 14:54:56 +07:00
|
|
|
return ret;
|
|
|
|
|
2019-09-27 18:53:38 +07:00
|
|
|
kvm->arch.xive = xive;
|
2017-04-05 14:54:56 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:28 +07:00
|
|
|
int kvmppc_xive_debug_show_queues(struct seq_file *m, struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
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_puts(m, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
static int xive_debug_show(struct seq_file *m, void *private)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = m->private;
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
u64 t_rm_h_xirr = 0;
|
|
|
|
u64 t_rm_h_ipoll = 0;
|
|
|
|
u64 t_rm_h_cppr = 0;
|
|
|
|
u64 t_rm_h_eoi = 0;
|
|
|
|
u64 t_rm_h_ipi = 0;
|
|
|
|
u64 t_vm_h_xirr = 0;
|
|
|
|
u64 t_vm_h_ipoll = 0;
|
|
|
|
u64 t_vm_h_cppr = 0;
|
|
|
|
u64 t_vm_h_eoi = 0;
|
|
|
|
u64 t_vm_h_ipi = 0;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (!kvm)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
seq_printf(m, "=========\nVCPU state\n=========\n");
|
|
|
|
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
seq_printf(m, "cpu server %#x CPPR:%#x HWCPPR:%#x"
|
|
|
|
" MFRR:%#x PEND:%#x h_xirr: R=%lld V=%lld\n",
|
|
|
|
xc->server_num, xc->cppr, xc->hw_cppr,
|
|
|
|
xc->mfrr, xc->pending,
|
|
|
|
xc->stat_rm_h_xirr, xc->stat_vm_h_xirr);
|
2018-01-12 09:37:11 +07:00
|
|
|
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_debug_show_queues(m, vcpu);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
t_rm_h_xirr += xc->stat_rm_h_xirr;
|
|
|
|
t_rm_h_ipoll += xc->stat_rm_h_ipoll;
|
|
|
|
t_rm_h_cppr += xc->stat_rm_h_cppr;
|
|
|
|
t_rm_h_eoi += xc->stat_rm_h_eoi;
|
|
|
|
t_rm_h_ipi += xc->stat_rm_h_ipi;
|
|
|
|
t_vm_h_xirr += xc->stat_vm_h_xirr;
|
|
|
|
t_vm_h_ipoll += xc->stat_vm_h_ipoll;
|
|
|
|
t_vm_h_cppr += xc->stat_vm_h_cppr;
|
|
|
|
t_vm_h_eoi += xc->stat_vm_h_eoi;
|
|
|
|
t_vm_h_ipi += xc->stat_vm_h_ipi;
|
|
|
|
}
|
|
|
|
|
|
|
|
seq_printf(m, "Hcalls totals\n");
|
|
|
|
seq_printf(m, " H_XIRR R=%10lld V=%10lld\n", t_rm_h_xirr, t_vm_h_xirr);
|
|
|
|
seq_printf(m, " H_IPOLL R=%10lld V=%10lld\n", t_rm_h_ipoll, t_vm_h_ipoll);
|
|
|
|
seq_printf(m, " H_CPPR R=%10lld V=%10lld\n", t_rm_h_cppr, t_vm_h_cppr);
|
|
|
|
seq_printf(m, " H_EOI R=%10lld V=%10lld\n", t_rm_h_eoi, t_vm_h_eoi);
|
|
|
|
seq_printf(m, " H_IPI R=%10lld V=%10lld\n", t_rm_h_ipi, t_vm_h_ipi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-05 21:47:17 +07:00
|
|
|
DEFINE_SHOW_ATTRIBUTE(xive_debug);
|
2017-04-05 14:54:56 +07:00
|
|
|
|
|
|
|
static void xive_debugfs_init(struct kvmppc_xive *xive)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
name = kasprintf(GFP_KERNEL, "kvm-xive-%p", xive);
|
|
|
|
if (!name) {
|
|
|
|
pr_err("%s: no memory for name\n", __func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xive->dentry = debugfs_create_file(name, S_IRUGO, powerpc_debugfs_root,
|
|
|
|
xive, &xive_debug_fops);
|
|
|
|
|
|
|
|
pr_debug("%s: created %s\n", __func__, name);
|
|
|
|
kfree(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kvmppc_xive_init(struct kvm_device *dev)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private;
|
|
|
|
|
|
|
|
/* Register some debug interfaces */
|
|
|
|
xive_debugfs_init(xive);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct kvm_device_ops kvm_xive_ops = {
|
|
|
|
.name = "kvm-xive",
|
|
|
|
.create = kvmppc_xive_create,
|
|
|
|
.init = kvmppc_xive_init,
|
2019-04-18 17:39:42 +07:00
|
|
|
.release = kvmppc_xive_release,
|
2017-04-05 14:54:56 +07:00
|
|
|
.set_attr = xive_set_attr,
|
|
|
|
.get_attr = xive_get_attr,
|
|
|
|
.has_attr = xive_has_attr,
|
|
|
|
};
|
|
|
|
|
|
|
|
void kvmppc_xive_init_module(void)
|
|
|
|
{
|
|
|
|
__xive_vm_h_xirr = xive_vm_h_xirr;
|
|
|
|
__xive_vm_h_ipoll = xive_vm_h_ipoll;
|
|
|
|
__xive_vm_h_ipi = xive_vm_h_ipi;
|
|
|
|
__xive_vm_h_cppr = xive_vm_h_cppr;
|
|
|
|
__xive_vm_h_eoi = xive_vm_h_eoi;
|
|
|
|
}
|
|
|
|
|
|
|
|
void kvmppc_xive_exit_module(void)
|
|
|
|
{
|
|
|
|
__xive_vm_h_xirr = NULL;
|
|
|
|
__xive_vm_h_ipoll = NULL;
|
|
|
|
__xive_vm_h_ipi = NULL;
|
|
|
|
__xive_vm_h_cppr = NULL;
|
|
|
|
__xive_vm_h_eoi = NULL;
|
|
|
|
}
|