2019-04-18 17:39:27 +07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2017-2019, 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>
|
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
|
|
|
#include <linux/file.h>
|
2019-04-18 17:39:27 +07:00
|
|
|
#include <asm/uaccess.h>
|
|
|
|
#include <asm/kvm_book3s.h>
|
|
|
|
#include <asm/kvm_ppc.h>
|
|
|
|
#include <asm/hvcall.h>
|
|
|
|
#include <asm/xive.h>
|
|
|
|
#include <asm/xive-regs.h>
|
|
|
|
#include <asm/debug.h>
|
|
|
|
#include <asm/debugfs.h>
|
|
|
|
#include <asm/opal.h>
|
|
|
|
|
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
|
|
|
#include "book3s_xive.h"
|
|
|
|
|
2019-04-18 17:39:29 +07:00
|
|
|
static u8 xive_vm_esb_load(struct xive_irq_data *xd, u32 offset)
|
|
|
|
{
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG)
|
|
|
|
offset |= offset << 4;
|
|
|
|
|
|
|
|
val = in_be64(xd->eoi_mmio + offset);
|
|
|
|
return (u8)val;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:28 +07:00
|
|
|
static void kvmppc_xive_native_cleanup_queue(struct kvm_vcpu *vcpu, int prio)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct xive_q *q = &xc->queues[prio];
|
|
|
|
|
|
|
|
xive_native_disable_queue(xc->vp_id, q, prio);
|
|
|
|
if (q->qpage) {
|
|
|
|
put_page(virt_to_page(q->qpage));
|
|
|
|
q->qpage = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-13 23:46:13 +07:00
|
|
|
static int kvmppc_xive_native_configure_queue(u32 vp_id, struct xive_q *q,
|
|
|
|
u8 prio, __be32 *qpage,
|
|
|
|
u32 order, bool can_escalate)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
__be32 *qpage_prev = q->qpage;
|
|
|
|
|
|
|
|
rc = xive_native_configure_queue(vp_id, q, prio, qpage, order,
|
|
|
|
can_escalate);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
if (qpage_prev)
|
|
|
|
put_page(virt_to_page(qpage_prev));
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:28 +07:00
|
|
|
void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!kvmppc_xive_enabled(vcpu))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pr_devel("native_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);
|
|
|
|
|
2019-08-07 00:25:38 +07:00
|
|
|
/* Free escalations */
|
2019-04-18 17:39:28 +07:00
|
|
|
for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
|
|
|
|
/* Free the escalation irq */
|
|
|
|
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]);
|
2019-04-18 17:39:28 +07:00
|
|
|
free_irq(xc->esc_virq[i], vcpu);
|
|
|
|
irq_dispose_mapping(xc->esc_virq[i]);
|
|
|
|
kfree(xc->esc_virq_names[i]);
|
|
|
|
xc->esc_virq[i] = 0;
|
|
|
|
}
|
2019-08-07 00:25:38 +07:00
|
|
|
}
|
2019-04-18 17:39:28 +07:00
|
|
|
|
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++) {
|
2019-04-18 17:39:28 +07:00
|
|
|
kvmppc_xive_native_cleanup_queue(vcpu, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the VP */
|
|
|
|
kfree(xc);
|
|
|
|
|
|
|
|
/* Cleanup the vcpu */
|
|
|
|
vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
|
|
|
|
vcpu->arch.xive_vcpu = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
|
|
|
|
struct kvm_vcpu *vcpu, u32 server_num)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
struct kvmppc_xive_vcpu *xc = NULL;
|
|
|
|
int rc;
|
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;
|
2019-04-18 17:39:28 +07:00
|
|
|
|
|
|
|
pr_devel("native_connect_vcpu(server=%d)\n", server_num);
|
|
|
|
|
|
|
|
if (dev->ops != &kvm_xive_native_ops) {
|
|
|
|
pr_devel("Wrong ops !\n");
|
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
if (xive->kvm != vcpu->kvm)
|
|
|
|
return -EPERM;
|
|
|
|
if (vcpu->arch.irq_type != KVMPPC_IRQ_DEFAULT)
|
|
|
|
return -EBUSY;
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_lock(&xive->lock);
|
2019-04-18 17:39:28 +07:00
|
|
|
|
2019-09-27 18:53:55 +07:00
|
|
|
rc = kvmppc_xive_compute_vp_id(xive, server_num, &vp_id);
|
|
|
|
if (rc)
|
2019-04-18 17:39:28 +07:00
|
|
|
goto bail;
|
|
|
|
|
|
|
|
xc = kzalloc(sizeof(*xc), GFP_KERNEL);
|
|
|
|
if (!xc) {
|
|
|
|
rc = -ENOMEM;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcpu->arch.xive_vcpu = xc;
|
|
|
|
xc->xive = xive;
|
|
|
|
xc->vcpu = vcpu;
|
|
|
|
xc->server_num = server_num;
|
|
|
|
|
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;
|
2019-04-18 17:39:28 +07:00
|
|
|
xc->valid = true;
|
|
|
|
vcpu->arch.irq_type = KVMPPC_IRQ_XIVE;
|
|
|
|
|
|
|
|
rc = xive_native_get_vp_info(xc->vp_id, &xc->vp_cam, &xc->vp_chip_id);
|
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to get VP info from OPAL: %d\n", rc);
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable the VP first as the single escalation mode will
|
|
|
|
* affect escalation interrupts numbering
|
|
|
|
*/
|
|
|
|
rc = xive_native_enable_vp(xc->vp_id, xive->single_escalation);
|
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to enable VP in OPAL: %d\n", rc);
|
|
|
|
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);
|
|
|
|
|
|
|
|
/* TODO: reset all queues to a clean state ? */
|
|
|
|
bail:
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
2019-04-18 17:39:28 +07:00
|
|
|
if (rc)
|
|
|
|
kvmppc_xive_native_cleanup_vcpu(vcpu);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/*
|
|
|
|
* Device passthrough support
|
|
|
|
*/
|
|
|
|
static int kvmppc_xive_native_reset_mapped(struct kvm *kvm, unsigned long irq)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = kvm->arch.xive;
|
2019-05-29 04:13:24 +07:00
|
|
|
pgoff_t esb_pgoff = KVM_XIVE_ESB_PAGE_OFFSET + irq * 2;
|
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
|
|
|
|
|
|
|
if (irq >= KVMPPC_XIVE_NR_IRQS)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the ESB pages of the IRQ number being mapped (or
|
|
|
|
* unmapped) into the guest and let the the VM fault handler
|
|
|
|
* repopulate with the appropriate ESB pages (device or IC)
|
|
|
|
*/
|
|
|
|
pr_debug("clearing esb pages for girq 0x%lx\n", irq);
|
|
|
|
mutex_lock(&xive->mapping_lock);
|
|
|
|
if (xive->mapping)
|
|
|
|
unmap_mapping_range(xive->mapping,
|
2019-05-29 04:13:24 +07:00
|
|
|
esb_pgoff << PAGE_SHIFT,
|
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
|
|
|
2ull << PAGE_SHIFT, 1);
|
|
|
|
mutex_unlock(&xive->mapping_lock);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct kvmppc_xive_ops kvmppc_xive_native_ops = {
|
|
|
|
.reset_mapped = kvmppc_xive_native_reset_mapped,
|
|
|
|
};
|
|
|
|
|
2019-04-18 17:39:38 +07:00
|
|
|
static vm_fault_t xive_native_esb_fault(struct vm_fault *vmf)
|
|
|
|
{
|
|
|
|
struct vm_area_struct *vma = vmf->vma;
|
|
|
|
struct kvm_device *dev = vma->vm_file->private_data;
|
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
struct xive_irq_data *xd;
|
|
|
|
u32 hw_num;
|
|
|
|
u16 src;
|
|
|
|
u64 page;
|
|
|
|
unsigned long irq;
|
|
|
|
u64 page_offset;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Linux/KVM uses a two pages ESB setting, one for trigger and
|
|
|
|
* one for EOI
|
|
|
|
*/
|
|
|
|
page_offset = vmf->pgoff - vma->vm_pgoff;
|
|
|
|
irq = page_offset / 2;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &src);
|
|
|
|
if (!sb) {
|
|
|
|
pr_devel("%s: source %lx not found !\n", __func__, irq);
|
|
|
|
return VM_FAULT_SIGBUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = &sb->irq_state[src];
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, &xd);
|
|
|
|
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* first/even page is for trigger
|
|
|
|
* second/odd page is for EOI and management.
|
|
|
|
*/
|
|
|
|
page = page_offset % 2 ? xd->eoi_page : xd->trig_page;
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
if (WARN_ON(!page)) {
|
2019-05-02 17:23:13 +07:00
|
|
|
pr_err("%s: accessing invalid ESB page for source %lx !\n",
|
2019-04-18 17:39:38 +07:00
|
|
|
__func__, irq);
|
|
|
|
return VM_FAULT_SIGBUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
vmf_insert_pfn(vma, vmf->address, page >> PAGE_SHIFT);
|
|
|
|
return VM_FAULT_NOPAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct vm_operations_struct xive_native_esb_vmops = {
|
|
|
|
.fault = xive_native_esb_fault,
|
|
|
|
};
|
|
|
|
|
2019-04-18 17:39:37 +07:00
|
|
|
static vm_fault_t xive_native_tima_fault(struct vm_fault *vmf)
|
|
|
|
{
|
|
|
|
struct vm_area_struct *vma = vmf->vma;
|
|
|
|
|
|
|
|
switch (vmf->pgoff - vma->vm_pgoff) {
|
|
|
|
case 0: /* HW - forbid access */
|
|
|
|
case 1: /* HV - forbid access */
|
|
|
|
return VM_FAULT_SIGBUS;
|
|
|
|
case 2: /* OS */
|
|
|
|
vmf_insert_pfn(vma, vmf->address, xive_tima_os >> PAGE_SHIFT);
|
|
|
|
return VM_FAULT_NOPAGE;
|
|
|
|
case 3: /* USER - TODO */
|
|
|
|
default:
|
|
|
|
return VM_FAULT_SIGBUS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct vm_operations_struct xive_native_tima_vmops = {
|
|
|
|
.fault = xive_native_tima_fault,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_mmap(struct kvm_device *dev,
|
|
|
|
struct vm_area_struct *vma)
|
|
|
|
{
|
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
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
|
2019-04-18 17:39:37 +07:00
|
|
|
/* We only allow mappings at fixed offset for now */
|
|
|
|
if (vma->vm_pgoff == KVM_XIVE_TIMA_PAGE_OFFSET) {
|
|
|
|
if (vma_pages(vma) > 4)
|
|
|
|
return -EINVAL;
|
|
|
|
vma->vm_ops = &xive_native_tima_vmops;
|
2019-04-18 17:39:38 +07:00
|
|
|
} else if (vma->vm_pgoff == KVM_XIVE_ESB_PAGE_OFFSET) {
|
|
|
|
if (vma_pages(vma) > KVMPPC_XIVE_NR_IRQS * 2)
|
|
|
|
return -EINVAL;
|
|
|
|
vma->vm_ops = &xive_native_esb_vmops;
|
2019-04-18 17:39:37 +07:00
|
|
|
} else {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vma->vm_flags |= VM_IO | VM_PFNMAP;
|
|
|
|
vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot);
|
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
|
|
|
|
|
|
|
/*
|
|
|
|
* Grab the KVM device file address_space to be able to clear
|
|
|
|
* the ESB pages mapping when a device is passed-through into
|
|
|
|
* the guest.
|
|
|
|
*/
|
|
|
|
xive->mapping = vma->vm_file->f_mapping;
|
2019-04-18 17:39:37 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:29 +07:00
|
|
|
static int kvmppc_xive_native_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;
|
|
|
|
u64 val;
|
|
|
|
u16 idx;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
pr_devel("%s irq=0x%lx\n", __func__, irq);
|
|
|
|
|
|
|
|
if (irq < KVMPPC_XIVE_FIRST_IRQ || irq >= KVMPPC_XIVE_NR_IRQS)
|
|
|
|
return -E2BIG;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &idx);
|
|
|
|
if (!sb) {
|
|
|
|
pr_debug("No source, creating source block...\n");
|
|
|
|
sb = kvmppc_xive_create_src_block(xive, irq);
|
|
|
|
if (!sb) {
|
|
|
|
pr_err("Failed to create block...\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
state = &sb->irq_state[idx];
|
|
|
|
|
|
|
|
if (get_user(val, ubufp)) {
|
|
|
|
pr_err("fault getting user info !\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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_err("Failed to allocate IRQ !\n");
|
|
|
|
rc = -ENXIO;
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
xive_native_populate_irq_data(state->ipi_number,
|
|
|
|
&state->ipi_data);
|
|
|
|
pr_debug("%s allocated hw_irq=0x%x for irq=0x%lx\n", __func__,
|
|
|
|
state->ipi_number, irq);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Restore LSI state */
|
|
|
|
if (val & KVM_XIVE_LEVEL_SENSITIVE) {
|
|
|
|
state->lsi = true;
|
|
|
|
if (val & KVM_XIVE_LEVEL_ASSERTED)
|
|
|
|
state->asserted = true;
|
|
|
|
pr_devel(" LSI ! Asserted=%d\n", state->asserted);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Mask IRQ to start with */
|
|
|
|
state->act_server = 0;
|
|
|
|
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);
|
|
|
|
|
|
|
|
/* Increment the number of valid sources and mark this one valid */
|
|
|
|
if (!state->valid)
|
|
|
|
xive->src_count++;
|
|
|
|
state->valid = true;
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:30 +07:00
|
|
|
static int kvmppc_xive_native_update_source_config(struct kvmppc_xive *xive,
|
|
|
|
struct kvmppc_xive_src_block *sb,
|
|
|
|
struct kvmppc_xive_irq_state *state,
|
|
|
|
u32 server, u8 priority, bool masked,
|
|
|
|
u32 eisn)
|
|
|
|
{
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
u32 hw_num;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
|
|
|
|
if (state->act_server == server && state->act_priority == priority &&
|
|
|
|
state->eisn == eisn)
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
pr_devel("new_act_prio=%d new_act_server=%d mask=%d act_server=%d act_prio=%d\n",
|
|
|
|
priority, server, masked, state->act_server,
|
|
|
|
state->act_priority);
|
|
|
|
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, NULL);
|
|
|
|
|
|
|
|
if (priority != MASKED && !masked) {
|
|
|
|
rc = kvmppc_xive_select_target(kvm, &server, priority);
|
|
|
|
if (rc)
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
state->act_priority = priority;
|
|
|
|
state->act_server = server;
|
|
|
|
state->eisn = eisn;
|
|
|
|
|
|
|
|
rc = xive_native_configure_irq(hw_num,
|
|
|
|
kvmppc_xive_vp(xive, server),
|
|
|
|
priority, eisn);
|
|
|
|
} else {
|
|
|
|
state->act_priority = MASKED;
|
|
|
|
state->act_server = 0;
|
|
|
|
state->eisn = 0;
|
|
|
|
|
|
|
|
rc = xive_native_configure_irq(hw_num, 0, MASKED, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_set_source_config(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 src;
|
|
|
|
u64 kvm_cfg;
|
|
|
|
u32 server;
|
|
|
|
u8 priority;
|
|
|
|
bool masked;
|
|
|
|
u32 eisn;
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &src);
|
|
|
|
if (!sb)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
state = &sb->irq_state[src];
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (get_user(kvm_cfg, ubufp))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
pr_devel("%s irq=0x%lx cfg=%016llx\n", __func__, irq, kvm_cfg);
|
|
|
|
|
|
|
|
priority = (kvm_cfg & KVM_XIVE_SOURCE_PRIORITY_MASK) >>
|
|
|
|
KVM_XIVE_SOURCE_PRIORITY_SHIFT;
|
|
|
|
server = (kvm_cfg & KVM_XIVE_SOURCE_SERVER_MASK) >>
|
|
|
|
KVM_XIVE_SOURCE_SERVER_SHIFT;
|
|
|
|
masked = (kvm_cfg & KVM_XIVE_SOURCE_MASKED_MASK) >>
|
|
|
|
KVM_XIVE_SOURCE_MASKED_SHIFT;
|
|
|
|
eisn = (kvm_cfg & KVM_XIVE_SOURCE_EISN_MASK) >>
|
|
|
|
KVM_XIVE_SOURCE_EISN_SHIFT;
|
|
|
|
|
|
|
|
if (priority != xive_prio_from_guest(priority)) {
|
|
|
|
pr_err("invalid priority for queue %d for VCPU %d\n",
|
|
|
|
priority, server);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return kvmppc_xive_native_update_source_config(xive, sb, state, server,
|
|
|
|
priority, masked, eisn);
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:33 +07:00
|
|
|
static int kvmppc_xive_native_sync_source(struct kvmppc_xive *xive,
|
|
|
|
long irq, u64 addr)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_src_block *sb;
|
|
|
|
struct kvmppc_xive_irq_state *state;
|
|
|
|
struct xive_irq_data *xd;
|
|
|
|
u32 hw_num;
|
|
|
|
u16 src;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
pr_devel("%s irq=0x%lx", __func__, irq);
|
|
|
|
|
|
|
|
sb = kvmppc_xive_find_source(xive, irq, &src);
|
|
|
|
if (!sb)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
state = &sb->irq_state[src];
|
|
|
|
|
|
|
|
rc = -EINVAL;
|
|
|
|
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
|
|
|
|
if (state->valid) {
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, &xd);
|
|
|
|
xive_native_sync_source(hw_num);
|
|
|
|
rc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:31 +07:00
|
|
|
static int xive_native_validate_queue_size(u32 qshift)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We only support 64K pages for the moment. This is also
|
|
|
|
* advertised in the DT property "ibm,xive-eq-sizes"
|
|
|
|
*/
|
|
|
|
switch (qshift) {
|
|
|
|
case 0: /* EQ reset */
|
|
|
|
case 16:
|
|
|
|
return 0;
|
|
|
|
case 12:
|
|
|
|
case 21:
|
|
|
|
case 24:
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive,
|
|
|
|
long eq_idx, u64 addr)
|
|
|
|
{
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
struct kvmppc_xive_vcpu *xc;
|
|
|
|
void __user *ubufp = (void __user *) addr;
|
|
|
|
u32 server;
|
|
|
|
u8 priority;
|
|
|
|
struct kvm_ppc_xive_eq kvm_eq;
|
|
|
|
int rc;
|
|
|
|
__be32 *qaddr = 0;
|
|
|
|
struct page *page;
|
|
|
|
struct xive_q *q;
|
|
|
|
gfn_t gfn;
|
|
|
|
unsigned long page_size;
|
2019-05-28 19:17:16 +07:00
|
|
|
int srcu_idx;
|
2019-04-18 17:39:31 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Demangle priority/server tuple from the EQ identifier
|
|
|
|
*/
|
|
|
|
priority = (eq_idx & KVM_XIVE_EQ_PRIORITY_MASK) >>
|
|
|
|
KVM_XIVE_EQ_PRIORITY_SHIFT;
|
|
|
|
server = (eq_idx & KVM_XIVE_EQ_SERVER_MASK) >>
|
|
|
|
KVM_XIVE_EQ_SERVER_SHIFT;
|
|
|
|
|
|
|
|
if (copy_from_user(&kvm_eq, ubufp, sizeof(kvm_eq)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
vcpu = kvmppc_xive_find_server(kvm, server);
|
|
|
|
if (!vcpu) {
|
|
|
|
pr_err("Can't find server %d\n", server);
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
xc = vcpu->arch.xive_vcpu;
|
|
|
|
|
|
|
|
if (priority != xive_prio_from_guest(priority)) {
|
|
|
|
pr_err("Trying to restore invalid queue %d for VCPU %d\n",
|
|
|
|
priority, server);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
q = &xc->queues[priority];
|
|
|
|
|
|
|
|
pr_devel("%s VCPU %d priority %d fl:%x shift:%d addr:%llx g:%d idx:%d\n",
|
|
|
|
__func__, server, priority, kvm_eq.flags,
|
|
|
|
kvm_eq.qshift, kvm_eq.qaddr, kvm_eq.qtoggle, kvm_eq.qindex);
|
|
|
|
|
|
|
|
/* reset queue and disable queueing */
|
|
|
|
if (!kvm_eq.qshift) {
|
|
|
|
q->guest_qaddr = 0;
|
|
|
|
q->guest_qshift = 0;
|
|
|
|
|
2019-11-13 23:46:13 +07:00
|
|
|
rc = kvmppc_xive_native_configure_queue(xc->vp_id, q, priority,
|
|
|
|
NULL, 0, true);
|
2019-04-18 17:39:31 +07:00
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to reset queue %d for VCPU %d: %d\n",
|
|
|
|
priority, xc->server_num, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-20 14:15:13 +07:00
|
|
|
/*
|
|
|
|
* sPAPR specifies a "Unconditional Notify (n) flag" for the
|
|
|
|
* H_INT_SET_QUEUE_CONFIG hcall which forces notification
|
|
|
|
* without using the coalescing mechanisms provided by the
|
|
|
|
* XIVE END ESBs. This is required on KVM as notification
|
|
|
|
* using the END ESBs is not supported.
|
|
|
|
*/
|
|
|
|
if (kvm_eq.flags != KVM_XIVE_EQ_ALWAYS_NOTIFY) {
|
|
|
|
pr_err("invalid flags %d\n", kvm_eq.flags);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = xive_native_validate_queue_size(kvm_eq.qshift);
|
|
|
|
if (rc) {
|
|
|
|
pr_err("invalid queue size %d\n", kvm_eq.qshift);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:31 +07:00
|
|
|
if (kvm_eq.qaddr & ((1ull << kvm_eq.qshift) - 1)) {
|
|
|
|
pr_err("queue page is not aligned %llx/%llx\n", kvm_eq.qaddr,
|
|
|
|
1ull << kvm_eq.qshift);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-05-28 19:17:16 +07:00
|
|
|
srcu_idx = srcu_read_lock(&kvm->srcu);
|
2019-04-18 17:39:31 +07:00
|
|
|
gfn = gpa_to_gfn(kvm_eq.qaddr);
|
|
|
|
|
2020-01-09 03:24:37 +07:00
|
|
|
page_size = kvm_host_page_size(vcpu, gfn);
|
2019-04-18 17:39:31 +07:00
|
|
|
if (1ull << kvm_eq.qshift > page_size) {
|
2019-05-28 19:17:16 +07:00
|
|
|
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
2019-04-18 17:39:31 +07:00
|
|
|
pr_warn("Incompatible host page size %lx!\n", page_size);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-11-13 23:46:19 +07:00
|
|
|
page = gfn_to_page(kvm, gfn);
|
|
|
|
if (is_error_page(page)) {
|
|
|
|
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
|
|
|
pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:31 +07:00
|
|
|
qaddr = page_to_virt(page) + (kvm_eq.qaddr & ~PAGE_MASK);
|
2019-05-28 19:17:16 +07:00
|
|
|
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
2019-04-18 17:39:31 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Backup the queue page guest address to the mark EQ page
|
|
|
|
* dirty for migration.
|
|
|
|
*/
|
|
|
|
q->guest_qaddr = kvm_eq.qaddr;
|
|
|
|
q->guest_qshift = kvm_eq.qshift;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unconditional Notification is forced by default at the
|
|
|
|
* OPAL level because the use of END ESBs is not supported by
|
|
|
|
* Linux.
|
|
|
|
*/
|
2019-11-13 23:46:13 +07:00
|
|
|
rc = kvmppc_xive_native_configure_queue(xc->vp_id, q, priority,
|
|
|
|
(__be32 *) qaddr, kvm_eq.qshift, true);
|
2019-04-18 17:39:31 +07:00
|
|
|
if (rc) {
|
|
|
|
pr_err("Failed to configure queue %d for VCPU %d: %d\n",
|
|
|
|
priority, xc->server_num, rc);
|
|
|
|
put_page(page);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only restore the queue state when needed. When doing the
|
|
|
|
* H_INT_SET_SOURCE_CONFIG hcall, it should not.
|
|
|
|
*/
|
|
|
|
if (kvm_eq.qtoggle != 1 || kvm_eq.qindex != 0) {
|
|
|
|
rc = xive_native_set_queue_state(xc->vp_id, priority,
|
|
|
|
kvm_eq.qtoggle,
|
|
|
|
kvm_eq.qindex);
|
|
|
|
if (rc)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = kvmppc_xive_attach_escalation(vcpu, priority,
|
|
|
|
xive->single_escalation);
|
|
|
|
error:
|
|
|
|
if (rc)
|
|
|
|
kvmppc_xive_native_cleanup_queue(vcpu, priority);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_get_queue_config(struct kvmppc_xive *xive,
|
|
|
|
long eq_idx, u64 addr)
|
|
|
|
{
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
struct kvmppc_xive_vcpu *xc;
|
|
|
|
struct xive_q *q;
|
|
|
|
void __user *ubufp = (u64 __user *) addr;
|
|
|
|
u32 server;
|
|
|
|
u8 priority;
|
|
|
|
struct kvm_ppc_xive_eq kvm_eq;
|
|
|
|
u64 qaddr;
|
|
|
|
u64 qshift;
|
|
|
|
u64 qeoi_page;
|
|
|
|
u32 escalate_irq;
|
|
|
|
u64 qflags;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Demangle priority/server tuple from the EQ identifier
|
|
|
|
*/
|
|
|
|
priority = (eq_idx & KVM_XIVE_EQ_PRIORITY_MASK) >>
|
|
|
|
KVM_XIVE_EQ_PRIORITY_SHIFT;
|
|
|
|
server = (eq_idx & KVM_XIVE_EQ_SERVER_MASK) >>
|
|
|
|
KVM_XIVE_EQ_SERVER_SHIFT;
|
|
|
|
|
|
|
|
vcpu = kvmppc_xive_find_server(kvm, server);
|
|
|
|
if (!vcpu) {
|
|
|
|
pr_err("Can't find server %d\n", server);
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
xc = vcpu->arch.xive_vcpu;
|
|
|
|
|
|
|
|
if (priority != xive_prio_from_guest(priority)) {
|
|
|
|
pr_err("invalid priority for queue %d for VCPU %d\n",
|
|
|
|
priority, server);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
q = &xc->queues[priority];
|
|
|
|
|
|
|
|
memset(&kvm_eq, 0, sizeof(kvm_eq));
|
|
|
|
|
|
|
|
if (!q->qpage)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
rc = xive_native_get_queue_info(xc->vp_id, priority, &qaddr, &qshift,
|
|
|
|
&qeoi_page, &escalate_irq, &qflags);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
kvm_eq.flags = 0;
|
|
|
|
if (qflags & OPAL_XIVE_EQ_ALWAYS_NOTIFY)
|
|
|
|
kvm_eq.flags |= KVM_XIVE_EQ_ALWAYS_NOTIFY;
|
|
|
|
|
|
|
|
kvm_eq.qshift = q->guest_qshift;
|
|
|
|
kvm_eq.qaddr = q->guest_qaddr;
|
|
|
|
|
|
|
|
rc = xive_native_get_queue_state(xc->vp_id, priority, &kvm_eq.qtoggle,
|
|
|
|
&kvm_eq.qindex);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
pr_devel("%s VCPU %d priority %d fl:%x shift:%d addr:%llx g:%d idx:%d\n",
|
|
|
|
__func__, server, priority, kvm_eq.flags,
|
|
|
|
kvm_eq.qshift, kvm_eq.qaddr, kvm_eq.qtoggle, kvm_eq.qindex);
|
|
|
|
|
|
|
|
if (copy_to_user(ubufp, &kvm_eq, sizeof(kvm_eq)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:32 +07:00
|
|
|
static void kvmppc_xive_reset_sources(struct kvmppc_xive_src_block *sb)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (state->act_priority == MASKED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
state->eisn = 0;
|
|
|
|
state->act_server = 0;
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_reset(struct kvmppc_xive *xive)
|
|
|
|
{
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
pr_devel("%s\n", __func__);
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_lock(&xive->lock);
|
2019-04-18 17:39:32 +07:00
|
|
|
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
unsigned int prio;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
kvmppc_xive_disable_vcpu_interrupts(vcpu);
|
|
|
|
|
|
|
|
for (prio = 0; prio < KVMPPC_XIVE_Q_COUNT; prio++) {
|
|
|
|
|
|
|
|
/* Single escalation, no queue 7 */
|
|
|
|
if (prio == 7 && xive->single_escalation)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (xc->esc_virq[prio]) {
|
|
|
|
free_irq(xc->esc_virq[prio], vcpu);
|
|
|
|
irq_dispose_mapping(xc->esc_virq[prio]);
|
|
|
|
kfree(xc->esc_virq_names[prio]);
|
|
|
|
xc->esc_virq[prio] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
kvmppc_xive_native_cleanup_queue(vcpu, prio);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
|
|
|
|
|
|
|
|
if (sb) {
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
kvmppc_xive_reset_sources(sb);
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
2019-04-18 17:39:32 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:34 +07:00
|
|
|
static void kvmppc_xive_native_sync_sources(struct kvmppc_xive_src_block *sb)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
|
|
|
|
for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) {
|
|
|
|
struct kvmppc_xive_irq_state *state = &sb->irq_state[j];
|
|
|
|
struct xive_irq_data *xd;
|
|
|
|
u32 hw_num;
|
|
|
|
|
|
|
|
if (!state->valid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The struct kvmppc_xive_irq_state reflects the state
|
|
|
|
* of the EAS configuration and not the state of the
|
|
|
|
* source. The source is masked setting the PQ bits to
|
|
|
|
* '-Q', which is what is being done before calling
|
|
|
|
* the KVM_DEV_XIVE_EQ_SYNC control.
|
|
|
|
*
|
|
|
|
* If a source EAS is configured, OPAL syncs the XIVE
|
|
|
|
* IC of the source and the XIVE IC of the previous
|
|
|
|
* target if any.
|
|
|
|
*
|
|
|
|
* So it should be fine ignoring MASKED sources as
|
|
|
|
* they have been synced already.
|
|
|
|
*/
|
|
|
|
if (state->act_priority == MASKED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
kvmppc_xive_select_irq(state, &hw_num, &xd);
|
|
|
|
xive_native_sync_source(hw_num);
|
|
|
|
xive_native_sync_queue(hw_num);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_vcpu_eq_sync(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
unsigned int prio;
|
2019-05-28 19:17:16 +07:00
|
|
|
int srcu_idx;
|
2019-04-18 17:39:34 +07:00
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
for (prio = 0; prio < KVMPPC_XIVE_Q_COUNT; prio++) {
|
|
|
|
struct xive_q *q = &xc->queues[prio];
|
|
|
|
|
|
|
|
if (!q->qpage)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Mark EQ page dirty for migration */
|
2019-05-28 19:17:16 +07:00
|
|
|
srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
|
2019-04-18 17:39:34 +07:00
|
|
|
mark_page_dirty(vcpu->kvm, gpa_to_gfn(q->guest_qaddr));
|
2019-05-28 19:17:16 +07:00
|
|
|
srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
|
2019-04-18 17:39:34 +07:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_eq_sync(struct kvmppc_xive *xive)
|
|
|
|
{
|
|
|
|
struct kvm *kvm = xive->kvm;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
pr_devel("%s\n", __func__);
|
|
|
|
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_lock(&xive->lock);
|
2019-04-18 17:39:34 +07:00
|
|
|
for (i = 0; i <= xive->max_sbid; i++) {
|
|
|
|
struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
|
|
|
|
|
|
|
|
if (sb) {
|
|
|
|
arch_spin_lock(&sb->lock);
|
|
|
|
kvmppc_xive_native_sync_sources(sb);
|
|
|
|
arch_spin_unlock(&sb->lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
kvmppc_xive_native_vcpu_eq_sync(vcpu);
|
|
|
|
}
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_unlock(&xive->lock);
|
2019-04-18 17:39:34 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:27 +07:00
|
|
|
static int kvmppc_xive_native_set_attr(struct kvm_device *dev,
|
|
|
|
struct kvm_device_attr *attr)
|
|
|
|
{
|
2019-04-18 17:39:29 +07:00
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
|
2019-04-18 17:39:27 +07:00
|
|
|
switch (attr->group) {
|
|
|
|
case KVM_DEV_XIVE_GRP_CTRL:
|
2019-04-18 17:39:32 +07:00
|
|
|
switch (attr->attr) {
|
|
|
|
case KVM_DEV_XIVE_RESET:
|
|
|
|
return kvmppc_xive_reset(xive);
|
2019-04-18 17:39:34 +07:00
|
|
|
case KVM_DEV_XIVE_EQ_SYNC:
|
|
|
|
return kvmppc_xive_native_eq_sync(xive);
|
2019-09-27 18:54:07 +07:00
|
|
|
case KVM_DEV_XIVE_NR_SERVERS:
|
|
|
|
return kvmppc_xive_set_nr_servers(xive, attr->addr);
|
2019-04-18 17:39:32 +07:00
|
|
|
}
|
2019-04-18 17:39:27 +07:00
|
|
|
break;
|
2019-04-18 17:39:29 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_SOURCE:
|
|
|
|
return kvmppc_xive_native_set_source(xive, attr->attr,
|
|
|
|
attr->addr);
|
2019-04-18 17:39:30 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_SOURCE_CONFIG:
|
|
|
|
return kvmppc_xive_native_set_source_config(xive, attr->attr,
|
|
|
|
attr->addr);
|
2019-04-18 17:39:31 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_EQ_CONFIG:
|
|
|
|
return kvmppc_xive_native_set_queue_config(xive, attr->attr,
|
|
|
|
attr->addr);
|
2019-04-18 17:39:33 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_SOURCE_SYNC:
|
|
|
|
return kvmppc_xive_native_sync_source(xive, attr->attr,
|
|
|
|
attr->addr);
|
2019-04-18 17:39:27 +07:00
|
|
|
}
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_get_attr(struct kvm_device *dev,
|
|
|
|
struct kvm_device_attr *attr)
|
|
|
|
{
|
2019-04-18 17:39:31 +07:00
|
|
|
struct kvmppc_xive *xive = dev->private;
|
|
|
|
|
|
|
|
switch (attr->group) {
|
|
|
|
case KVM_DEV_XIVE_GRP_EQ_CONFIG:
|
|
|
|
return kvmppc_xive_native_get_queue_config(xive, attr->attr,
|
|
|
|
attr->addr);
|
|
|
|
}
|
2019-04-18 17:39:27 +07:00
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kvmppc_xive_native_has_attr(struct kvm_device *dev,
|
|
|
|
struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
switch (attr->group) {
|
|
|
|
case KVM_DEV_XIVE_GRP_CTRL:
|
2019-04-18 17:39:32 +07:00
|
|
|
switch (attr->attr) {
|
|
|
|
case KVM_DEV_XIVE_RESET:
|
2019-04-18 17:39:34 +07:00
|
|
|
case KVM_DEV_XIVE_EQ_SYNC:
|
2019-09-27 18:54:07 +07:00
|
|
|
case KVM_DEV_XIVE_NR_SERVERS:
|
2019-04-18 17:39:32 +07:00
|
|
|
return 0;
|
|
|
|
}
|
2019-04-18 17:39:27 +07:00
|
|
|
break;
|
2019-04-18 17:39:29 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_SOURCE:
|
2019-04-18 17:39:30 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_SOURCE_CONFIG:
|
2019-04-18 17:39:33 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_SOURCE_SYNC:
|
2019-04-18 17:39:29 +07:00
|
|
|
if (attr->attr >= KVMPPC_XIVE_FIRST_IRQ &&
|
|
|
|
attr->attr < KVMPPC_XIVE_NR_IRQS)
|
|
|
|
return 0;
|
|
|
|
break;
|
2019-04-18 17:39:31 +07:00
|
|
|
case KVM_DEV_XIVE_GRP_EQ_CONFIG:
|
|
|
|
return 0;
|
2019-04-18 17:39:27 +07:00
|
|
|
}
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
/*
|
2019-05-24 20:20:30 +07:00
|
|
|
* Called when device fd is closed. kvm->lock is held.
|
2019-04-18 17:39:42 +07:00
|
|
|
*/
|
|
|
|
static void kvmppc_xive_native_release(struct kvm_device *dev)
|
2019-04-18 17:39:27 +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;
|
2019-04-18 17:39:29 +07:00
|
|
|
int i;
|
2019-04-18 17:39:27 +07:00
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
pr_devel("Releasing xive native device\n");
|
|
|
|
|
2019-05-20 14:15:12 +07:00
|
|
|
/*
|
|
|
|
* Clear the KVM device file address_space which is used to
|
|
|
|
* unmap the ESB pages when a device is passed-through.
|
|
|
|
*/
|
|
|
|
mutex_lock(&xive->mapping_lock);
|
|
|
|
xive->mapping = NULL;
|
|
|
|
mutex_unlock(&xive->mapping_lock);
|
|
|
|
|
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
|
|
|
* Since this is the device release function, we know that
|
|
|
|
* userspace does not have any open fd or mmap referring to
|
|
|
|
* the device. Therefore there can not be any of the
|
|
|
|
* device attribute set/get, mmap, or page fault 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);
|
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_native_[gs]et_vp) can be being done.
|
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);
|
2019-04-18 17:39:42 +07:00
|
|
|
kvmppc_xive_native_cleanup_vcpu(vcpu);
|
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_unlock(&vcpu->mutex);
|
|
|
|
}
|
2019-04-18 17:39:27 +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;
|
2019-04-18 17:39:27 +07:00
|
|
|
|
2019-04-18 17:39:29 +07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:27 +07:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2019-04-18 17:39:27 +07:00
|
|
|
kfree(dev);
|
|
|
|
}
|
|
|
|
|
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 XIVE device. kvm->lock is held.
|
|
|
|
*/
|
2019-04-18 17:39:27 +07:00
|
|
|
static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive;
|
|
|
|
struct kvm *kvm = dev->kvm;
|
|
|
|
|
|
|
|
pr_devel("Creating xive native device\n");
|
|
|
|
|
|
|
|
if (kvm->arch.xive)
|
|
|
|
return -EEXIST;
|
|
|
|
|
2019-04-18 17:39:42 +07:00
|
|
|
xive = kvmppc_xive_get_device(kvm, type);
|
2019-04-18 17:39:27 +07:00
|
|
|
if (!xive)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
dev->private = xive;
|
|
|
|
xive->dev = dev;
|
|
|
|
xive->kvm = kvm;
|
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
|
|
|
mutex_init(&xive->mapping_lock);
|
2019-05-24 20:20:30 +07:00
|
|
|
mutex_init(&xive->lock);
|
2019-04-18 17:39:27 +07:00
|
|
|
|
2019-09-27 18:54:01 +07:00
|
|
|
/* VP allocation is delayed to the first call to connect_vcpu */
|
|
|
|
xive->vp_base = XIVE_INVALID_VP;
|
|
|
|
/* KVM_MAX_VCPUS limits the number of VMs to roughly 64 per sockets
|
|
|
|
* on a POWER9 system.
|
2019-04-18 17:39:27 +07:00
|
|
|
*/
|
2019-09-27 18:54:01 +07:00
|
|
|
xive->nr_servers = KVM_MAX_VCPUS;
|
2019-04-18 17:39:27 +07:00
|
|
|
|
|
|
|
xive->single_escalation = xive_native_has_single_escalation();
|
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
|
|
|
xive->ops = &kvmppc_xive_native_ops;
|
2019-04-18 17:39:27 +07:00
|
|
|
|
2019-09-27 18:53:38 +07:00
|
|
|
kvm->arch.xive = xive;
|
2019-07-19 04:51:54 +07:00
|
|
|
return 0;
|
2019-04-18 17:39:27 +07:00
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:35 +07:00
|
|
|
/*
|
|
|
|
* Interrupt Pending Buffer (IPB) offset
|
|
|
|
*/
|
|
|
|
#define TM_IPB_SHIFT 40
|
|
|
|
#define TM_IPB_MASK (((u64) 0xFF) << TM_IPB_SHIFT)
|
|
|
|
|
|
|
|
int kvmppc_xive_native_get_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
u64 opal_state;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (!kvmppc_xive_enabled(vcpu))
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
/* Thread context registers. We only care about IPB and CPPR */
|
|
|
|
val->xive_timaval[0] = vcpu->arch.xive_saved_state.w01;
|
|
|
|
|
|
|
|
/* Get the VP state from OPAL */
|
|
|
|
rc = xive_native_get_vp_state(xc->vp_id, &opal_state);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Capture the backup of IPB register in the NVT structure and
|
|
|
|
* merge it in our KVM VP state.
|
|
|
|
*/
|
|
|
|
val->xive_timaval[0] |= cpu_to_be64(opal_state & TM_IPB_MASK);
|
|
|
|
|
|
|
|
pr_devel("%s NSR=%02x CPPR=%02x IBP=%02x PIPR=%02x w01=%016llx w2=%08x opal=%016llx\n",
|
|
|
|
__func__,
|
|
|
|
vcpu->arch.xive_saved_state.nsr,
|
|
|
|
vcpu->arch.xive_saved_state.cppr,
|
|
|
|
vcpu->arch.xive_saved_state.ipb,
|
|
|
|
vcpu->arch.xive_saved_state.pipr,
|
|
|
|
vcpu->arch.xive_saved_state.w01,
|
|
|
|
(u32) vcpu->arch.xive_cam_word, opal_state);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvmppc_xive_native_set_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
|
|
|
|
|
|
|
|
pr_devel("%s w01=%016llx vp=%016llx\n", __func__,
|
|
|
|
val->xive_timaval[0], val->xive_timaval[1]);
|
|
|
|
|
|
|
|
if (!kvmppc_xive_enabled(vcpu))
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
if (!xc || !xive)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
/* We can't update the state of a "pushed" VCPU */
|
|
|
|
if (WARN_ON(vcpu->arch.xive_pushed))
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore the thread context registers. IPB and CPPR should
|
|
|
|
* be the only ones that matter.
|
|
|
|
*/
|
|
|
|
vcpu->arch.xive_saved_state.w01 = val->xive_timaval[0];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There is no need to restore the XIVE internal state (IPB
|
|
|
|
* stored in the NVT) as the IPB register was merged in KVM VP
|
|
|
|
* state when captured.
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-08-26 13:21:21 +07:00
|
|
|
bool kvmppc_xive_native_supported(void)
|
|
|
|
{
|
|
|
|
return xive_native_has_queue_state_support();
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:27 +07:00
|
|
|
static int xive_native_debug_show(struct seq_file *m, void *private)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = m->private;
|
|
|
|
struct kvm *kvm = xive->kvm;
|
2019-04-18 17:39:28 +07:00
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
unsigned int i;
|
2019-04-18 17:39:27 +07:00
|
|
|
|
|
|
|
if (!kvm)
|
|
|
|
return 0;
|
|
|
|
|
2019-04-18 17:39:28 +07:00
|
|
|
seq_puts(m, "=========\nVCPU state\n=========\n");
|
|
|
|
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
|
|
|
|
|
|
|
if (!xc)
|
|
|
|
continue;
|
|
|
|
|
2019-09-27 18:53:49 +07:00
|
|
|
seq_printf(m, "cpu server %#x VP=%#x NSR=%02x CPPR=%02x IBP=%02x PIPR=%02x w01=%016llx w2=%08x\n",
|
|
|
|
xc->server_num, xc->vp_id,
|
2019-04-18 17:39:28 +07:00
|
|
|
vcpu->arch.xive_saved_state.nsr,
|
|
|
|
vcpu->arch.xive_saved_state.cppr,
|
|
|
|
vcpu->arch.xive_saved_state.ipb,
|
|
|
|
vcpu->arch.xive_saved_state.pipr,
|
|
|
|
vcpu->arch.xive_saved_state.w01,
|
|
|
|
(u32) vcpu->arch.xive_cam_word);
|
|
|
|
|
|
|
|
kvmppc_xive_debug_show_queues(m, vcpu);
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:39:27 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xive_native_debug_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, xive_native_debug_show, inode->i_private);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations xive_native_debug_fops = {
|
|
|
|
.open = xive_native_debug_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void xive_native_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, 0444, powerpc_debugfs_root,
|
|
|
|
xive, &xive_native_debug_fops);
|
|
|
|
|
|
|
|
pr_debug("%s: created %s\n", __func__, name);
|
|
|
|
kfree(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kvmppc_xive_native_init(struct kvm_device *dev)
|
|
|
|
{
|
|
|
|
struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private;
|
|
|
|
|
|
|
|
/* Register some debug interfaces */
|
|
|
|
xive_native_debugfs_init(xive);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct kvm_device_ops kvm_xive_native_ops = {
|
|
|
|
.name = "kvm-xive-native",
|
|
|
|
.create = kvmppc_xive_native_create,
|
|
|
|
.init = kvmppc_xive_native_init,
|
2019-04-18 17:39:42 +07:00
|
|
|
.release = kvmppc_xive_native_release,
|
2019-04-18 17:39:27 +07:00
|
|
|
.set_attr = kvmppc_xive_native_set_attr,
|
|
|
|
.get_attr = kvmppc_xive_native_get_attr,
|
|
|
|
.has_attr = kvmppc_xive_native_has_attr,
|
2019-04-18 17:39:37 +07:00
|
|
|
.mmap = kvmppc_xive_native_mmap,
|
2019-04-18 17:39:27 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
void kvmppc_xive_native_init_module(void)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
void kvmppc_xive_native_exit_module(void)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|