From patchwork Mon Apr 23 16:43:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903129 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VDq13pTNz9s06 for ; Tue, 24 Apr 2018 04:03:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932319AbeDWSDk (ORCPT ); Mon, 23 Apr 2018 14:03:40 -0400 Received: from 6.mo2.mail-out.ovh.net ([87.98.165.38]:33895 "EHLO 6.mo2.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932109AbeDWSDk (ORCPT ); Mon, 23 Apr 2018 14:03:40 -0400 X-Greylist: delayed 4780 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 14:03:39 EDT Received: from player737.ha.ovh.net (unknown [10.109.120.71]) by mo2.mail-out.ovh.net (Postfix) with ESMTP id 3A820121A30 for ; Mon, 23 Apr 2018 18:43:58 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id E97EDE00BB; Mon, 23 Apr 2018 18:43:51 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 01/16] powerpc/xive: export flags for the XIVE native exploitation mode hcalls Date: Mon, 23 Apr 2018 18:43:26 +0200 Message-Id: <20180423164341.15767-2-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 958703772596866007 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org These flags are shared between Linux/KVM implementing the hypervisor calls for the XIVE native exploitation mode and the driver for the sPAPR guests. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/xive.h | 23 +++++++++++++++++++++++ arch/powerpc/sysdev/xive/spapr.c | 28 ++++++++-------------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h index 8d1a2792484f..33c76321f91a 100644 --- a/arch/powerpc/include/asm/xive.h +++ b/arch/powerpc/include/asm/xive.h @@ -94,6 +94,29 @@ extern void xive_flush_interrupt(void); /* xmon hook */ extern void xmon_xive_do_dump(int cpu); +/* + * Hcall flags shared by the sPAPR backend and KVM + */ + +/* H_INT_GET_SOURCE_INFO */ +#define XIVE_SPAPR_SRC_H_INT_ESB PPC_BIT(60) +#define XIVE_SPAPR_SRC_LSI PPC_BIT(61) +#define XIVE_SPAPR_SRC_TRIGGER PPC_BIT(62) +#define XIVE_SPAPR_SRC_STORE_EOI PPC_BIT(63) + +/* H_INT_SET_SOURCE_CONFIG */ +#define XIVE_SPAPR_SRC_SET_EISN PPC_BIT(62) +#define XIVE_SPAPR_SRC_MASK PPC_BIT(63) /* unused */ + +/* H_INT_SET_QUEUE_CONFIG */ +#define XIVE_SPAPR_EQ_ALWAYS_NOTIFY PPC_BIT(63) + +/* H_INT_SET_QUEUE_CONFIG */ +#define XIVE_SPAPR_EQ_DEBUG PPC_BIT(63) + +/* H_INT_ESB */ +#define XIVE_SPAPR_ESB_STORE PPC_BIT(63) + /* APIs used by KVM */ extern u32 xive_native_default_eq_shift(void); extern u32 xive_native_alloc_vp_block(u32 max_vcpus); diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c index 091f1d0d0af1..3cf5f8bf4c29 100644 --- a/arch/powerpc/sysdev/xive/spapr.c +++ b/arch/powerpc/sysdev/xive/spapr.c @@ -135,9 +135,6 @@ static long plpar_int_get_source_info(unsigned long flags, return 0; } -#define XIVE_SRC_SET_EISN (1ull << (63 - 62)) -#define XIVE_SRC_MASK (1ull << (63 - 63)) /* unused */ - static long plpar_int_set_source_config(unsigned long flags, unsigned long lisn, unsigned long target, @@ -187,8 +184,6 @@ static long plpar_int_get_queue_info(unsigned long flags, return 0; } -#define XIVE_EQ_ALWAYS_NOTIFY (1ull << (63 - 63)) - static long plpar_int_set_queue_config(unsigned long flags, unsigned long target, unsigned long priority, @@ -224,8 +219,6 @@ static long plpar_int_sync(unsigned long flags, unsigned long lisn) return 0; } -#define XIVE_ESB_FLAG_STORE (1ull << (63 - 63)) - static long plpar_int_esb(unsigned long flags, unsigned long lisn, unsigned long offset, @@ -255,7 +248,7 @@ static u64 xive_spapr_esb_rw(u32 lisn, u32 offset, u64 data, bool write) unsigned long read_data; long rc; - rc = plpar_int_esb(write ? XIVE_ESB_FLAG_STORE : 0, + rc = plpar_int_esb(write ? XIVE_SPAPR_ESB_STORE : 0, lisn, offset, data, &read_data); if (rc) return -1; @@ -263,11 +256,6 @@ static u64 xive_spapr_esb_rw(u32 lisn, u32 offset, u64 data, bool write) return write ? 0 : read_data; } -#define XIVE_SRC_H_INT_ESB (1ull << (63 - 60)) -#define XIVE_SRC_LSI (1ull << (63 - 61)) -#define XIVE_SRC_TRIGGER (1ull << (63 - 62)) -#define XIVE_SRC_STORE_EOI (1ull << (63 - 63)) - static int xive_spapr_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) { long rc; @@ -283,11 +271,11 @@ static int xive_spapr_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) if (rc) return -EINVAL; - if (flags & XIVE_SRC_H_INT_ESB) + if (flags & XIVE_SPAPR_SRC_H_INT_ESB) data->flags |= XIVE_IRQ_FLAG_H_INT_ESB; - if (flags & XIVE_SRC_STORE_EOI) + if (flags & XIVE_SPAPR_SRC_STORE_EOI) data->flags |= XIVE_IRQ_FLAG_STORE_EOI; - if (flags & XIVE_SRC_LSI) + if (flags & XIVE_SPAPR_SRC_LSI) data->flags |= XIVE_IRQ_FLAG_LSI; data->eoi_page = eoi_page; data->esb_shift = esb_shift; @@ -308,7 +296,7 @@ static int xive_spapr_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) data->hw_irq = hw_irq; /* Full function page supports trigger */ - if (flags & XIVE_SRC_TRIGGER) { + if (flags & XIVE_SPAPR_SRC_TRIGGER) { data->trig_mmio = data->eoi_mmio; return 0; } @@ -325,8 +313,8 @@ static int xive_spapr_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq) { long rc; - rc = plpar_int_set_source_config(XIVE_SRC_SET_EISN, hw_irq, target, - prio, sw_irq); + rc = plpar_int_set_source_config(XIVE_SPAPR_SRC_SET_EISN, hw_irq, + target, prio, sw_irq); return rc == 0 ? 0 : -ENXIO; } @@ -366,7 +354,7 @@ static int xive_spapr_configure_queue(u32 target, struct xive_q *q, u8 prio, q->eoi_phys = esn_page; /* Default is to always notify */ - flags = XIVE_EQ_ALWAYS_NOTIFY; + flags = XIVE_SPAPR_EQ_ALWAYS_NOTIFY; /* Configure and enable the queue in HW */ rc = plpar_int_set_queue_config(flags, target, prio, qpage_phys, order); From patchwork Mon Apr 23 16:43:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903022 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VC3C5jpNz9ry1 for ; Tue, 24 Apr 2018 02:44:07 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932145AbeDWQoG (ORCPT ); Mon, 23 Apr 2018 12:44:06 -0400 Received: from 3.mo3.mail-out.ovh.net ([46.105.44.175]:60462 "EHLO 3.mo3.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932156AbeDWQoG (ORCPT ); Mon, 23 Apr 2018 12:44:06 -0400 Received: from player737.ha.ovh.net (unknown [10.109.108.50]) by mo3.mail-out.ovh.net (Postfix) with ESMTP id 68FD41B3F40 for ; Mon, 23 Apr 2018 18:44:04 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 1D144E0099; Mon, 23 Apr 2018 18:43:58 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 02/16] powerpc/xive: add OPAL extensions for the XIVE native exploitation support Date: Mon, 23 Apr 2018 18:43:27 +0200 Message-Id: <20180423164341.15767-3-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 960392621519506391 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The support for XIVE native exploitation mode in Linux/KVM needs a couple more OPAL calls to configure the sPAPR guest and to save/restore the state of the XIVE internals. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/opal-api.h | 13 ++- arch/powerpc/include/asm/opal.h | 12 +++ arch/powerpc/include/asm/xive.h | 19 +++++ arch/powerpc/platforms/powernv/opal-wrappers.S | 4 + arch/powerpc/sysdev/xive/native.c | 107 +++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 94bd1bf2c873..17803390811a 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -186,8 +186,8 @@ #define OPAL_XIVE_FREE_IRQ 140 #define OPAL_XIVE_SYNC 141 #define OPAL_XIVE_DUMP 142 -#define OPAL_XIVE_RESERVED3 143 -#define OPAL_XIVE_RESERVED4 144 +#define OPAL_XIVE_GET_QUEUE_STATE 143 +#define OPAL_XIVE_SET_QUEUE_STATE 144 #define OPAL_SIGNAL_SYSTEM_RESET 145 #define OPAL_NPU_INIT_CONTEXT 146 #define OPAL_NPU_DESTROY_CONTEXT 147 @@ -204,7 +204,14 @@ #define OPAL_NPU_SPA_SETUP 159 #define OPAL_NPU_SPA_CLEAR_CACHE 160 #define OPAL_NPU_TL_SET 161 -#define OPAL_LAST 161 +#define OPAL_SENSOR_READ_U64 162 +#define OPAL_SENSOR_GROUP_ENABLE 163 +#define OPAL_PCI_GET_PBCQ_TUNNEL_BAR 164 +#define OPAL_PCI_SET_PBCQ_TUNNEL_BAR 165 +#define OPAL_HANDLE_HMI2 166 +#define OPAL_XIVE_GET_VP_STATE 167 +#define OPAL_XIVE_SET_VP_STATE 168 +#define OPAL_LAST 168 /* Device tree flags */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 12e70fb58700..d7c228634911 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -273,6 +273,18 @@ int64_t opal_xive_allocate_irq(uint32_t chip_id); int64_t opal_xive_free_irq(uint32_t girq); int64_t opal_xive_sync(uint32_t type, uint32_t id); int64_t opal_xive_dump(uint32_t type, uint32_t id); +int64_t opal_xive_get_queue_state(uint64_t vp, uint32_t prio, + __be32 *out_version, + __be64 *out_state); +int64_t opal_xive_set_queue_state(uint64_t vp, uint32_t prio, + uint32_t version, + uint64_t new_state); +int64_t opal_xive_get_vp_state(uint64_t vp, + __be32 *out_version, + __be64 *out_state); +int64_t opal_xive_set_vp_state(uint64_t vp, + uint32_t version, + uint64_t new_state); int64_t opal_pci_set_p2p(uint64_t phb_init, uint64_t phb_target, uint64_t desc, uint16_t pe_number); diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h index 33c76321f91a..aef28248b5b7 100644 --- a/arch/powerpc/include/asm/xive.h +++ b/arch/powerpc/include/asm/xive.h @@ -139,6 +139,25 @@ extern int xive_native_disable_vp(u32 vp_id); extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id); extern bool xive_native_has_single_escalation(void); +extern int xive_native_get_queue_info(u32 vp_id, uint32_t prio, + u64 *out_qpage, + u64 *out_qsize, + u64 *out_qeoi_page, + u32 *out_escalate_irq, + u64 *out_qflags); + +/* Version is 1, backward compatible to 1 */ +#define XIVE_STATE_VERSION 0x00010001 +#define XIVE_STATE_COMPAT(v) ((v) & 0xffff) + +extern int xive_native_get_queue_state(u32 vp_id, uint32_t prio, u32 *out_version, + u64 *out_state); +extern int xive_native_set_queue_state(u32 vp_id, uint32_t prio, u32 version, + u64 state); +extern int xive_native_get_vp_state(u32 vp_id, u32 *out_version, + u64 *out_state); +extern int xive_native_set_vp_state(u32 vp_id, u32 version, u64 state); + #else static inline bool xive_enabled(void) { return false; } diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 1b2936ba6040..feb51ce21326 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -307,6 +307,10 @@ OPAL_CALL(opal_xive_get_vp_info, OPAL_XIVE_GET_VP_INFO); OPAL_CALL(opal_xive_set_vp_info, OPAL_XIVE_SET_VP_INFO); OPAL_CALL(opal_xive_sync, OPAL_XIVE_SYNC); OPAL_CALL(opal_xive_dump, OPAL_XIVE_DUMP); +OPAL_CALL(opal_xive_get_queue_state, OPAL_XIVE_GET_QUEUE_STATE); +OPAL_CALL(opal_xive_set_queue_state, OPAL_XIVE_SET_QUEUE_STATE); +OPAL_CALL(opal_xive_get_vp_state, OPAL_XIVE_GET_VP_STATE); +OPAL_CALL(opal_xive_set_vp_state, OPAL_XIVE_SET_VP_STATE); OPAL_CALL(opal_signal_system_reset, OPAL_SIGNAL_SYSTEM_RESET); OPAL_CALL(opal_npu_init_context, OPAL_NPU_INIT_CONTEXT); OPAL_CALL(opal_npu_destroy_context, OPAL_NPU_DESTROY_CONTEXT); diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index d22aeb0b69e1..0b71ac83f7c6 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -724,3 +724,110 @@ bool xive_native_has_single_escalation(void) return xive_has_single_esc; } EXPORT_SYMBOL_GPL(xive_native_has_single_escalation); + +int xive_native_get_queue_info(u32 vp_id, u32 prio, + u64 *out_qpage, + u64 *out_qsize, + u64 *out_qeoi_page, + u32 *out_escalate_irq, + u64 *out_qflags) +{ + __be64 qpage; + __be64 qsize; + __be64 qeoi_page; + __be32 escalate_irq; + __be64 qflags; + s64 rc; + + rc = opal_xive_get_queue_info(vp_id, prio, &qpage, &qsize, + &qeoi_page, &escalate_irq, &qflags); + if (rc) { + pr_err("OPAL failed to get queue info for VCPU %d/%d : %lld\n", + vp_id, prio, rc); + return -EIO; + } + *out_qpage = be64_to_cpu(qpage); + *out_qsize = be32_to_cpu(qsize); + *out_qeoi_page = be64_to_cpu(qeoi_page); + *out_escalate_irq = be32_to_cpu(escalate_irq); + *out_qflags = be64_to_cpu(qflags); + + return 0; +} +EXPORT_SYMBOL_GPL(xive_native_get_queue_info); + +int xive_native_get_queue_state(u32 vp_id, u32 prio, + u32 *out_version, + u64 *out_state) +{ + __be32 version; + __be64 state; + s64 rc; + + rc = opal_xive_get_queue_state(vp_id, prio, &version, &state); + if (rc) { + pr_err("OPAL failed to get queue state for VCPU %d/%d : %lld\n", + vp_id, prio, rc); + return -EIO; + } + + *out_version = be32_to_cpu(version); + *out_state = be64_to_cpu(state); + return 0; +} +EXPORT_SYMBOL_GPL(xive_native_get_queue_state); + +int xive_native_set_queue_state(u32 vp_id, u32 prio, + u32 version, + u64 state) +{ + s64 rc; + + rc = opal_xive_set_queue_state(vp_id, prio, version, state); + if (rc) { + pr_err("OPAL failed to set queue state for VCPU %d/%d : %lld\n", + vp_id, prio, rc); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(xive_native_set_queue_state); + +int xive_native_get_vp_state(u32 vp_id, + u32 *out_version, + u64 *out_state) +{ + __be32 version; + __be64 state; + s64 rc; + + rc = opal_xive_get_vp_state(vp_id, &version, &state); + if (rc) { + pr_err("OPAL failed to get vp state for VCPU %d : %lld\n", + vp_id, rc); + return -EIO; + } + + *out_version = be32_to_cpu(version); + *out_state = be64_to_cpu(state); + return 0; +} +EXPORT_SYMBOL_GPL(xive_native_get_vp_state); + +int xive_native_set_vp_state(u32 vp_id, + u32 version, + u64 state) +{ + s64 rc; + + rc = opal_xive_set_vp_state(vp_id, version, state); + if (rc) { + pr_err("OPAL failed to set vp state for VCPU %d : %lld\n", + vp_id, rc); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(xive_native_set_vp_state); From patchwork Mon Apr 23 16:43:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903042 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCQV517sz9s08 for ; Tue, 24 Apr 2018 03:00:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755600AbeDWRAt (ORCPT ); Mon, 23 Apr 2018 13:00:49 -0400 Received: from 1.mo68.mail-out.ovh.net ([46.105.41.146]:60973 "EHLO 1.mo68.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755603AbeDWRAt (ORCPT ); Mon, 23 Apr 2018 13:00:49 -0400 X-Greylist: delayed 947 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 13:00:48 EDT Received: from player737.ha.ovh.net (unknown [10.109.122.68]) by mo68.mail-out.ovh.net (Postfix) with ESMTP id 8F838DFAEF for ; Mon, 23 Apr 2018 18:44:10 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 452E7E0099; Mon, 23 Apr 2018 18:44:04 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 03/16] KVM: PPC: Book3S HV: check the IRQ controller type Date: Mon, 23 Apr 2018 18:43:28 +0200 Message-Id: <20180423164341.15767-4-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 962081472082316247 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org We will have different KVM devices for interrupts, one for the XICS-over-XIVE mode and one for the XIVE native exploitation mode. Let's add some checks to make sure we are not mixing the interfaces in KVM. Signed-off-by: Cédric Le Goater --- arch/powerpc/kvm/book3s_xive.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index f9818d7d3381..a23ea2f2abe5 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -751,6 +751,9 @@ u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu) { struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + if (!kvmppc_xics_enabled(vcpu)) + return -EPERM; + if (!xc) return 0; @@ -767,6 +770,9 @@ int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) u8 cppr, mfrr; u32 xisr; + if (!kvmppc_xics_enabled(vcpu)) + return -EPERM; + if (!xc || !xive) return -ENOENT; From patchwork Mon Apr 23 16:43:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903075 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCrg2VDRz9s0W for ; Tue, 24 Apr 2018 03:20:03 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755473AbeDWRUC (ORCPT ); Mon, 23 Apr 2018 13:20:02 -0400 Received: from 13.mo7.mail-out.ovh.net ([87.98.150.175]:52677 "EHLO 13.mo7.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932073AbeDWRUC (ORCPT ); Mon, 23 Apr 2018 13:20:02 -0400 Received: from player737.ha.ovh.net (unknown [10.109.105.5]) by mo7.mail-out.ovh.net (Postfix) with ESMTP id A1DDFA354F for ; Mon, 23 Apr 2018 18:44:16 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 6DED7E00A0; Mon, 23 Apr 2018 18:44:10 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 04/16] KVM: PPC: Book3S HV: export services for the XIVE native exploitation device Date: Mon, 23 Apr 2018 18:43:29 +0200 Message-Id: <20180423164341.15767-5-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 963770323437652951 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The KVM device for the XIVE native exploitation mode will reuse the structures of the XICS-over-XIVE glue implementation. Some code will also be shared : source block creation and destruction, target selection and escalation attachment. Signed-off-by: Cédric Le Goater --- arch/powerpc/kvm/book3s_xive.c | 89 ++++++++++++++++++++++++------------------ arch/powerpc/kvm/book3s_xive.h | 11 ++++++ 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index a23ea2f2abe5..10e2ceae7b04 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -103,7 +103,7 @@ static irqreturn_t xive_esc_irq(int irq, void *data) return IRQ_HANDLED; } -static int xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio) +int kvmppc_xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio) { struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; struct xive_q *q = &xc->queues[prio]; @@ -228,7 +228,7 @@ static int xive_check_provisioning(struct kvm *kvm, u8 prio) continue; rc = xive_provision_queue(vcpu, prio); if (rc == 0 && !xive->single_escalation) - xive_attach_escalation(vcpu, prio); + kvmppc_xive_attach_escalation(vcpu, prio); if (rc) return rc; } @@ -279,7 +279,7 @@ static int xive_try_pick_queue(struct kvm_vcpu *vcpu, u8 prio) return atomic_add_unless(&q->count, 1, max) ? 0 : -EBUSY; } -static int xive_select_target(struct kvm *kvm, u32 *server, u8 prio) +int kvmppc_xive_select_target(struct kvm *kvm, u32 *server, u8 prio) { struct kvm_vcpu *vcpu; int i, rc; @@ -467,7 +467,7 @@ static int xive_target_interrupt(struct kvm *kvm, * priority. The count for that new target will have * already been incremented. */ - rc = xive_select_target(kvm, &server, prio); + rc = kvmppc_xive_select_target(kvm, &server, prio); /* * We failed to find a target ? Not much we can do @@ -987,7 +987,7 @@ int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq, } EXPORT_SYMBOL_GPL(kvmppc_xive_clr_mapped); -static void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu) +void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu) { struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; struct kvm *kvm = vcpu->kvm; @@ -1157,7 +1157,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, if (xive->qmap & (1 << i)) { r = xive_provision_queue(vcpu, i); if (r == 0 && !xive->single_escalation) - xive_attach_escalation(vcpu, i); + kvmppc_xive_attach_escalation(vcpu, i); if (r) goto bail; } else { @@ -1172,7 +1172,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, } /* If not done above, attach priority 0 escalation */ - r = xive_attach_escalation(vcpu, 0); + r = kvmppc_xive_attach_escalation(vcpu, 0); if (r) goto bail; @@ -1423,8 +1423,8 @@ static int xive_get_source(struct kvmppc_xive *xive, long irq, u64 addr) return 0; } -static struct kvmppc_xive_src_block *xive_create_src_block(struct kvmppc_xive *xive, - int irq) +struct kvmppc_xive_src_block *kvmppc_xive_create_src_block( + struct kvmppc_xive *xive, int irq) { struct kvm *kvm = xive->kvm; struct kvmppc_xive_src_block *sb; @@ -1503,7 +1503,7 @@ static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr) sb = kvmppc_xive_find_source(xive, irq, &idx); if (!sb) { pr_devel("No source, creating source block...\n"); - sb = xive_create_src_block(xive, irq); + sb = kvmppc_xive_create_src_block(xive, irq); if (!sb) { pr_devel("Failed to create block...\n"); return -ENOMEM; @@ -1727,7 +1727,7 @@ static void kvmppc_xive_cleanup_irq(u32 hw_num, struct xive_irq_data *xd) xive_cleanup_irq_data(xd); } -static void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb) +void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb) { int i; @@ -1756,6 +1756,8 @@ static void kvmppc_xive_free(struct kvm_device *dev) debugfs_remove(xive->dentry); + pr_devel("Destroying xive for partition\n"); + if (kvm) kvm->arch.xive = NULL; @@ -1821,6 +1823,43 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type) return 0; } +int kvmppc_xive_debug_show_queues(struct seq_file *m, struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + unsigned int i; + + for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { + struct xive_q *q = &xc->queues[i]; + u32 i0, i1, idx; + + if (!q->qpage && !xc->esc_virq[i]) + continue; + + seq_printf(m, " [q%d]: ", i); + + if (q->qpage) { + idx = q->idx; + i0 = be32_to_cpup(q->qpage + idx); + idx = (idx + 1) & q->msk; + i1 = be32_to_cpup(q->qpage + idx); + seq_printf(m, "T=%d %08x %08x...\n", q->toggle, + i0, i1); + } + if (xc->esc_virq[i]) { + struct irq_data *d = irq_get_irq_data(xc->esc_virq[i]); + struct xive_irq_data *xd = + irq_data_get_irq_handler_data(d); + u64 pq = xive_vm_esb_load(xd, XIVE_ESB_GET); + + seq_printf(m, "E:%c%c I(%d:%llx:%llx)", + (pq & XIVE_ESB_VAL_P) ? 'P' : 'p', + (pq & XIVE_ESB_VAL_Q) ? 'Q' : 'q', + xc->esc_virq[i], pq, xd->eoi_page); + seq_puts(m, "\n"); + } + } + return 0; +} static int xive_debug_show(struct seq_file *m, void *private) { @@ -1846,7 +1885,6 @@ static int xive_debug_show(struct seq_file *m, void *private) kvm_for_each_vcpu(i, vcpu, kvm) { struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; - unsigned int i; if (!xc) continue; @@ -1856,33 +1894,8 @@ static int xive_debug_show(struct seq_file *m, void *private) xc->server_num, xc->cppr, xc->hw_cppr, xc->mfrr, xc->pending, xc->stat_rm_h_xirr, xc->stat_vm_h_xirr); - for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { - struct xive_q *q = &xc->queues[i]; - u32 i0, i1, idx; - if (!q->qpage && !xc->esc_virq[i]) - continue; - - seq_printf(m, " [q%d]: ", i); - - if (q->qpage) { - idx = q->idx; - i0 = be32_to_cpup(q->qpage + idx); - idx = (idx + 1) & q->msk; - i1 = be32_to_cpup(q->qpage + idx); - seq_printf(m, "T=%d %08x %08x... \n", q->toggle, i0, i1); - } - if (xc->esc_virq[i]) { - struct irq_data *d = irq_get_irq_data(xc->esc_virq[i]); - struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); - u64 pq = xive_vm_esb_load(xd, XIVE_ESB_GET); - seq_printf(m, "E:%c%c I(%d:%llx:%llx)", - (pq & XIVE_ESB_VAL_P) ? 'P' : 'p', - (pq & XIVE_ESB_VAL_Q) ? 'Q' : 'q', - xc->esc_virq[i], pq, xd->eoi_page); - seq_printf(m, "\n"); - } - } + kvmppc_xive_debug_show_queues(m, vcpu); t_rm_h_xirr += xc->stat_rm_h_xirr; t_rm_h_ipoll += xc->stat_rm_h_ipoll; diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index a08ae6fd4c51..10c4aa5cd010 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -248,5 +248,16 @@ extern int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server, extern int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr); extern int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr); +/* + * Common Xive routines for XICS-over-XIVE and XIVE native + */ +struct kvmppc_xive_src_block *kvmppc_xive_create_src_block( + struct kvmppc_xive *xive, int irq); +void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb); +int kvmppc_xive_select_target(struct kvm *kvm, u32 *server, u8 prio); +void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu); +int kvmppc_xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio); +int kvmppc_xive_debug_show_queues(struct seq_file *m, struct kvm_vcpu *vcpu); + #endif /* CONFIG_KVM_XICS */ #endif /* _KVM_PPC_BOOK3S_XICS_H */ From patchwork Mon Apr 23 16:43:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903038 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCPF4T4Pz9s02 for ; Tue, 24 Apr 2018 02:59:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755473AbeDWQ7o (ORCPT ); Mon, 23 Apr 2018 12:59:44 -0400 Received: from 15.mo3.mail-out.ovh.net ([87.98.150.177]:37559 "EHLO 15.mo3.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754788AbeDWQ7n (ORCPT ); Mon, 23 Apr 2018 12:59:43 -0400 X-Greylist: delayed 586 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 12:59:43 EDT Received: from player737.ha.ovh.net (unknown [10.109.122.22]) by mo3.mail-out.ovh.net (Postfix) with ESMTP id CB83D1AE74B for ; Mon, 23 Apr 2018 18:44:22 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 97BBAE0099; Mon, 23 Apr 2018 18:44:16 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 05/16] KVM: PPC: Book3S HV: add a new KVM device for the XIVE native exploitation mode Date: Mon, 23 Apr 2018 18:43:30 +0200 Message-Id: <20180423164341.15767-6-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 965459170359348183 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org This is the basic framework for the new KVM device supporting the XIVE native exploitation mode. The user interface exposes a new capability and a new KVM device defines to be used by QEMU. Internally, the interface to the new KVM device is protected with a new interrupt mode: KVMPPC_IRQ_XIVE. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/kvm_host.h | 2 + arch/powerpc/include/asm/kvm_ppc.h | 21 +++ arch/powerpc/kvm/Makefile | 2 +- arch/powerpc/kvm/book3s.c | 7 +- arch/powerpc/kvm/book3s_xive.h | 3 + arch/powerpc/kvm/book3s_xive_native.c | 338 ++++++++++++++++++++++++++++++++++ arch/powerpc/kvm/powerpc.c | 30 +++ include/uapi/linux/kvm.h | 3 + 8 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/kvm/book3s_xive_native.c diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 6b69d7999381..ab9268ca4ca3 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -211,6 +211,7 @@ extern struct kvm_device_ops kvm_xics_ops; struct kvmppc_xive; struct kvmppc_xive_vcpu; extern struct kvm_device_ops kvm_xive_ops; +extern struct kvm_device_ops kvm_xive_native_ops; struct kvmppc_passthru_irqmap; @@ -431,6 +432,7 @@ struct kvmppc_passthru_irqmap { #define KVMPPC_IRQ_DEFAULT 0 #define KVMPPC_IRQ_MPIC 1 #define KVMPPC_IRQ_XICS 2 /* Includes a XIVE option */ +#define KVMPPC_IRQ_XIVE 3 /* XIVE native exploitation mode */ #define MMIO_HPTE_CACHE_SIZE 4 diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 23cfaef9544e..bacbe4aaa357 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -582,6 +582,18 @@ extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval); extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, bool line_status); + +static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.irq_type == KVMPPC_IRQ_XIVE; +} + +extern int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, + struct kvm_vcpu *vcpu, u32 cpu); +extern int kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu); +extern void kvmppc_xive_native_init_module(void); +extern void kvmppc_xive_native_exit_module(void); + #else static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority) { return -1; } @@ -604,6 +616,15 @@ static inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { retur static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, bool line_status) { return -ENODEV; } + +static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu) + { return 0; } +static inline int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, + struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY} +static inline int kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) { return 0; } +static inline void kvmppc_xive_native_init_module(void) { } +static inline void kvmppc_xive_native_exit_module(void) { } + #endif /* CONFIG_KVM_XIVE */ /* diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 85ba80de7133..a9cc91b528bf 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -90,7 +90,7 @@ endif kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ book3s_xics.o -kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o +kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o book3s_xive_native.o kvm-book3s_64-objs-$(CONFIG_SPAPR_TCE_IOMMU) += book3s_64_vio.o kvm-book3s_64-module-objs := \ diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 97d4a112648f..19c0187cada3 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -1021,7 +1021,10 @@ static int kvmppc_book3s_init(void) #ifdef CONFIG_KVM_XIVE if (xive_enabled()) { kvmppc_xive_init_module(); + kvmppc_xive_native_init_module(); kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS); + kvm_register_device_ops(&kvm_xive_native_ops, + KVM_DEV_TYPE_XIVE); } else #endif kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS); @@ -1032,8 +1035,10 @@ static int kvmppc_book3s_init(void) static void kvmppc_book3s_exit(void) { #ifdef CONFIG_KVM_XICS - if (xive_enabled()) + if (xive_enabled()) { kvmppc_xive_exit_module(); + kvmppc_xive_native_exit_module(); + } #endif #ifdef CONFIG_KVM_BOOK3S_32_HANDLER kvmppc_book3s_exit_pr(); diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index 10c4aa5cd010..5f22415520b4 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -12,6 +12,9 @@ #ifdef CONFIG_KVM_XICS #include "book3s_xics.h" +#define KVMPPC_XIVE_FIRST_IRQ 0 +#define KVMPPC_XIVE_NR_IRQS KVMPPC_XICS_NR_IRQS + /* * State for one guest irq source. * diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c new file mode 100644 index 000000000000..58f272f56c99 --- /dev/null +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2017-2018, IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "xive-kvm: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "book3s_xive.h" + +static void 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; + } +} + +int kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + int i; + + pr_devel("native_cleanup_vcpu(cpu=%d)\n", xc->server_num); + + if (!kvmppc_xive_enabled(vcpu)) + return -EPERM; + + if (!xc) + return -ENOENT; + + /* Ensure no interrupt is still routed to that VP */ + xc->valid = false; + kvmppc_xive_disable_vcpu_interrupts(vcpu); + + /* Disable the VP */ + xive_native_disable_vp(xc->vp_id); + + /* Free the queues & associated interrupts */ + for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { + /* Free the escalation irq */ + if (xc->esc_virq[i]) { + 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; + } + + /* Free the queue */ + 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; + return 0; +} + +int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, + struct kvm_vcpu *vcpu, u32 cpu) +{ + struct kvmppc_xive *xive = dev->private; + struct kvmppc_xive_vcpu *xc; + int rc; + + pr_devel("native_connect_vcpu(cpu=%d)\n", cpu); + + 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) + return -EBUSY; + if (kvmppc_xive_find_server(vcpu->kvm, cpu)) { + pr_devel("Duplicate !\n"); + return -EEXIST; + } + if (cpu >= KVM_MAX_VCPUS) { + pr_devel("Out of bounds !\n"); + return -EINVAL; + } + xc = kzalloc(sizeof(*xc), GFP_KERNEL); + if (!xc) + return -ENOMEM; + + mutex_lock(&vcpu->kvm->lock); + vcpu->arch.xive_vcpu = xc; + xc->xive = xive; + xc->vcpu = vcpu; + xc->server_num = cpu; + xc->vp_id = xive->vp_base + cpu; + xc->valid = true; + + 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 queues ? */ + +bail: + vcpu->arch.irq_type = KVMPPC_IRQ_XIVE; + mutex_unlock(&vcpu->kvm->lock); + if (rc) + kvmppc_xive_native_cleanup_vcpu(vcpu); + + return rc; +} + +static int kvmppc_xive_native_set_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +static int kvmppc_xive_native_get_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +static int kvmppc_xive_native_has_attr(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +static void kvmppc_xive_native_free(struct kvm_device *dev) +{ + struct kvmppc_xive *xive = dev->private; + struct kvm *kvm = xive->kvm; + int i; + + debugfs_remove(xive->dentry); + + pr_devel("Destroying xive native for partition\n"); + + if (kvm) + kvm->arch.xive = NULL; + + /* Mask and free interrupts */ + for (i = 0; i <= xive->max_sbid; i++) { + if (xive->src_blocks[i]) + kvmppc_xive_free_sources(xive->src_blocks[i]); + kfree(xive->src_blocks[i]); + xive->src_blocks[i] = NULL; + } + + if (xive->vp_base != XIVE_INVALID_VP) + xive_native_free_vp_block(xive->vp_base); + + kfree(xive); + kfree(dev); +} + +static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type) +{ + struct kvmppc_xive *xive; + struct kvm *kvm = dev->kvm; + int ret = 0; + + pr_devel("Creating xive native for partition\n"); + + if (kvm->arch.xive) + return -EEXIST; + + xive = kzalloc(sizeof(*xive), GFP_KERNEL); + if (!xive) + return -ENOMEM; + + dev->private = xive; + xive->dev = dev; + xive->kvm = kvm; + kvm->arch.xive = xive; + + /* We use the default queue size set by the host */ + xive->q_order = xive_native_default_eq_shift(); + if (xive->q_order < PAGE_SHIFT) + xive->q_page_order = 0; + else + xive->q_page_order = xive->q_order - PAGE_SHIFT; + + /* Allocate a bunch of VPs */ + xive->vp_base = xive_native_alloc_vp_block(KVM_MAX_VCPUS); + pr_devel("VP_Base=%x\n", xive->vp_base); + + if (xive->vp_base == XIVE_INVALID_VP) + ret = -ENOMEM; + + xive->single_escalation = xive_native_has_single_escalation(); + + if (ret) + kfree(xive); + + return ret; +} + +static int xive_native_debug_show(struct seq_file *m, void *private) +{ + struct kvmppc_xive *xive = m->private; + struct kvm *kvm = xive->kvm; + struct kvm_vcpu *vcpu; + unsigned int i; + + if (!kvm) + return 0; + + 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; + + seq_printf(m, "cpu server %#x NSR=%02x CPPR=%02x IBP=%02x PIPR=%02x w01=%016llx w2=%08x\n", + xc->server_num, + 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); + + /* TODO: hcalls statistics */ + } + + 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, + .destroy = kvmppc_xive_native_free, + .set_attr = kvmppc_xive_native_set_attr, + .get_attr = kvmppc_xive_native_get_attr, + .has_attr = kvmppc_xive_native_has_attr, +}; + +void kvmppc_xive_native_init_module(void) +{ + ; +} + +void kvmppc_xive_native_exit_module(void) +{ + ; +} diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 52c205373986..42eb75e43d6e 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -552,6 +552,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) #ifdef CONFIG_KVM_XICS case KVM_CAP_IRQ_XICS: #endif +#ifdef CONFIG_KVM_XIVE + case KVM_CAP_PPC_IRQ_XIVE: +#endif case KVM_CAP_PPC_GET_CPU_CHAR: r = 1; break; @@ -731,6 +734,9 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) else kvmppc_xics_free_icp(vcpu); break; + case KVMPPC_IRQ_XIVE: + kvmppc_xive_native_cleanup_vcpu(vcpu); + break; } kvmppc_core_vcpu_free(vcpu); @@ -1714,6 +1720,30 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, break; } #endif /* CONFIG_KVM_XICS */ +#ifdef CONFIG_KVM_XIVE + case KVM_CAP_PPC_IRQ_XIVE: { + struct fd f; + struct kvm_device *dev; + + r = -EBADF; + f = fdget(cap->args[0]); + if (!f.file) + break; + + r = -ENXIO; + if (!xive_enabled()) + break; + + r = -EPERM; + dev = kvm_device_from_filp(f.file); + if (dev) + r = kvmppc_xive_native_connect_vcpu(dev, vcpu, + cap->args[1]); + + fdput(f); + break; + } +#endif /* CONFIG_KVM_XIVE */ #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE case KVM_CAP_PPC_FWNMI: r = -EINVAL; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 7b26d4b0b052..cda8b85f4849 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -936,6 +936,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_GET_CPU_CHAR 151 #define KVM_CAP_S390_BPB 152 #define KVM_CAP_GET_MSR_FEATURES 153 +#define KVM_CAP_PPC_IRQ_XIVE 154 #ifdef KVM_CAP_IRQ_ROUTING @@ -1159,6 +1160,8 @@ enum kvm_device_type { #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_ITS, #define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS + KVM_DEV_TYPE_XIVE, +#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_MAX, }; From patchwork Mon Apr 23 16:43:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903041 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCPy3d8dz9s06 for ; Tue, 24 Apr 2018 03:00:22 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755432AbeDWRAW (ORCPT ); Mon, 23 Apr 2018 13:00:22 -0400 Received: from 17.mo5.mail-out.ovh.net ([46.105.56.132]:41839 "EHLO 17.mo5.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754788AbeDWRAV (ORCPT ); Mon, 23 Apr 2018 13:00:21 -0400 Received: from player737.ha.ovh.net (unknown [10.109.122.36]) by mo5.mail-out.ovh.net (Postfix) with ESMTP id 061401A49C3 for ; Mon, 23 Apr 2018 18:44:28 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id C1471E0099; Mon, 23 Apr 2018 18:44:22 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 06/16] KVM: PPC: Book3S HV: add a SET_SOURCE control to the XIVE native device Date: Mon, 23 Apr 2018 18:43:31 +0200 Message-Id: <20180423164341.15767-7-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 967148021338835927 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org Interrupt sources are simply created at the OPAL level and then MASKED. KVM only needs to know about their type: LSI or MSI. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/uapi/asm/kvm.h | 7 ++ arch/powerpc/kvm/book3s_xive_native.c | 106 +++++++++++++++++++++++++ arch/powerpc/kvm/book3s_xive_native_template.c | 30 +++++++ 3 files changed, 143 insertions(+) create mode 100644 arch/powerpc/kvm/book3s_xive_native_template.c diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 833ed9a16adf..84fde0295939 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -673,4 +673,11 @@ struct kvm_ppc_cpu_char { #define KVM_XICS_PRESENTED (1ULL << 43) #define KVM_XICS_QUEUED (1ULL << 44) +/* POWER9 XIVE Native Interrupt Controller */ +#define KVM_DEV_XIVE_GRP_SOURCES 1 /* 64-bit source attributes */ + +/* Layout of 64-bit XIVE source attribute values */ +#define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) +#define KVM_XIVE_LEVEL_ASSERTED (1ULL << 1) + #endif /* __LINUX_KVM_POWERPC_H */ diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 58f272f56c99..6ebb628462d4 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -34,6 +34,24 @@ #include "book3s_xive.h" +/* + * We still instanciate them here because we use some of the + * generated utility functions as well in this file. + */ +#define XIVE_RUNTIME_CHECKS +#define X_PFX xive_vm_ +#define X_STATIC static +#define X_STAT_PFX stat_vm_ +#define __x_tima xive_tima +#define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_mmio)) +#define __x_trig_page(xd) ((void __iomem *)((xd)->trig_mmio)) +#define __x_writeb __raw_writeb +#define __x_readw __raw_readw +#define __x_readq __raw_readq +#define __x_writeq __raw_writeq + +#include "book3s_xive_native_template.c" + static void xive_native_cleanup_queue(struct kvm_vcpu *vcpu, int prio) { struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; @@ -157,9 +175,90 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, return rc; } +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; + + pr_devel("%s irq=0x%lx\n", __func__, irq); + + if (irq < KVMPPC_XIVE_FIRST_IRQ || irq >= KVMPPC_XIVE_NR_IRQS) + return -ENOENT; + + /* Find the source */ + 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]; + + /* Read user passed data */ + if (get_user(val, ubufp)) { + pr_err("fault getting user info !\n"); + return -EFAULT; + } + + /* + * 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"); + return -ENOMEM; + } + 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); + } + + arch_spin_lock(&sb->lock); + + /* 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; + + arch_spin_unlock(&sb->lock); + + return 0; +} + static int kvmppc_xive_native_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { + struct kvmppc_xive *xive = dev->private; + + switch (attr->group) { + case KVM_DEV_XIVE_GRP_SOURCES: + return kvmppc_xive_native_set_source(xive, attr->attr, + attr->addr); + } return -ENXIO; } @@ -172,6 +271,13 @@ static int kvmppc_xive_native_get_attr(struct kvm_device *dev, static int kvmppc_xive_native_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { + switch (attr->group) { + case KVM_DEV_XIVE_GRP_SOURCES: + if (attr->attr >= KVMPPC_XIVE_FIRST_IRQ && + attr->attr < KVMPPC_XIVE_NR_IRQS) + return 0; + break; + } return -ENXIO; } diff --git a/arch/powerpc/kvm/book3s_xive_native_template.c b/arch/powerpc/kvm/book3s_xive_native_template.c new file mode 100644 index 000000000000..2a4cf4116b11 --- /dev/null +++ b/arch/powerpc/kvm/book3s_xive_native_template.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2018, IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +/* File to be included by other .c files */ + +#define XGLUE(a, b) a##b +#define GLUE(a, b) XGLUE(a, b) + +/* + * TODO: introduce a common template file with the XIVE native layer + * and the XICS-on-XIVE glue for the utility functions + */ +static u8 GLUE(X_PFX, esb_load)(struct xive_irq_data *xd, u32 offset) +{ + u64 val; + + if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG) + offset |= offset << 4; + + val = __x_readq(__x_eoi_page(xd) + offset); +#ifdef __LITTLE_ENDIAN__ + val >>= 64-8; +#endif + return (u8)val; +} From patchwork Mon Apr 23 16:43:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903026 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCBk2ss0z9s0n for ; Tue, 24 Apr 2018 02:50:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755783AbeDWQuh (ORCPT ); Mon, 23 Apr 2018 12:50:37 -0400 Received: from 1.mo6.mail-out.ovh.net ([46.105.56.136]:52545 "EHLO 1.mo6.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755643AbeDWQuh (ORCPT ); Mon, 23 Apr 2018 12:50:37 -0400 X-Greylist: delayed 360 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 12:50:37 EDT Received: from player737.ha.ovh.net (unknown [10.109.105.78]) by mo6.mail-out.ovh.net (Postfix) with ESMTP id 35C06156C29 for ; Mon, 23 Apr 2018 18:44:35 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id ED0FBE00A8; Mon, 23 Apr 2018 18:44:28 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 07/16] KVM: PPC: Book3S HV: add a GET_ESB_FD control to the XIVE native device Date: Mon, 23 Apr 2018 18:43:32 +0200 Message-Id: <20180423164341.15767-8-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 969118345481653207 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org This will let the guest create a memory mapping to expose the ESB MMIO regions used to control the interrupt sources, to trigger events, to EOI or to turn off the sources. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/uapi/asm/kvm.h | 2 + arch/powerpc/kvm/book3s_xive_native.c | 88 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 84fde0295939..cf54fad1faf6 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -675,6 +675,8 @@ struct kvm_ppc_cpu_char { /* POWER9 XIVE Native Interrupt Controller */ #define KVM_DEV_XIVE_GRP_SOURCES 1 /* 64-bit source attributes */ +#define KVM_DEV_XIVE_GRP_CTRL 2 +#define KVM_DEV_XIVE_GET_ESB_FD 1 /* Layout of 64-bit XIVE source attribute values */ #define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 6ebb628462d4..395298c5fca8 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -249,6 +249,78 @@ static int kvmppc_xive_native_set_source(struct kvmppc_xive *xive, long irq, return 0; } +static int xive_native_esb_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + struct kvmppc_xive *xive = vma->vm_file->private_data; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct xive_irq_data *xd; + u32 hw_num; + u16 src; + unsigned long irq, pfn; + + /* There are two pages (trigger and EOI) per IRQ */ + irq = vmf->pgoff / 2; + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_err("%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 page is the trigger page */ + if (vmf->pgoff % 2) + pfn = xd->eoi_page >> PAGE_SHIFT; + else + pfn = xd->trig_page >> PAGE_SHIFT; + + arch_spin_unlock(&sb->lock); + + vm_insert_pfn(vma, vmf->address, pfn); + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct xive_native_esb_vmops = { + .fault = xive_native_esb_fault, +}; + +static int xive_native_esb_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long len = vma->vm_end - vma->vm_start; + + /* There are two pages (trigger and EOI) per IRQ */ + if ((len >> PAGE_SHIFT) >= KVMPPC_XIVE_NR_IRQS * 2) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_PFNMAP; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_ops = &xive_native_esb_vmops; + return 0; +} + +static const struct file_operations xive_native_esb_fops = { + .mmap = xive_native_esb_mmap, +}; + +static int kvmppc_xive_native_get_esb_fd(struct kvmppc_xive *xive, u64 addr) +{ + u64 __user *ubufp = (u64 __user *) addr; + int ret; + + ret = anon_inode_getfd("esb", &xive_native_esb_fops, xive, + O_RDWR | O_CLOEXEC); + if (ret < 0) + return ret; + + return put_user(ret, ubufp); +} + static int kvmppc_xive_native_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { @@ -265,6 +337,16 @@ static int kvmppc_xive_native_set_attr(struct kvm_device *dev, static int kvmppc_xive_native_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { + struct kvmppc_xive *xive = dev->private; + + switch (attr->group) { + case KVM_DEV_XIVE_GRP_CTRL: + switch (attr->attr) { + case KVM_DEV_XIVE_GET_ESB_FD: + return kvmppc_xive_native_get_esb_fd(xive, attr->addr); + } + break; + } return -ENXIO; } @@ -277,6 +359,12 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev, attr->attr < KVMPPC_XIVE_NR_IRQS) return 0; break; + case KVM_DEV_XIVE_GRP_CTRL: + switch (attr->attr) { + case KVM_DEV_XIVE_GET_ESB_FD: + return 0; + } + break; } return -ENXIO; } From patchwork Mon Apr 23 16:43:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903023 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCBD25FZz9s08 for ; Tue, 24 Apr 2018 02:50:12 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755643AbeDWQuL (ORCPT ); Mon, 23 Apr 2018 12:50:11 -0400 Received: from 10.mo69.mail-out.ovh.net ([46.105.73.241]:35699 "EHLO 10.mo69.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755779AbeDWQuI (ORCPT ); Mon, 23 Apr 2018 12:50:08 -0400 X-Greylist: delayed 326 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 12:50:08 EDT Received: from player737.ha.ovh.net (unknown [10.109.105.122]) by mo69.mail-out.ovh.net (Postfix) with ESMTP id 4CCA9126FC for ; Mon, 23 Apr 2018 18:44:41 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 21854E0089; Mon, 23 Apr 2018 18:44:35 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 08/16] KVM: PPC: Book3S HV: add a GET_TIMA_FD control to XIVE native device Date: Mon, 23 Apr 2018 18:43:33 +0200 Message-Id: <20180423164341.15767-9-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 970807196780825559 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org This will let the guest create a memory mapping to expose the XIVE MMIO region (TIMA) used for interrupt management at the CPU level. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/uapi/asm/kvm.h | 1 + arch/powerpc/kvm/book3s_xive_native.c | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index cf54fad1faf6..c564ee892cac 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -677,6 +677,7 @@ struct kvm_ppc_cpu_char { #define KVM_DEV_XIVE_GRP_SOURCES 1 /* 64-bit source attributes */ #define KVM_DEV_XIVE_GRP_CTRL 2 #define KVM_DEV_XIVE_GET_ESB_FD 1 +#define KVM_DEV_XIVE_GET_TIMA_FD 2 /* Layout of 64-bit XIVE source attribute values */ #define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 395298c5fca8..cfce8ba327ca 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -321,6 +321,52 @@ static int kvmppc_xive_native_get_esb_fd(struct kvmppc_xive *xive, u64 addr) return put_user(ret, ubufp); } +static int xive_native_tima_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + + if (vmf->pgoff) + return VM_FAULT_SIGBUS; + + vm_insert_pfn(vma, vmf->address, (unsigned long) + local_paca->kvm_hstate.xive_tima_phys >> PAGE_SHIFT); + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct xive_native_tima_vmops = { + .fault = xive_native_tima_fault, +}; + +static int xive_native_tima_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long len = vma->vm_end - vma->vm_start; + + if (len != (1 << PAGE_SHIFT)) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_PFNMAP; + vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot); + vma->vm_ops = &xive_native_tima_vmops; + return 0; +} + +static const struct file_operations xive_native_tima_fops = { + .mmap = xive_native_tima_mmap, +}; + +static int kvmppc_xive_native_get_tima_fd(struct kvmppc_xive *xive, u64 addr) +{ + u64 __user *ubufp = (u64 __user *) addr; + int ret; + + ret = anon_inode_getfd("tima", &xive_native_tima_fops, xive, + O_RDWR | O_CLOEXEC); + if (ret < 0) + return ret; + + return put_user(ret, ubufp); +} + static int kvmppc_xive_native_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { @@ -344,6 +390,8 @@ static int kvmppc_xive_native_get_attr(struct kvm_device *dev, switch (attr->attr) { case KVM_DEV_XIVE_GET_ESB_FD: return kvmppc_xive_native_get_esb_fd(xive, attr->addr); + case KVM_DEV_XIVE_GET_TIMA_FD: + return kvmppc_xive_native_get_tima_fd(xive, attr->addr); } break; } @@ -362,6 +410,7 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev, case KVM_DEV_XIVE_GRP_CTRL: switch (attr->attr) { case KVM_DEV_XIVE_GET_ESB_FD: + case KVM_DEV_XIVE_GET_TIMA_FD: return 0; } break; From patchwork Mon Apr 23 16:43:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903077 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCsZ13b2z9s0W for ; Tue, 24 Apr 2018 03:20:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755644AbeDWRUt (ORCPT ); Mon, 23 Apr 2018 13:20:49 -0400 Received: from 13.mo6.mail-out.ovh.net ([188.165.56.124]:33786 "EHLO 13.mo6.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755628AbeDWRUs (ORCPT ); Mon, 23 Apr 2018 13:20:48 -0400 X-Greylist: delayed 1197 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 13:20:48 EDT Received: from player737.ha.ovh.net (unknown [10.109.105.98]) by mo6.mail-out.ovh.net (Postfix) with ESMTP id 947B8157E62 for ; Mon, 23 Apr 2018 18:44:47 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 4A6D5E0089; Mon, 23 Apr 2018 18:44:41 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 09/16] KVM: PPC: Book3S HV: add a VC_BASE control to the XIVE native device Date: Mon, 23 Apr 2018 18:43:34 +0200 Message-Id: <20180423164341.15767-10-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 972496044610325463 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The ESB MMIO region controls the interrupt sources of the guest. QEMU will query an fd (GET_ESB_FD ioctl) and map this region at a specific address for the guest to use and the guest will obtain this information using the H_INT_GET_SOURCE_INFO hcall. To inform KVM of the address setting used by QEMU, let's add a VC_BASE control to the KVM XIVE device Signed-off-by: Cédric Le Goater --- arch/powerpc/include/uapi/asm/kvm.h | 1 + arch/powerpc/kvm/book3s_xive.h | 3 +++ arch/powerpc/kvm/book3s_xive_native.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index c564ee892cac..6e120129dfe6 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -678,6 +678,7 @@ struct kvm_ppc_cpu_char { #define KVM_DEV_XIVE_GRP_CTRL 2 #define KVM_DEV_XIVE_GET_ESB_FD 1 #define KVM_DEV_XIVE_GET_TIMA_FD 2 +#define KVM_DEV_XIVE_VC_BASE 3 /* Layout of 64-bit XIVE source attribute values */ #define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index 5f22415520b4..ae4a670eea63 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -125,6 +125,9 @@ struct kvmppc_xive { /* Flags */ u8 single_escalation; + + /* VC base address for ESBs */ + u64 vc_base; }; #define KVMPPC_XIVE_Q_COUNT 8 diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index cfce8ba327ca..1cc58afe3103 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -249,6 +249,25 @@ static int kvmppc_xive_native_set_source(struct kvmppc_xive *xive, long irq, return 0; } +static int kvmppc_xive_native_set_vc_base(struct kvmppc_xive *xive, u64 addr) +{ + u64 __user *ubufp = (u64 __user *) addr; + + if (get_user(xive->vc_base, ubufp)) + return -EFAULT; + return 0; +} + +static int kvmppc_xive_native_get_vc_base(struct kvmppc_xive *xive, u64 addr) +{ + u64 __user *ubufp = (u64 __user *) addr; + + if (put_user(xive->vc_base, ubufp)) + return -EFAULT; + + return 0; +} + static int xive_native_esb_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; @@ -376,6 +395,12 @@ static int kvmppc_xive_native_set_attr(struct kvm_device *dev, case KVM_DEV_XIVE_GRP_SOURCES: return kvmppc_xive_native_set_source(xive, attr->attr, attr->addr); + case KVM_DEV_XIVE_GRP_CTRL: + switch (attr->attr) { + case KVM_DEV_XIVE_VC_BASE: + return kvmppc_xive_native_set_vc_base(xive, attr->addr); + } + break; } return -ENXIO; } @@ -392,6 +417,8 @@ static int kvmppc_xive_native_get_attr(struct kvm_device *dev, return kvmppc_xive_native_get_esb_fd(xive, attr->addr); case KVM_DEV_XIVE_GET_TIMA_FD: return kvmppc_xive_native_get_tima_fd(xive, attr->addr); + case KVM_DEV_XIVE_VC_BASE: + return kvmppc_xive_native_get_vc_base(xive, attr->addr); } break; } @@ -411,6 +438,7 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev, switch (attr->attr) { case KVM_DEV_XIVE_GET_ESB_FD: case KVM_DEV_XIVE_GET_TIMA_FD: + case KVM_DEV_XIVE_VC_BASE: return 0; } break; @@ -446,6 +474,11 @@ static void kvmppc_xive_native_free(struct kvm_device *dev) kfree(dev); } +/* + * ESB MMIO address of chip 0 + */ +#define XIVE_VC_BASE 0x0006010000000000ull + static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type) { struct kvmppc_xive *xive; @@ -480,6 +513,8 @@ static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type) if (xive->vp_base == XIVE_INVALID_VP) ret = -ENOMEM; + xive->vc_base = XIVE_VC_BASE; + xive->single_escalation = xive_native_has_single_escalation(); if (ret) From patchwork Mon Apr 23 16:43:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903078 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCxy698cz9s0n for ; Tue, 24 Apr 2018 03:24:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932122AbeDWRYh (ORCPT ); Mon, 23 Apr 2018 13:24:37 -0400 Received: from 15.mo1.mail-out.ovh.net ([188.165.38.232]:46953 "EHLO 15.mo1.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932110AbeDWRYh (ORCPT ); Mon, 23 Apr 2018 13:24:37 -0400 X-Greylist: delayed 2030 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 13:24:37 EDT Received: from player737.ha.ovh.net (unknown [10.109.105.60]) by mo1.mail-out.ovh.net (Postfix) with ESMTP id AD550EC45C for ; Mon, 23 Apr 2018 18:44:53 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 72D15E0089; Mon, 23 Apr 2018 18:44:47 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 10/16] KVM: PPC: Book3S HV: add a EISN attribute to kvmppc_xive_irq_state Date: Mon, 23 Apr 2018 18:43:35 +0200 Message-Id: <20180423164341.15767-11-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 974184895945542615 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The Effective IRQ Source Number is the number pushed in the event queue that the guest OS will dispatch internally. Signed-off-by: Cédric Le Goater --- arch/powerpc/kvm/book3s_xive.c | 1 + arch/powerpc/kvm/book3s_xive.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index 10e2ceae7b04..abb4ae5c5b91 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -1447,6 +1447,7 @@ struct kvmppc_xive_src_block *kvmppc_xive_create_src_block( for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) { sb->irq_state[i].number = (bid << KVMPPC_XICS_ICS_SHIFT) | i; + sb->irq_state[i].eisn = 0; sb->irq_state[i].guest_priority = MASKED; sb->irq_state[i].saved_priority = MASKED; sb->irq_state[i].act_priority = MASKED; diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index ae4a670eea63..67e07b41061d 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -57,6 +57,9 @@ struct kvmppc_xive_irq_state { bool saved_p; bool saved_q; u8 saved_scan_prio; + + /* Xive native */ + u32 eisn; /* Guest Effective IRQ number */ }; /* Select the "right" interrupt (IPI vs. passthrough) */ From patchwork Mon Apr 23 16:43:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903043 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCQk2zNGz9s02 for ; Tue, 24 Apr 2018 03:01:02 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755619AbeDWRBC (ORCPT ); Mon, 23 Apr 2018 13:01:02 -0400 Received: from 11.mo4.mail-out.ovh.net ([46.105.34.195]:50662 "EHLO 11.mo4.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755603AbeDWRBA (ORCPT ); Mon, 23 Apr 2018 13:01:00 -0400 X-Greylist: delayed 26103 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 13:00:59 EDT Received: from player737.ha.ovh.net (unknown [10.109.120.70]) by mo4.mail-out.ovh.net (Postfix) with ESMTP id DCB921683AE for ; Mon, 23 Apr 2018 18:44:59 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 9B86CE0091; Mon, 23 Apr 2018 18:44:53 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 11/16] KVM: PPC: Book3S HV: add support for the XIVE native exploitation mode hcalls Date: Mon, 23 Apr 2018 18:43:36 +0200 Message-Id: <20180423164341.15767-12-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 975873746197318615 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The XIVE native exploitation mode specs define a set of Hypervisor calls to configure the sources and the event queues : - H_INT_GET_SOURCE_INFO used to obtain the address of the MMIO page of the Event State Buffer (PQ bits) entry associated with the source. - H_INT_SET_SOURCE_CONFIG assigns a source to a "target". - H_INT_GET_SOURCE_CONFIG determines which "target" and "priority" is assigned to a source - H_INT_GET_QUEUE_INFO returns the address of the notification management page associated with the specified "target" and "priority". - H_INT_SET_QUEUE_CONFIG sets or resets the event queue for a given "target" and "priority". It is also used to set the notification configuration associated with the queue, only unconditional notification is supported for the moment. Reset is performed with a queue size of 0 and queueing is disabled in that case. - H_INT_GET_QUEUE_CONFIG returns the queue settings for a given "target" and "priority". - H_INT_RESET resets all of the guest's internal interrupt structures to their initial state, losing all configuration set via the hcalls H_INT_SET_SOURCE_CONFIG and H_INT_SET_QUEUE_CONFIG. - H_INT_SYNC issue a synchronisation on a source to make sure all notifications have reached their queue. Calls that still need to be addressed : H_INT_SET_OS_REPORTING_LINE H_INT_GET_OS_REPORTING_LINE Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/kvm_ppc.h | 43 +++ arch/powerpc/kvm/Makefile | 2 + arch/powerpc/kvm/book3s_hv.c | 31 +++ arch/powerpc/kvm/book3s_hv_builtin.c | 196 ++++++++++++++ arch/powerpc/kvm/book3s_hv_rm_xive_native.c | 47 ++++ arch/powerpc/kvm/book3s_hv_rmhandlers.S | 52 ++++ arch/powerpc/kvm/book3s_xive.h | 54 ++++ arch/powerpc/kvm/book3s_xive_native.c | 322 ++++++++++++++++++++++- arch/powerpc/kvm/book3s_xive_native_template.c | 351 +++++++++++++++++++++++++ 9 files changed, 1096 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/kvm/book3s_hv_rm_xive_native.c diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index bacbe4aaa357..b5fceb4d7776 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -593,6 +593,7 @@ extern int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, extern int kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu); extern void kvmppc_xive_native_init_module(void); extern void kvmppc_xive_native_exit_module(void); +extern int kvmppc_xive_hcall(struct kvm_vcpu *vcpu, u32 cmd); #else static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, @@ -624,6 +625,8 @@ static inline int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, static inline int kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) { return 0; } static inline void kvmppc_xive_native_init_module(void) { } static inline void kvmppc_xive_native_exit_module(void) { } +static inline int kvmppc_xive_hcall(struct kvm_vcpu *vcpu, u32 cmd) + { return 0; } #endif /* CONFIG_KVM_XIVE */ @@ -671,6 +674,46 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); +int kvmppc_rm_h_int_get_source_info(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +int kvmppc_rm_h_int_set_source_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn, + unsigned long target, + unsigned long priority, + unsigned long eisn); +int kvmppc_rm_h_int_get_source_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +int kvmppc_rm_h_int_get_queue_info(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +int kvmppc_rm_h_int_set_queue_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority, + unsigned long qpage, + unsigned long qsize); +int kvmppc_rm_h_int_get_queue_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +int kvmppc_rm_h_int_set_os_reporting_line(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long reportingline); +int kvmppc_rm_h_int_get_os_reporting_line(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long reportingline); +int kvmppc_rm_h_int_esb(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn, unsigned long offset, + unsigned long data); +int kvmppc_rm_h_int_sync(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn); +int kvmppc_rm_h_int_reset(struct kvm_vcpu *vcpu, unsigned long flag); + /* * Host-side operations we want to set up while running in real * mode in the guest operating on the xics. diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index a9cc91b528bf..c6dd7a3ba7aa 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -76,6 +76,8 @@ kvm-hv-y += \ kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \ book3s_hv_rm_xics.o book3s_hv_rm_xive.o +kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XIVE) += \ + book3s_hv_rm_xive_native.o ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 4863ab81f663..805525d6d240 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -882,6 +882,24 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) break; } return RESUME_HOST; + + case H_INT_GET_SOURCE_INFO: + case H_INT_SET_SOURCE_CONFIG: + case H_INT_GET_SOURCE_CONFIG: + case H_INT_GET_QUEUE_INFO: + case H_INT_SET_QUEUE_CONFIG: + case H_INT_GET_QUEUE_CONFIG: + case H_INT_SET_OS_REPORTING_LINE: + case H_INT_GET_OS_REPORTING_LINE: + case H_INT_ESB: + case H_INT_SYNC: + case H_INT_RESET: + if (kvmppc_xive_enabled(vcpu)) { + ret = kvmppc_xive_hcall(vcpu, req); + break; + } + return RESUME_HOST; + case H_PUT_TCE: ret = kvmppc_h_put_tce(vcpu, kvmppc_get_gpr(vcpu, 4), kvmppc_get_gpr(vcpu, 5), @@ -4261,6 +4279,19 @@ static unsigned int default_hcall_list[] = { H_XIRR, H_XIRR_X, #endif +#ifdef CONFIG_KVM_XIVE + H_INT_GET_SOURCE_INFO, + H_INT_SET_SOURCE_CONFIG, + H_INT_GET_SOURCE_CONFIG, + H_INT_GET_QUEUE_INFO, + H_INT_SET_QUEUE_CONFIG, + H_INT_GET_QUEUE_CONFIG, + H_INT_SET_OS_REPORTING_LINE, + H_INT_GET_OS_REPORTING_LINE, + H_INT_ESB, + H_INT_SYNC, + H_INT_RESET, +#endif 0 }; diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 49a2c7825e04..d90af2ca2d31 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -50,6 +50,42 @@ EXPORT_SYMBOL_GPL(__xive_vm_h_ipi); EXPORT_SYMBOL_GPL(__xive_vm_h_cppr); EXPORT_SYMBOL_GPL(__xive_vm_h_eoi); +int (*__xive_vm_h_int_get_source_info)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +int (*__xive_vm_h_int_get_source_config)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +int (*__xive_vm_h_int_get_queue_info)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +int (*__xive_vm_h_int_get_queue_config)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +int (*__xive_vm_h_int_set_os_reporting_line)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long line); +int (*__xive_vm_h_int_get_os_reporting_line)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long line); +int (*__xive_vm_h_int_esb)(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn, unsigned long offset, + unsigned long data); +int (*__xive_vm_h_int_sync)(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn); + +EXPORT_SYMBOL_GPL(__xive_vm_h_int_get_source_info); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_get_source_config); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_get_queue_info); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_get_queue_config); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_set_os_reporting_line); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_get_os_reporting_line); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_esb); +EXPORT_SYMBOL_GPL(__xive_vm_h_int_sync); + /* * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206) * should be power of 2. @@ -631,6 +667,166 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) } #endif /* CONFIG_KVM_XICS */ +#ifdef CONFIG_KVM_XIVE +int kvmppc_rm_h_int_get_source_info(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_get_source_info(vcpu, flag, lisn); + if (unlikely(!__xive_vm_h_int_get_source_info)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_get_source_info(vcpu, flag, lisn); +} + +int kvmppc_rm_h_int_set_source_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn, + unsigned long target, + unsigned long priority, + unsigned long eisn) +{ + return H_TOO_HARD; +} + +int kvmppc_rm_h_int_get_source_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_get_source_config(vcpu, flag, lisn); + if (unlikely(!__xive_vm_h_int_get_source_config)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_get_source_config(vcpu, flag, lisn); +} + +int kvmppc_rm_h_int_get_queue_info(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_get_queue_info(vcpu, flag, target, + priority); + if (unlikely(!__xive_vm_h_int_get_queue_info)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_get_queue_info(vcpu, flag, target, priority); +} + +int kvmppc_rm_h_int_set_queue_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority, + unsigned long qpage, + unsigned long qsize) +{ + return H_TOO_HARD; +} + +int kvmppc_rm_h_int_get_queue_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_get_queue_config(vcpu, flag, target, + priority); + if (unlikely(!__xive_vm_h_int_get_queue_config)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_get_queue_config(vcpu, flag, target, priority); +} + +int kvmppc_rm_h_int_set_os_reporting_line(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long line) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_set_os_reporting_line(vcpu, flag, line); + if (unlikely(!__xive_vm_h_int_set_os_reporting_line)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_set_os_reporting_line(vcpu, flag, line); +} + +int kvmppc_rm_h_int_get_os_reporting_line(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long line) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_get_os_reporting_line(vcpu, + flag, target, line); + if (unlikely(!__xive_vm_h_int_get_os_reporting_line)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_get_os_reporting_line(vcpu, flag, target, line); +} + +int kvmppc_rm_h_int_esb(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn, unsigned long offset, + unsigned long data) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_esb(vcpu, flag, lisn, offset, data); + if (unlikely(!__xive_vm_h_int_esb)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_esb(vcpu, flag, lisn, offset, data); +} + +int kvmppc_rm_h_int_sync(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn) +{ + if (!kvmppc_xive_enabled(vcpu)) + return H_TOO_HARD; + if (!xive_enabled()) + return H_TOO_HARD; + + if (is_rm()) + return xive_rm_h_int_sync(vcpu, flag, lisn); + if (unlikely(!__xive_vm_h_int_sync)) + return H_NOT_AVAILABLE; + return __xive_vm_h_int_sync(vcpu, flag, lisn); +} + +int kvmppc_rm_h_int_reset(struct kvm_vcpu *vcpu, unsigned long flag) +{ + return H_TOO_HARD; +} +#endif /* CONFIG_KVM_XIVE */ + void kvmppc_bad_interrupt(struct pt_regs *regs) { die("Bad interrupt in KVM entry/exit code", regs, SIGABRT); diff --git a/arch/powerpc/kvm/book3s_hv_rm_xive_native.c b/arch/powerpc/kvm/book3s_hv_rm_xive_native.c new file mode 100644 index 000000000000..0e72a6ae0f07 --- /dev/null +++ b/arch/powerpc/kvm/book3s_hv_rm_xive_native.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "book3s_xive.h" + +/* XXX */ +#include +//#define DBG(fmt...) udbg_printf(fmt) +#define DBG(fmt...) do { } while (0) + +static inline void __iomem *get_tima_phys(void) +{ + return local_paca->kvm_hstate.xive_tima_phys; +} + +#undef XIVE_RUNTIME_CHECKS +#define X_PFX xive_rm_ +#define X_STATIC +#define X_STAT_PFX stat_rm_ +#define __x_tima get_tima_phys() +#define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_page)) +#define __x_trig_page(xd) ((void __iomem *)((xd)->trig_page)) +#define __x_writeb __raw_rm_writeb +#define __x_readw __raw_rm_readw +#define __x_readq __raw_rm_readq +#define __x_writeq __raw_rm_writeq + +#include "book3s_xive_native_template.c" diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index f86a20270e50..fbf7466d252b 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -2477,6 +2477,58 @@ hcall_real_table: .long 0 /* 0x2fc - H_XIRR_X*/ #endif .long DOTSYM(kvmppc_h_random) - hcall_real_table + .long 0 /* 0x304 */ + .long 0 /* 0x308 */ + .long 0 /* 0x30c */ + .long 0 /* 0x310 */ + .long 0 /* 0x314 */ + .long 0 /* 0x318 */ + .long 0 /* 0x31c */ + .long 0 /* 0x320 */ + .long 0 /* 0x324 */ + .long 0 /* 0x328 */ + .long 0 /* 0x32c */ + .long 0 /* 0x330 */ + .long 0 /* 0x334 */ + .long 0 /* 0x338 */ + .long 0 /* 0x33c */ + .long 0 /* 0x340 */ + .long 0 /* 0x344 */ + .long 0 /* 0x348 */ + .long 0 /* 0x34c */ + .long 0 /* 0x350 */ + .long 0 /* 0x354 */ + .long 0 /* 0x358 */ + .long 0 /* 0x35c */ + .long 0 /* 0x360 */ + .long 0 /* 0x364 */ + .long 0 /* 0x368 */ + .long 0 /* 0x36c */ + .long 0 /* 0x370 */ + .long 0 /* 0x374 */ + .long 0 /* 0x378 */ + .long 0 /* 0x37c */ + .long 0 /* 0x380 */ + .long 0 /* 0x384 */ + .long 0 /* 0x388 */ + .long 0 /* 0x38c */ + .long 0 /* 0x390 */ + .long 0 /* 0x394 */ + .long 0 /* 0x398 */ + .long 0 /* 0x39c */ + .long 0 /* 0x3a0 */ + .long 0 /* 0x3a4 */ + .long DOTSYM(kvmppc_rm_h_int_get_source_info) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_set_source_config) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_get_source_config) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_get_queue_info) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_set_queue_config) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_get_queue_config) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_set_os_reporting_line) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_get_os_reporting_line) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_esb) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_sync) - hcall_real_table + .long DOTSYM(kvmppc_rm_h_int_reset) - hcall_real_table .globl hcall_real_table_end hcall_real_table_end: diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index 67e07b41061d..31e598e62589 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -268,5 +268,59 @@ void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu); int kvmppc_xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio); int kvmppc_xive_debug_show_queues(struct seq_file *m, struct kvm_vcpu *vcpu); +int xive_rm_h_int_get_source_info(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +int xive_rm_h_int_get_source_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +int xive_rm_h_int_get_queue_info(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +int xive_rm_h_int_get_queue_config(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +int xive_rm_h_int_set_os_reporting_line(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long reportingline); +int xive_rm_h_int_get_os_reporting_line(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long reportingline); +int xive_rm_h_int_esb(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn, unsigned long offset, + unsigned long data); +int xive_rm_h_int_sync(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn); + +extern int (*__xive_vm_h_int_get_source_info)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +extern int (*__xive_vm_h_int_get_source_config)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long lisn); +extern int (*__xive_vm_h_int_get_queue_info)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +extern int (*__xive_vm_h_int_get_queue_config)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long priority); +extern int (*__xive_vm_h_int_set_os_reporting_line)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long reportingline); +extern int (*__xive_vm_h_int_get_os_reporting_line)(struct kvm_vcpu *vcpu, + unsigned long flag, + unsigned long target, + unsigned long reportingline); +extern int (*__xive_vm_h_int_esb)(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn, unsigned long offset, + unsigned long data); +extern int (*__xive_vm_h_int_sync)(struct kvm_vcpu *vcpu, unsigned long flag, + unsigned long lisn); + #endif /* CONFIG_KVM_XICS */ #endif /* _KVM_PPC_BOOK3S_XICS_H */ diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 1cc58afe3103..789c137f6b31 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -175,6 +175,20 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, return rc; } +static int xive_native_validate_queue_size(u32 qsize) +{ + switch (qsize) { + case 12: + case 16: + case 21: + case 24: + case 0: + return 0; + default: + return -EINVAL; + } +} + static int kvmppc_xive_native_set_source(struct kvmppc_xive *xive, long irq, u64 addr) { @@ -268,6 +282,52 @@ static int kvmppc_xive_native_get_vc_base(struct kvmppc_xive *xive, u64 addr) return 0; } +static int kvmppc_xive_native_set_source_config(struct kvmppc_xive *xive, + struct kvmppc_xive_src_block *sb, + struct kvmppc_xive_irq_state *state, + u32 server, + u8 priority, + u32 eisn) +{ + struct kvm *kvm = xive->kvm; + u32 hw_num; + int rc = 0; + + arch_spin_lock(&sb->lock); + + /* TODO: check also eisn for retargeting ? */ + if (state->act_server == server && state->act_priority == priority) + goto unlock; + + pr_devel("new_act_prio=%d new_act_server=%d act_server=%d act_prio=%d\n", + priority, server, state->act_server, state->act_priority); + + kvmppc_xive_select_irq(state, &hw_num, NULL); + + if (priority != 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, xive->vp_base + 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 xive_native_esb_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; @@ -523,6 +583,248 @@ static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type) return ret; } +static int kvmppc_h_int_set_source_config(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long irq, + unsigned long server, + unsigned long priority, + unsigned long eisn) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + int rc = 0; + u16 idx; + + pr_devel("H_INT_SET_SOURCE_CONFIG flags=%08lx irq=%lx server=%ld priority=%ld eisn=%lx\n", + flags, irq, server, priority, eisn); + + if (flags & ~(XIVE_SPAPR_SRC_SET_EISN | XIVE_SPAPR_SRC_MASK)) + return H_PARAMETER; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return H_P2; + state = &sb->irq_state[idx]; + + if (!(flags & XIVE_SPAPR_SRC_SET_EISN)) + eisn = state->eisn; + + if (priority != xive_prio_from_guest(priority)) { + pr_err("invalid priority for queue %ld for VCPU %ld\n", + priority, server); + return H_P3; + } + + rc = kvmppc_xive_native_set_source_config(xive, sb, state, server, + priority, eisn); + if (!rc) + return H_SUCCESS; + else if (rc == -EINVAL) + return H_P4; /* no server found */ + else + return H_HARDWARE; +} + +static int kvmppc_h_int_set_queue_config(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long server, + unsigned long priority, + unsigned long qpage, + unsigned long qsize) +{ + struct kvm *kvm = vcpu->kvm; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_q *q; + int rc; + __be32 *qaddr = 0; + struct page *page; + + pr_devel("H_INT_SET_QUEUE_CONFIG flags=%08lx server=%ld priority=%ld qpage=%08lx qsize=%ld\n", + flags, server, priority, qpage, qsize); + + if (flags & ~XIVE_SPAPR_EQ_ALWAYS_NOTIFY) + return H_PARAMETER; + + if (xc->server_num != server) { + vcpu = kvmppc_xive_find_server(kvm, server); + if (!vcpu) { + pr_debug("Can't find server %ld\n", server); + return H_P2; + } + xc = vcpu->arch.xive_vcpu; + } + + if (priority != xive_prio_from_guest(priority) || priority == MASKED) { + pr_err("invalid priority for queue %ld for VCPU %d\n", + priority, xc->server_num); + return H_P3; + } + q = &xc->queues[priority]; + + rc = xive_native_validate_queue_size(qsize); + if (rc) { + pr_err("invalid queue size %ld\n", qsize); + return H_P5; + } + + /* reset queue and disable queueing */ + if (!qsize) { + rc = xive_native_configure_queue(xc->vp_id, q, priority, + NULL, 0, true); + if (rc) { + pr_err("Failed to reset queue %ld for VCPU %d: %d\n", + priority, xc->server_num, rc); + return H_HARDWARE; + } + + if (q->qpage) { + put_page(virt_to_page(q->qpage)); + q->qpage = NULL; + } + + return H_SUCCESS; + } + + page = gfn_to_page(kvm, gpa_to_gfn(qpage)); + if (is_error_page(page)) { + pr_warn("Couldn't get guest page for %lx!\n", qpage); + return H_P4; + } + qaddr = page_to_virt(page) + (qpage & ~PAGE_MASK); + + rc = xive_native_configure_queue(xc->vp_id, q, priority, + (__be32 *) qaddr, qsize, true); + if (rc) { + pr_err("Failed to configure queue %ld for VCPU %d: %d\n", + priority, xc->server_num, rc); + put_page(page); + return H_HARDWARE; + } + + rc = kvmppc_xive_attach_escalation(vcpu, priority); + if (rc) { + xive_native_cleanup_queue(vcpu, priority); + return H_HARDWARE; + } + + return H_SUCCESS; +} + +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; + + arch_spin_lock(&sb->lock); + 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); + } + arch_spin_unlock(&sb->lock); + } +} + +static int kvmppc_h_int_reset(struct kvmppc_xive *xive, unsigned long flags) +{ + struct kvm *kvm = xive->kvm; + struct kvm_vcpu *vcpu; + unsigned int i; + + pr_devel("H_INT_RESET flags=%08lx\n", flags); + + if (flags) + return H_PARAMETER; + + mutex_lock(&kvm->lock); + + kvm_for_each_vcpu(i, vcpu, kvm) { + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + unsigned int i; + + if (!xc) + continue; + + /* TODO: Ensure no interrupt is still routed to that VP ? */ + + kvmppc_xive_disable_vcpu_interrupts(vcpu); + + for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { + + if (xc->esc_virq[i]) { + 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; + } + + xive_native_cleanup_queue(vcpu, i); + } + } + + for (i = 0; i <= xive->max_sbid; i++) { + if (xive->src_blocks[i]) + kvmppc_xive_reset_sources(xive->src_blocks[i]); + } + + mutex_unlock(&kvm->lock); + + return H_SUCCESS; +} + +int kvmppc_xive_hcall(struct kvm_vcpu *vcpu, u32 req) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + int rc; + + if (!xive || !vcpu->arch.xive_vcpu) + return H_FUNCTION; + + switch (req) { + case H_INT_SET_QUEUE_CONFIG: + rc = kvmppc_h_int_set_queue_config(vcpu, + kvmppc_get_gpr(vcpu, 4), + kvmppc_get_gpr(vcpu, 5), + kvmppc_get_gpr(vcpu, 6), + kvmppc_get_gpr(vcpu, 7), + kvmppc_get_gpr(vcpu, 8)); + break; + + case H_INT_SET_SOURCE_CONFIG: + rc = kvmppc_h_int_set_source_config(vcpu, + kvmppc_get_gpr(vcpu, 4), + kvmppc_get_gpr(vcpu, 5), + kvmppc_get_gpr(vcpu, 6), + kvmppc_get_gpr(vcpu, 7), + kvmppc_get_gpr(vcpu, 8)); + break; + + case H_INT_RESET: + rc = kvmppc_h_int_reset(xive, kvmppc_get_gpr(vcpu, 4)); + break; + + default: + rc = H_NOT_AVAILABLE; + } + + return rc; +} +EXPORT_SYMBOL_GPL(kvmppc_xive_hcall); + static int xive_native_debug_show(struct seq_file *m, void *private) { struct kvmppc_xive *xive = m->private; @@ -607,10 +909,26 @@ struct kvm_device_ops kvm_xive_native_ops = { void kvmppc_xive_native_init_module(void) { - ; + __xive_vm_h_int_get_source_info = xive_vm_h_int_get_source_info; + __xive_vm_h_int_get_source_config = xive_vm_h_int_get_source_config; + __xive_vm_h_int_get_queue_info = xive_vm_h_int_get_queue_info; + __xive_vm_h_int_get_queue_config = xive_vm_h_int_get_queue_config; + __xive_vm_h_int_set_os_reporting_line = + xive_vm_h_int_set_os_reporting_line; + __xive_vm_h_int_get_os_reporting_line = + xive_vm_h_int_get_os_reporting_line; + __xive_vm_h_int_esb = xive_vm_h_int_esb; + __xive_vm_h_int_sync = xive_vm_h_int_sync; } void kvmppc_xive_native_exit_module(void) { - ; + __xive_vm_h_int_get_source_info = NULL; + __xive_vm_h_int_get_source_config = NULL; + __xive_vm_h_int_get_queue_info = NULL; + __xive_vm_h_int_get_queue_config = NULL; + __xive_vm_h_int_set_os_reporting_line = NULL; + __xive_vm_h_int_get_os_reporting_line = NULL; + __xive_vm_h_int_esb = NULL; + __xive_vm_h_int_sync = NULL; } diff --git a/arch/powerpc/kvm/book3s_xive_native_template.c b/arch/powerpc/kvm/book3s_xive_native_template.c index 2a4cf4116b11..d74d023dd6e4 100644 --- a/arch/powerpc/kvm/book3s_xive_native_template.c +++ b/arch/powerpc/kvm/book3s_xive_native_template.c @@ -11,6 +11,265 @@ #define XGLUE(a, b) a##b #define GLUE(a, b) XGLUE(a, b) +X_STATIC int GLUE(X_PFX, h_int_get_source_info)(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long irq) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct xive_irq_data *xd; + u32 hw_num; + u16 src; + unsigned long trig_addr, eoi_addr; + + pr_devel("H_INT_GET_SOURCE_INFO flags=%08lx irq=%lx\n", flags, irq); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_debug("source %lx not found !\n", irq); + return H_P2; + } + state = &sb->irq_state[src]; + + arch_spin_lock(&sb->lock); + kvmppc_xive_select_irq(state, &hw_num, &xd); + + vcpu->arch.gpr[4] = 0; + if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI) + vcpu->arch.gpr[4] |= XIVE_SPAPR_SRC_STORE_EOI; + + if (state->lsi) + vcpu->arch.gpr[4] |= XIVE_SPAPR_SRC_LSI; + + trig_addr = xive->vc_base + irq * (1 << xd->esb_shift); + eoi_addr = trig_addr + (1 << (xd->esb_shift - 1)); + + vcpu->arch.gpr[5] = eoi_addr; + vcpu->arch.gpr[6] = trig_addr; + vcpu->arch.gpr[7] = PAGE_SHIFT; + arch_spin_unlock(&sb->lock); + return H_SUCCESS; +} + +X_STATIC int GLUE(X_PFX, h_int_get_source_config)(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long irq) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 src; + + pr_devel("H_INT_GET_SOURCE_CONFIG flags=%08lx irq=%lx\n", flags, irq); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_debug("source %lx not found !\n", irq); + return H_P2; + } + state = &sb->irq_state[src]; + + arch_spin_lock(&sb->lock); + vcpu->arch.gpr[4] = state->act_server; + vcpu->arch.gpr[5] = state->act_priority; + vcpu->arch.gpr[6] = state->number; + arch_spin_unlock(&sb->lock); + + return H_SUCCESS; +} + +X_STATIC int GLUE(X_PFX, h_int_get_queue_info)(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long server, + unsigned long priority) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_q *q; + + pr_devel("H_INT_GET_QUEUE_INFO flags=%08lx server=%ld priority=%ld\n", + flags, server, priority); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + if (xc->server_num != server) { + struct kvm_vcpu *vc; + + vc = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vc) { + pr_debug("server %ld not found\n", server); + return H_P2; + } + xc = vc->arch.xive_vcpu; + } + + if (priority != xive_prio_from_guest(priority) || priority == MASKED) { + pr_debug("invalid priority for queue %ld for VCPU %ld\n", + priority, server); + return H_P3; + } + q = &xc->queues[priority]; + + vcpu->arch.gpr[4] = q->eoi_phys; + /* TODO: Power of 2 page size of the notification page */ + vcpu->arch.gpr[5] = 0; + return H_SUCCESS; +} + +X_STATIC int GLUE(X_PFX, get_queue_state)(struct kvm_vcpu *vcpu, + struct kvmppc_xive_vcpu *xc, + unsigned long prio) +{ + int rc; + u32 version; + u64 qw1; + bool qtoggle; + u32 page_off; + + rc = xive_native_get_queue_state(xc->vp_id, prio, &version, &qw1); + if (rc) + return rc; + + if (XIVE_STATE_COMPAT(version) > 1) { + pr_err("invalid OPAL state version %08x\n", version); + return -EIO; + } + + qtoggle = GETFIELD(EQ_W1_GENERATION, qw1); + page_off = GETFIELD(EQ_W1_PAGE_OFF, qw1); + + vcpu->arch.gpr[4] |= ((unsigned long) qtoggle) << 62; + vcpu->arch.gpr[7] = page_off; + return 0; +} + +X_STATIC int GLUE(X_PFX, h_int_get_queue_config)(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long server, + unsigned long priority) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_q *q; + u64 qpage; + u64 qsize; + u64 qeoi_page; + u32 escalate_irq; + u64 qflags; + int rc; + + pr_devel("H_INT_GET_QUEUE_CONFIG flags=%08lx server=%ld priority=%ld\n", + flags, server, priority); + + if (!xive) + return H_FUNCTION; + + if (flags & ~XIVE_SPAPR_EQ_DEBUG) + return H_PARAMETER; + + if (xc->server_num != server) { + struct kvm_vcpu *vc; + + vc = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vc) { + pr_debug("server %ld not found\n", server); + return H_P2; + } + xc = vc->arch.xive_vcpu; + } + + if (priority != xive_prio_from_guest(priority) || priority == MASKED) { + pr_debug("invalid priority for queue %ld for VCPU %ld\n", + priority, server); + return H_P3; + } + q = &xc->queues[priority]; + + rc = xive_native_get_queue_info(xc->vp_id, priority, &qpage, &qsize, + &qeoi_page, &escalate_irq, &qflags); + if (rc) + return H_HARDWARE; + + vcpu->arch.gpr[4] = qflags; + vcpu->arch.gpr[5] = qpage; + vcpu->arch.gpr[6] = qsize; + if (flags & XIVE_SPAPR_EQ_DEBUG) { + rc = GLUE(X_PFX, get_queue_state)(vcpu, xc, priority); + if (rc) + return H_HARDWARE; + } + return H_SUCCESS; +} + +/* TODO H_INT_SET_OS_REPORTING_LINE */ +X_STATIC int GLUE(X_PFX, h_int_set_os_reporting_line)(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long line) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + + pr_devel("H_INT_SET_OS_REPORTING_LINE flags=%08lx line=%ld\n", + flags, line); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + return H_FUNCTION; +} + +/* TODO H_INT_GET_OS_REPORTING_LINE*/ +X_STATIC int GLUE(X_PFX, h_int_get_os_reporting_line)(struct kvm_vcpu *vcpu, + unsigned long flags, + unsigned long server, + unsigned long line) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + + pr_devel("H_INT_GET_OS_REPORTING_LINE flags=%08lx server=%ld line=%ld\n", + flags, server, line); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + if (xc->server_num != server) { + struct kvm_vcpu *vc; + + vc = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vc) { + pr_debug("server %ld not found\n", server); + return H_P2; + } + xc = vc->arch.xive_vcpu; + } + + return H_FUNCTION; + +} + /* * TODO: introduce a common template file with the XIVE native layer * and the XICS-on-XIVE glue for the utility functions @@ -28,3 +287,95 @@ static u8 GLUE(X_PFX, esb_load)(struct xive_irq_data *xd, u32 offset) #endif return (u8)val; } + +static u8 GLUE(X_PFX, esb_store)(struct xive_irq_data *xd, u32 offset, u64 data) +{ + u64 val; + + if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG) + offset |= offset << 4; + + val = __x_readq(__x_eoi_page(xd) + offset); +#ifdef __LITTLE_ENDIAN__ + val >>= 64-8; +#endif + return (u8)val; +} + +X_STATIC int GLUE(X_PFX, h_int_esb)(struct kvm_vcpu *vcpu, unsigned long flags, + unsigned long irq, unsigned long offset, + unsigned long data) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct xive_irq_data *xd; + u32 hw_num; + u16 src; + + pr_devel("H_INT_ESB flags=%08lx irq=%lx offset=%lx data=%lx\n", + flags, irq, offset, data); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_debug("source %lx not found !\n", irq); + return H_P2; + } + state = &sb->irq_state[src]; + + if (offset > (1ull << PAGE_SHIFT)) + return H_P3; + + arch_spin_lock(&sb->lock); + kvmppc_xive_select_irq(state, &hw_num, &xd); + + if (flags & XIVE_SPAPR_ESB_STORE) { + GLUE(X_PFX, esb_store)(xd, offset, data); + vcpu->arch.gpr[4] = -1; + } else { + vcpu->arch.gpr[4] = GLUE(X_PFX, esb_load)(xd, offset); + } + arch_spin_unlock(&sb->lock); + + return H_SUCCESS; +} + +X_STATIC int GLUE(X_PFX, h_int_sync)(struct kvm_vcpu *vcpu, unsigned long flags, + unsigned long irq) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct xive_irq_data *xd; + u32 hw_num; + u16 src; + + pr_devel("H_INT_SYNC flags=%08lx irq=%lx\n", flags, irq); + + if (!xive) + return H_FUNCTION; + + if (flags) + return H_PARAMETER; + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_debug("source %lx not found !\n", irq); + return H_P2; + } + state = &sb->irq_state[src]; + + arch_spin_lock(&sb->lock); + + kvmppc_xive_select_irq(state, &hw_num, &xd); + xive_native_sync_source(hw_num); + + arch_spin_unlock(&sb->lock); + return H_SUCCESS; +} From patchwork Mon Apr 23 16:43:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903024 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCBZ6dj7z9s0R for ; Tue, 24 Apr 2018 02:50:30 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755485AbeDWQua (ORCPT ); Mon, 23 Apr 2018 12:50:30 -0400 Received: from 2.mo68.mail-out.ovh.net ([46.105.52.162]:57496 "EHLO 2.mo68.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754788AbeDWQua (ORCPT ); Mon, 23 Apr 2018 12:50:30 -0400 X-Greylist: delayed 378 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 12:50:29 EDT Received: from player737.ha.ovh.net (unknown [10.109.122.24]) by mo68.mail-out.ovh.net (Postfix) with ESMTP id 13FC7DFB29 for ; Mon, 23 Apr 2018 18:45:06 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id CDC66E0091; Mon, 23 Apr 2018 18:44:59 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 12/16] powerpc/xive: update HW definitions Date: Mon, 23 Apr 2018 18:43:37 +0200 Message-Id: <20180423164341.15767-13-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 977562596988455895 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdegucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org We will need some of the XIVE internal structure definitions for migration. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/xive-regs.h | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/powerpc/include/asm/xive-regs.h b/arch/powerpc/include/asm/xive-regs.h index fa4288822b68..f1d398a48a3b 100644 --- a/arch/powerpc/include/asm/xive-regs.h +++ b/arch/powerpc/include/asm/xive-regs.h @@ -123,6 +123,51 @@ #define TM_QW3_NSR_I PPC_BIT8(2) #define TM_QW3_NSR_GRP_LVL PPC_BIT8(3,7) +/* IVE/EAS */ +#define IVE_VALID PPC_BIT(0) +#define IVE_EQ_BLOCK PPC_BITMASK(4, 7) /* Destination EQ block# */ +#define IVE_EQ_INDEX PPC_BITMASK(8, 31) /* Destination EQ index */ +#define IVE_MASKED PPC_BIT(32) /* Masked */ +#define IVE_EQ_DATA PPC_BITMASK(33, 63) /* Data written to the EQ */ + +/* EQ */ +#define EQ_W0_VALID PPC_BIT32(0) /* "v" bit */ +#define EQ_W0_ENQUEUE PPC_BIT32(1) /* "q" bit */ +#define EQ_W0_UCOND_NOTIFY PPC_BIT32(2) /* "n" bit */ +#define EQ_W0_BACKLOG PPC_BIT32(3) /* "b" bit */ +#define EQ_W0_PRECL_ESC_CTL PPC_BIT32(4) /* "p" bit */ +#define EQ_W0_ESCALATE_CTL PPC_BIT32(5) /* "e" bit */ +#define EQ_W0_UNCOND_ESCALATE PPC_BIT32(6) /* "u" bit - DD2.0 */ +#define EQ_W0_SILENT_ESCALATE PPC_BIT32(7) /* "s" bit - DD2.0 */ +#define EQ_W0_QSIZE PPC_BITMASK32(12, 15) +#define EQ_W0_SW0 PPC_BIT32(16) +#define EQ_W0_FIRMWARE EQ_W0_SW0 /* Owned by FW */ +#define EQ_QSIZE_4K 0 +#define EQ_QSIZE_64K 4 +#define EQ_W0_HWDEP PPC_BITMASK32(24, 31) +#define EQ_W1_ESn PPC_BITMASK32(0, 1) +#define EQ_W1_ESn_P PPC_BIT32(0) +#define EQ_W1_ESn_Q PPC_BIT32(1) +#define EQ_W1_ESe PPC_BITMASK32(2, 3) +#define EQ_W1_ESe_P PPC_BIT32(2) +#define EQ_W1_ESe_Q PPC_BIT32(3) +#define EQ_W1_GENERATION PPC_BIT32(9) +#define EQ_W1_PAGE_OFF PPC_BITMASK32(10, 31) +#define EQ_W2_MIGRATION_REG PPC_BITMASK32(0, 3) +#define EQ_W2_OP_DESC_HI PPC_BITMASK32(4, 31) +#define EQ_W3_OP_DESC_LO PPC_BITMASK32(0, 31) +#define EQ_W4_ESC_EQ_BLOCK PPC_BITMASK32(4, 7) +#define EQ_W4_ESC_EQ_INDEX PPC_BITMASK32(8, 31) +#define EQ_W5_ESC_EQ_DATA PPC_BITMASK32(1, 31) +#define EQ_W6_FORMAT_BIT PPC_BIT32(8) +#define EQ_W6_NVT_BLOCK PPC_BITMASK32(9, 12) +#define EQ_W6_NVT_INDEX PPC_BITMASK32(13, 31) +#define EQ_W7_F0_IGNORE PPC_BIT32(0) +#define EQ_W7_F0_BLK_GROUPING PPC_BIT32(1) +#define EQ_W7_F0_PRIORITY PPC_BITMASK32(8, 15) +#define EQ_W7_F1_WAKEZ PPC_BIT32(0) +#define EQ_W7_F1_LOG_SERVER_ID PPC_BITMASK32(1, 31) + /* Utilities to manipulate these (originaly from OPAL) */ #define MASK_TO_LSH(m) (__builtin_ffsl(m) - 1) #define GETFIELD(m, v) (((v) & (m)) >> MASK_TO_LSH(m)) From patchwork Mon Apr 23 16:43:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903045 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCS51tqyz9s0R for ; Tue, 24 Apr 2018 03:02:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755825AbeDWRCM (ORCPT ); Mon, 23 Apr 2018 13:02:12 -0400 Received: from 10.mo177.mail-out.ovh.net ([46.105.73.133]:34191 "EHLO 10.mo177.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755473AbeDWRCM (ORCPT ); Mon, 23 Apr 2018 13:02:12 -0400 Received: from player737.ha.ovh.net (unknown [10.109.105.4]) by mo177.mail-out.ovh.net (Postfix) with ESMTP id 49DF4AED0E for ; Mon, 23 Apr 2018 18:45:12 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 02343E0091; Mon, 23 Apr 2018 18:45:05 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 13/16] powerpc/xive: record guest queue page address Date: Mon, 23 Apr 2018 18:43:38 +0200 Message-Id: <20180423164341.15767-14-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 979532919971941335 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdeiucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org The guest physical address of the event queue will be part of the state to transfer in the migration. Let's just record it when the queue is configured. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/xive.h | 1 + arch/powerpc/kvm/book3s_xive_native.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h index aef28248b5b7..4096e4164ada 100644 --- a/arch/powerpc/include/asm/xive.h +++ b/arch/powerpc/include/asm/xive.h @@ -73,6 +73,7 @@ struct xive_q { u32 esc_irq; atomic_t count; atomic_t pending_count; + u64 guest_qpage; }; /* Global enable flags for the XIVE support */ diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 789c137f6b31..d705de3c5d65 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -693,6 +693,9 @@ static int kvmppc_h_int_set_queue_config(struct kvm_vcpu *vcpu, } qaddr = page_to_virt(page) + (qpage & ~PAGE_MASK); + /* Backup queue page guest address for migration */ + q->guest_qpage = qpage; + rc = xive_native_configure_queue(xc->vp_id, q, priority, (__be32 *) qaddr, qsize, true); if (rc) { From patchwork Mon Apr 23 16:43:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903025 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCBh5K75z9s02 for ; Tue, 24 Apr 2018 02:50:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755644AbeDWQuf (ORCPT ); Mon, 23 Apr 2018 12:50:35 -0400 Received: from 10.mo173.mail-out.ovh.net ([46.105.74.148]:59147 "EHLO 10.mo173.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755643AbeDWQue (ORCPT ); Mon, 23 Apr 2018 12:50:34 -0400 X-Greylist: delayed 27272 seconds by postgrey-1.27 at vger.kernel.org; Mon, 23 Apr 2018 12:50:33 EDT Received: from player737.ha.ovh.net (unknown [10.109.120.111]) by mo173.mail-out.ovh.net (Postfix) with ESMTP id 5F5FFBEC86 for ; Mon, 23 Apr 2018 18:45:18 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 2CD89E00A8; Mon, 23 Apr 2018 18:45:12 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 14/16] KVM: PPC: Book3S HV: add support for XIVE native migration Date: Mon, 23 Apr 2018 18:43:39 +0200 Message-Id: <20180423164341.15767-15-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 981221772425071575 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdeiucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org States we need to capture are : - the IVE table defining the source targeting - the main interrupt management registers for each vCPU - the EQs. Also mark the EQ page dirty to make sure it is transferred. This is work in progress. We need to make sure the HW has reached a quiescence point. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/kvm_ppc.h | 10 ++ arch/powerpc/include/uapi/asm/kvm.h | 11 ++ arch/powerpc/kvm/book3s.c | 46 +++++ arch/powerpc/kvm/book3s_xive_native.c | 320 ++++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index b5fceb4d7776..748518c7bf70 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -269,6 +269,8 @@ union kvmppc_one_reg { u64 addr; u64 length; } vpaval; + u32 xeqval[8]; + u64 vpval[2]; }; struct kvmppc_ops { @@ -594,6 +596,10 @@ extern int kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu); extern void kvmppc_xive_native_init_module(void); extern void kvmppc_xive_native_exit_module(void); extern int kvmppc_xive_hcall(struct kvm_vcpu *vcpu, u32 cmd); +extern int kvmppc_xive_get_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val); +extern int kvmppc_xive_set_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val); +extern int kvmppc_xive_get_vp_queue(struct kvm_vcpu *vcpu, int priority, union kvmppc_one_reg *val); +extern int kvmppc_xive_set_vp_queue(struct kvm_vcpu *vcpu, int priority, union kvmppc_one_reg *val); #else static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, @@ -627,6 +633,10 @@ static inline void kvmppc_xive_native_init_module(void) { } static inline void kvmppc_xive_native_exit_module(void) { } static inline int kvmppc_xive_hcall(struct kvm_vcpu *vcpu, u32 cmd) { return 0; } +static inline int kvmppc_xive_get_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val) { return 0; } +static inline int kvmppc_xive_set_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val) { return -ENOENT; } +static inline int kvmppc_xive_get_vp_queue(struct kvm_vcpu *vcpu, int priority, union kvmppc_one_reg *val) { return 0; } +static inline int kvmppc_xive_set_vp_queue(struct kvm_vcpu *vcpu, int priority, union kvmppc_one_reg *val) { return -ENOENT; } #endif /* CONFIG_KVM_XIVE */ diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 6e120129dfe6..8a2be937a98e 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -480,6 +480,16 @@ struct kvm_ppc_cpu_char { #define KVM_REG_PPC_ICP_PPRI_SHIFT 16 /* pending irq priority */ #define KVM_REG_PPC_ICP_PPRI_MASK 0xff +#define KVM_REG_PPC_VP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x8d) +#define KVM_REG_PPC_VP_EQ0 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x8e) +#define KVM_REG_PPC_VP_EQ1 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x8f) +#define KVM_REG_PPC_VP_EQ2 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x90) +#define KVM_REG_PPC_VP_EQ3 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x91) +#define KVM_REG_PPC_VP_EQ4 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x92) +#define KVM_REG_PPC_VP_EQ5 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x93) +#define KVM_REG_PPC_VP_EQ6 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x94) +#define KVM_REG_PPC_VP_EQ7 (KVM_REG_PPC | KVM_REG_SIZE_U256 | 0x95) + /* Device control API: PPC-specific devices */ #define KVM_DEV_MPIC_GRP_MISC 1 #define KVM_DEV_MPIC_BASE_ADDR 0 /* 64-bit */ @@ -679,6 +689,7 @@ struct kvm_ppc_cpu_char { #define KVM_DEV_XIVE_GET_ESB_FD 1 #define KVM_DEV_XIVE_GET_TIMA_FD 2 #define KVM_DEV_XIVE_VC_BASE 3 +#define KVM_DEV_XIVE_GRP_IVE 3 /* Layout of 64-bit XIVE source attribute values */ #define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0) diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 19c0187cada3..fc745233b2d9 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -625,6 +625,29 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu)); break; #endif /* CONFIG_KVM_XICS */ +#ifdef CONFIG_KVM_XIVE + case KVM_REG_PPC_VP_STATE: + if (!vcpu->arch.xive_vcpu) { + r = -ENXIO; + break; + } + if (xive_enabled()) + r = kvmppc_xive_get_vp(vcpu, val); + else + r = -ENXIO; + break; + case KVM_REG_PPC_VP_EQ0 ... KVM_REG_PPC_VP_EQ7: + if (!vcpu->arch.xive_vcpu) { + r = -ENXIO; + break; + } + if (xive_enabled()) { + i = id - KVM_REG_PPC_VP_EQ0; + r = kvmppc_xive_get_vp_queue(vcpu, i, val); + } else + r = -ENXIO; + break; +#endif /* CONFIG_KVM_XIVE */ case KVM_REG_PPC_FSCR: *val = get_reg_val(id, vcpu->arch.fscr); break; @@ -698,6 +721,29 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, r = kvmppc_xics_set_icp(vcpu, set_reg_val(id, *val)); break; #endif /* CONFIG_KVM_XICS */ +#ifdef CONFIG_KVM_XIVE + case KVM_REG_PPC_VP_STATE: + if (!vcpu->arch.xive_vcpu) { + r = -ENXIO; + break; + } + if (xive_enabled()) + r = kvmppc_xive_set_vp(vcpu, val); + else + r = -ENXIO; + break; + case KVM_REG_PPC_VP_EQ0 ... KVM_REG_PPC_VP_EQ7: + if (!vcpu->arch.xive_vcpu) { + r = -ENXIO; + break; + } + if (xive_enabled()) { + i = id - KVM_REG_PPC_VP_EQ0; + kvmppc_xive_set_vp_queue(vcpu, i, val); + } else + r = -ENXIO; + break; +#endif /* CONFIG_KVM_XIVE */ case KVM_REG_PPC_FSCR: vcpu->arch.fscr = set_reg_val(id, *val); break; diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index d705de3c5d65..056d4669a506 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -189,6 +189,233 @@ static int xive_native_validate_queue_size(u32 qsize) } } +int kvmppc_xive_get_vp(struct kvm_vcpu *vcpu, union kvmppc_one_reg *val) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + u32 version; + int rc; + + if (!kvmppc_xive_enabled(vcpu)) + return -EPERM; + + if (!xc) + return -ENOENT; + + val->vpval[0] = vcpu->arch.xive_saved_state.w01; + + rc = xive_native_get_vp_state(xc->vp_id, &version, &val->vpval[1]); + if (rc) + return rc; + + if (XIVE_STATE_COMPAT(version) > 1) { + pr_err("invalid OPAL state version %08x\n", version); + return -EIO; + } + + 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, val->vpval[1]); + + return 0; +} + +int kvmppc_xive_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; + u32 version = XIVE_STATE_VERSION; + int rc; + + pr_devel("%s w01=%016llx vp=%016llx\n", __func__, val->vpval[0], + val->vpval[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 -EIO; + + /* TODO: only restore IPB and CPPR ? */ + vcpu->arch.xive_saved_state.w01 = val->vpval[0]; + + rc = xive_native_set_vp_state(xc->vp_id, version, val->vpval[1]); + if (rc) + return rc; + + return 0; +} + +int kvmppc_xive_get_vp_queue(struct kvm_vcpu *vcpu, int priority, + union kvmppc_one_reg *val) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_q *q; + u64 qpage; + u64 qsize; + u64 qeoi_page; + u32 escalate_irq; + u64 qflags; + u32 version; + u64 qw1; + int rc; + + pr_debug("%s vcpu %d priority %d\n", __func__, xc->server_num, + priority); + + if (!kvmppc_xive_enabled(vcpu)) + return -EPERM; + + if (!xc) + return -ENOENT; + + if (priority != xive_prio_from_guest(priority) || priority == MASKED) { + pr_err("Trying to retrieve info from queue %d for VCPU %d\n", + priority, xc->server_num); + return -EINVAL; + } + q = &xc->queues[priority]; + + memset(val->xeqval, 0, sizeof(val->xeqval)); + + if (!q->qpage) + return 0; + + rc = xive_native_get_queue_info(xc->vp_id, priority, &qpage, &qsize, + &qeoi_page, &escalate_irq, &qflags); + if (rc) + return rc; + + rc = xive_native_get_queue_state(xc->vp_id, priority, &version, &qw1); + if (rc) + return rc; + + if (XIVE_STATE_COMPAT(version) > 1) { + pr_err("invalid OPAL state version %08x\n", version); + return -EIO; + } + + val->xeqval[0] = 0; + if (qflags & OPAL_XIVE_EQ_ENABLED) + val->xeqval[0] |= EQ_W0_VALID|EQ_W0_ENQUEUE; + if (qflags & OPAL_XIVE_EQ_ALWAYS_NOTIFY) + val->xeqval[0] |= EQ_W0_UCOND_NOTIFY; + if (qflags & OPAL_XIVE_EQ_ESCALATE) + val->xeqval[0] |= EQ_W0_ESCALATE_CTL; + val->xeqval[0] |= SETFIELD(EQ_W0_QSIZE, 0ul, qsize - 12); + + val->xeqval[1] = qw1 & 0xffffffff; + val->xeqval[2] = (q->guest_qpage >> 32) & 0x0fffffff; + val->xeqval[3] = q->guest_qpage & 0xffffffff; + val->xeqval[4] = 0; + val->xeqval[5] = 0; + val->xeqval[6] = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, 0ul) | + SETFIELD(EQ_W6_NVT_INDEX, 0ul, xc->server_num); + val->xeqval[7] = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, priority); + + /* Mark EQ page dirty for migration */ + mark_page_dirty(vcpu->kvm, gpa_to_gfn(q->guest_qpage)); + + return 0; +} + +int kvmppc_xive_set_vp_queue(struct kvm_vcpu *vcpu, int priority, + union kvmppc_one_reg *val) +{ + struct kvm *kvm = vcpu->kvm; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + u32 qsize; + u64 qpage; + u32 server; + u8 prio; + int rc; + __be32 *qaddr = 0; + struct page *page; + struct xive_q *q; + u32 version = XIVE_STATE_VERSION; + + pr_devel("%s vcpu %d priority %d\n", __func__, xc->server_num, + priority); + + if (!xc || !xive) + return -ENOENT; + + /* + * Check that we are not trying to configure queues reserved + * for the hypervisor + */ + if (priority != xive_prio_from_guest(priority) || priority == MASKED) { + pr_err("Trying to restore invalid queue %d for VCPU %d\n", + priority, xc->server_num); + return -EINVAL; + } + + qsize = GETFIELD(EQ_W0_QSIZE, val->xeqval[0]) + 12; + qpage = (((u64)(val->xeqval[2] & 0x0fffffff)) << 32) | val->xeqval[3]; + server = GETFIELD(EQ_W6_NVT_INDEX, val->xeqval[6]); + prio = GETFIELD(EQ_W7_F0_PRIORITY, val->xeqval[7]); + + if (xc->server_num != server) { + vcpu = kvmppc_xive_find_server(kvm, server); + if (!vcpu) { + pr_debug("Can't find server %d\n", server); + return -EINVAL; + } + xc = vcpu->arch.xive_vcpu; + } + + if (priority != prio) { + pr_err("invalid state for queue %d for VCPU %d\n", + priority, xc->server_num); + return -EIO; + } + q = &xc->queues[prio]; + + rc = xive_native_validate_queue_size(qsize); + if (rc || !qsize) { + pr_err("invalid queue size %d\n", qsize); + return rc; + } + + page = gfn_to_page(kvm, gpa_to_gfn(qpage)); + if (is_error_page(page)) { + pr_debug("Couldn't get guest page for %llx!\n", qpage); + return -ENOMEM; + } + qaddr = page_to_virt(page) + (qpage & ~PAGE_MASK); + q->guest_qpage = qpage; + + rc = xive_native_configure_queue(xc->vp_id, q, prio, (__be32 *) qaddr, + qsize, true); + if (rc) { + pr_err("Failed to configure queue %d for VCPU %d: %d\n", + prio, xc->server_num, rc); + put_page(page); + return rc; + } + + rc = xive_native_set_queue_state(xc->vp_id, prio, version, + val->xeqval[1]); + if (rc) + goto error; + + rc = kvmppc_xive_attach_escalation(vcpu, prio); +error: + if (rc) + xive_native_cleanup_queue(vcpu, prio); + return rc; +} + + static int kvmppc_xive_native_set_source(struct kvmppc_xive *xive, long irq, u64 addr) { @@ -328,6 +555,94 @@ static int kvmppc_xive_native_set_source_config(struct kvmppc_xive *xive, return rc; } +static int kvmppc_xive_native_set_ive(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 ive; + u32 eq_idx; + u32 server; + u8 priority; + u32 eisn; + + pr_devel("%s irq=0x%lx\n", __func__, irq); + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) + return -ENOENT; + + state = &sb->irq_state[src]; + + if (!state->valid) + return -ENOENT; + + if (get_user(ive, ubufp)) { + pr_err("fault getting user info !\n"); + return -EFAULT; + } + + if (!(ive & IVE_VALID) || ive & IVE_MASKED) { + pr_err("invalid IVE %016llx for IRQ %lx\n", ive, irq); + return -EPERM; + } + + /* QEMU encoding of EQ index */ + eq_idx = GETFIELD(IVE_EQ_INDEX, ive); + server = eq_idx >> 3; + priority = eq_idx & 0x7; + + eisn = GETFIELD(IVE_EQ_DATA, ive); + + return kvmppc_xive_native_set_source_config(xive, sb, state, server, + priority, eisn); +} + +static int kvmppc_xive_native_get_ive(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 ive; + u32 eq_idx; + + pr_devel("%s irq=0x%lx\n", __func__, irq); + + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) + return -ENOENT; + + state = &sb->irq_state[src]; + + if (!state->valid) + return -ENOENT; + + ive = IVE_VALID; + + arch_spin_lock(&sb->lock); + + if (state->act_priority == MASKED) + ive |= IVE_MASKED; + else { + /* QEMU encoding of EQ index */ + eq_idx = ((state->act_server) << 3) | + ((state->act_priority) & 0x7); + ive |= SETFIELD(IVE_EQ_BLOCK, 0ul, 0ul) | + SETFIELD(IVE_EQ_INDEX, 0ul, eq_idx) | + SETFIELD(IVE_EQ_DATA, 0ul, state->eisn); + } + arch_spin_unlock(&sb->lock); + + if (put_user(ive, ubufp)) + return -EFAULT; + + return 0; +} + static int xive_native_esb_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; @@ -455,6 +770,8 @@ static int kvmppc_xive_native_set_attr(struct kvm_device *dev, case KVM_DEV_XIVE_GRP_SOURCES: return kvmppc_xive_native_set_source(xive, attr->attr, attr->addr); + case KVM_DEV_XIVE_GRP_IVE: + return kvmppc_xive_native_set_ive(xive, attr->attr, attr->addr); case KVM_DEV_XIVE_GRP_CTRL: switch (attr->attr) { case KVM_DEV_XIVE_VC_BASE: @@ -471,6 +788,8 @@ static int kvmppc_xive_native_get_attr(struct kvm_device *dev, struct kvmppc_xive *xive = dev->private; switch (attr->group) { + case KVM_DEV_XIVE_GRP_IVE: + return kvmppc_xive_native_get_ive(xive, attr->attr, attr->addr); case KVM_DEV_XIVE_GRP_CTRL: switch (attr->attr) { case KVM_DEV_XIVE_GET_ESB_FD: @@ -490,6 +809,7 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev, { switch (attr->group) { case KVM_DEV_XIVE_GRP_SOURCES: + case KVM_DEV_XIVE_GRP_IVE: if (attr->attr >= KVMPPC_XIVE_FIRST_IRQ && attr->attr < KVMPPC_XIVE_NR_IRQS) return 0; From patchwork Mon Apr 23 16:43:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903027 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCC04w7wz9ry1 for ; Tue, 24 Apr 2018 02:50:52 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755908AbeDWQuu (ORCPT ); Mon, 23 Apr 2018 12:50:50 -0400 Received: from 14.mo6.mail-out.ovh.net ([46.105.56.113]:47952 "EHLO 14.mo6.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755789AbeDWQur (ORCPT ); Mon, 23 Apr 2018 12:50:47 -0400 Received: from player737.ha.ovh.net (unknown [10.109.108.23]) by mo6.mail-out.ovh.net (Postfix) with ESMTP id 86698157E3F for ; Mon, 23 Apr 2018 18:45:24 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 563ABE0091; Mon, 23 Apr 2018 18:45:18 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 15/16] KVM: introduce a KVM_DESTROY_DEVICE ioctl Date: Mon, 23 Apr 2018 18:43:40 +0200 Message-Id: <20180423164341.15767-16-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 982910620631731159 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdeiucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org This will be used to destroy the KVM XICS or XIVE device when the sPAPR machine is reseted. When the VM boots, the CAS negotiation process will determine which interrupt mode to use and the appropriate KVM device will then be created. Signed-off-by: Cédric Le Goater --- include/uapi/linux/kvm.h | 2 ++ virt/kvm/kvm_main.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index cda8b85f4849..2545e20f3cec 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1279,6 +1279,8 @@ struct kvm_s390_ucas_mapping { #define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr) #define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr) +#define KVM_DESTROY_DEVICE _IOWR(KVMIO, 0xf0, struct kvm_create_device) + /* * ioctls for vcpu fds */ diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 65dea3ffef68..10fc3fa522b3 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2898,6 +2898,32 @@ static int kvm_ioctl_create_device(struct kvm *kvm, return 0; } +static int kvm_ioctl_destroy_device(struct kvm *kvm, + struct kvm_create_device *cd) +{ + struct fd f; + struct kvm_device *dev; + + f = fdget(cd->fd); + if (!f.file) + return -EBADF; + + dev = kvm_device_from_filp(f.file); + fdput(f); + + if (!dev) + return -EPERM; + + mutex_lock(&kvm->lock); + list_del(&dev->vm_node); + mutex_unlock(&kvm->lock); + dev->ops->destroy(dev); + + kvm_put_kvm(kvm); + + return 0; +} + static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) { switch (arg) { @@ -3093,6 +3119,20 @@ static long kvm_vm_ioctl(struct file *filp, r = 0; break; } + case KVM_DESTROY_DEVICE: { + struct kvm_create_device cd; + + r = -EFAULT; + if (copy_from_user(&cd, argp, sizeof(cd))) + goto out; + + r = kvm_ioctl_destroy_device(kvm, &cd); + if (r) + goto out; + + r = 0; + break; + } case KVM_CHECK_EXTENSION: r = kvm_vm_ioctl_check_extension_generic(kvm, arg); break; From patchwork Mon Apr 23 16:43:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 903032 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40VCJ44FPBz9s06 for ; Tue, 24 Apr 2018 02:55:16 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932073AbeDWQzP (ORCPT ); Mon, 23 Apr 2018 12:55:15 -0400 Received: from 9.mo69.mail-out.ovh.net ([46.105.56.78]:34403 "EHLO 9.mo69.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932093AbeDWQzP (ORCPT ); Mon, 23 Apr 2018 12:55:15 -0400 Received: from player737.ha.ovh.net (unknown [10.109.108.24]) by mo69.mail-out.ovh.net (Postfix) with ESMTP id A6DF910BFF for ; Mon, 23 Apr 2018 18:45:30 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player737.ha.ovh.net (Postfix) with ESMTPSA id 80A34E0091; Mon, 23 Apr 2018 18:45:24 +0200 (CEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Paul Mackerras , David Gibson , Benjamin Herrenschmidt , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 16/16] KVM: PPC: Book3S HV: disconnect vCPU from IRQ device Date: Mon, 23 Apr 2018 18:43:41 +0200 Message-Id: <20180423164341.15767-17-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180423164341.15767-1-clg@kaod.org> References: <20180423164341.15767-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 984599468972739543 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtgedrkeeggddutdeiucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org Before destroying a KVM device for IRQs, we need to disconnect the VCPUs. Do that using a 'disable=1' as last argument of the KVM_ENABLE_CAP ioctl. This is a bit hacky, we should introduce a KVM_DISABLE_CAP ioctl most certainly. Signed-off-by: Cédric Le Goater --- arch/powerpc/include/asm/kvm_ppc.h | 4 ++-- arch/powerpc/kvm/book3s_xics.c | 5 +++-- arch/powerpc/kvm/book3s_xive.c | 10 +++++++++- arch/powerpc/kvm/powerpc.c | 28 +++++++++++++++++++++------- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 748518c7bf70..5c0af1cabe34 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -518,7 +518,7 @@ extern void kvmppc_alloc_host_rm_ops(void); extern void kvmppc_free_host_rm_ops(void); extern void kvmppc_free_pimap(struct kvm *kvm); extern int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall); -extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu); +extern int kvmppc_xics_free_icp(struct kvm_vcpu *vcpu); extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd); extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu); extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval); @@ -574,7 +574,7 @@ extern void kvmppc_xive_exit_module(void); extern int kvmppc_xive_connect_vcpu(struct kvm_device *dev, struct kvm_vcpu *vcpu, u32 cpu); -extern void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu); +extern int kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu); extern int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq, struct irq_desc *host_desc); extern int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq, diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index b8356cdc0c04..b0c85525944d 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c @@ -1440,13 +1440,14 @@ int kvmppc_xics_connect_vcpu(struct kvm_device *dev, struct kvm_vcpu *vcpu, return r; } -void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) +int kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { if (!vcpu->arch.icp) - return; + return -ENOENT; kfree(vcpu->arch.icp); vcpu->arch.icp = NULL; vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT; + return 0; } void kvmppc_xics_set_mapped(struct kvm *kvm, unsigned long irq, diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index abb4ae5c5b91..3c66480d3304 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -1023,12 +1023,15 @@ void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu) } } -void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) +int kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) { struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; struct kvmppc_xive *xive = xc->xive; int i; + if (!vcpu->arch.xive_vcpu) + return -ENOENT; + pr_devel("cleanup_vcpu(cpu=%d)\n", xc->server_num); /* Ensure no interrupt is still routed to that VP */ @@ -1067,6 +1070,11 @@ void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) } /* Free the VP */ kfree(xc); + + /* Cleanup the vcpu */ + vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT; + vcpu->arch.xive_vcpu = NULL; + return 0; } int kvmppc_xive_connect_vcpu(struct kvm_device *dev, diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 42eb75e43d6e..e0ff5e9610ee 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -1710,10 +1710,19 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, r = -EPERM; dev = kvm_device_from_filp(f.file); if (dev) { - if (xive_enabled()) - r = kvmppc_xive_connect_vcpu(dev, vcpu, cap->args[1]); - else - r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]); + if (cap->args[2]) { + if (xive_enabled()) + r = kvmppc_xive_cleanup_vcpu(vcpu); + else + r = kvmppc_xics_free_icp(vcpu); + } else { + if (xive_enabled()) + r = kvmppc_xive_connect_vcpu(dev, vcpu, + cap->args[1]); + else + r = kvmppc_xics_connect_vcpu(dev, vcpu, + cap->args[1]); + } } fdput(f); @@ -1736,9 +1745,14 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, r = -EPERM; dev = kvm_device_from_filp(f.file); - if (dev) - r = kvmppc_xive_native_connect_vcpu(dev, vcpu, - cap->args[1]); + if (dev) { + if (cap->args[2]) { + r = kvmppc_xive_native_cleanup_vcpu(vcpu); + } else { + r = kvmppc_xive_native_connect_vcpu(dev, vcpu, + cap->args[1]); + } + } fdput(f); break;