From nobody Fri Apr 19 01:53:53 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1673656785667561.8527733597322; Fri, 13 Jan 2023 16:39:45 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pGUa0-0004gT-B4; Fri, 13 Jan 2023 19:39:28 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZy-0004gA-81 for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:26 -0500 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZv-0005Me-Ls for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:25 -0500 Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZy-006abt-AQ; Sat, 14 Jan 2023 00:39:26 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZk-001C2C-Qn; Sat, 14 Jan 2023 00:39:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=sNjkheOYhJnom1v1UgX1lUgnsNeUFzpzsJdTyyoHODk=; b=Ic+qkHarLV8QmMI9XNFNU3F2Kf aNb8lZQsk72GKzKFxzE8CJSnzHgBzPqcyERRAwOL/3f/T7PVrwoOlq0pZ9RPGet9zB8gGDyjQiE5s B/WnvZgphDzMjpcmHKg4nZZK82Gjq8p1ukTLL6STz1yibCcWxWY/jz2NyijPmIgZeAVfXfh3/HFC0 0A1QJE2HhYH1G2oU454vGBEbnqpECu3LoUDpxHcAVauwhnTO2IMyLF9TQI563cjsarHofSLmrMFLO qG480McRiKko3njc+ln2aZ3EIj313ONxlPRNAObHCGaqkSWvS9IfRGKEUbDCdXnebLqnbQFlYpB/F r0PbeiZA==; From: David Woodhouse To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Paul Durrant , Joao Martins , Ankur Arora , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Juan Quintela , "Dr . David Alan Gilbert" , Claudio Fontana , Julien Grall , "Michael S. Tsirkin" , arcel Apfelbaum Subject: [RFC PATCH 1/5] i386/xen: Implement HYPERVISOR_physdev_op Date: Sat, 14 Jan 2023 00:39:05 +0000 Message-Id: <20230114003909.284331-2-dwmw2@infradead.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230114003909.284331-1-dwmw2@infradead.org> References: <20230114003909.284331-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2001:8b0:10b:1236::1; envelope-from=BATV+cc7f48ec5f75d1861b59+7083+infradead.org+dwmw2@casper.srs.infradead.org; helo=casper.infradead.org X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1673656787909100001 Content-Type: text/plain; charset="utf-8" From: David Woodhouse Just hook up the basic hypercalls to stubs in xen_evtchn.c for now. Signed-off-by: David Woodhouse --- hw/i386/kvm/xen_evtchn.c | 25 ++++++++ hw/i386/kvm/xen_evtchn.h | 11 ++++ target/i386/kvm/xen-compat.h | 19 ++++++ target/i386/kvm/xen-emu.c | 118 +++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c index 084249c56d..fd83d052f7 100644 --- a/hw/i386/kvm/xen_evtchn.c +++ b/hw/i386/kvm/xen_evtchn.c @@ -1301,6 +1301,31 @@ int xen_evtchn_set_port(uint16_t port) return ret; } =20 +int xen_physdev_map_pirq(struct physdev_map_pirq *map) +{ + return -ENOTSUP; +} + +int xen_physdev_unmap_pirq(struct physdev_unmap_pirq *unmap) +{ + return -ENOTSUP; +} + +int xen_physdev_eoi_pirq(struct physdev_eoi *eoi) +{ + return -ENOTSUP; +} + +int xen_physdev_query_pirq(struct physdev_irq_status_query *query) +{ + return -ENOTSUP; +} + +int xen_physdev_get_free_pirq(struct physdev_get_free_pirq *get) +{ + return -ENOTSUP; +} + struct xenevtchn_handle *xen_be_evtchn_open(void) { struct xenevtchn_handle *xc =3D g_new0(struct xenevtchn_handle, 1); diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h index b7b6f4e592..ccf58aa796 100644 --- a/hw/i386/kvm/xen_evtchn.h +++ b/hw/i386/kvm/xen_evtchn.h @@ -65,4 +65,15 @@ int xen_evtchn_bind_interdomain_op(struct evtchn_bind_in= terdomain *interdomain); int xen_evtchn_bind_vcpu_op(struct evtchn_bind_vcpu *vcpu); int xen_evtchn_reset_op(struct evtchn_reset *reset); =20 +struct physdev_map_pirq; +struct physdev_unmap_pirq; +struct physdev_eoi; +struct physdev_irq_status_query; +struct physdev_get_free_pirq; +int xen_physdev_map_pirq(struct physdev_map_pirq *map); +int xen_physdev_unmap_pirq(struct physdev_unmap_pirq *unmap); +int xen_physdev_eoi_pirq(struct physdev_eoi *eoi); +int xen_physdev_query_pirq(struct physdev_irq_status_query *query); +int xen_physdev_get_free_pirq(struct physdev_get_free_pirq *get); + #endif /* QEMU_XEN_EVTCHN_H */ diff --git a/target/i386/kvm/xen-compat.h b/target/i386/kvm/xen-compat.h index ff5d20e901..e86ffc7644 100644 --- a/target/i386/kvm/xen-compat.h +++ b/target/i386/kvm/xen-compat.h @@ -48,4 +48,23 @@ struct compat_xen_add_to_physmap_batch { COMPAT_HANDLE(int) errs; }; =20 +struct compat_physdev_map_pirq { + domid_t domid; + uint16_t pad; + /* IN */ + int type; + /* IN (ignored for ..._MULTI_MSI) */ + int index; + /* IN or OUT */ + int pirq; + /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */ + int bus; + /* IN */ + int devfn; + /* IN (also OUT for ..._MULTI_MSI) */ + int entry_nr; + /* IN */ + uint64_t table_base; +} __attribute__((packed)); + #endif /* QEMU_I386_XEN_COMPAT_H */ diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c index 273200bc70..3fa58e33bd 100644 --- a/target/i386/kvm/xen-emu.c +++ b/target/i386/kvm/xen-emu.c @@ -1480,6 +1480,121 @@ static bool kvm_xen_hcall_gnttab_op(struct kvm_xen_= exit *exit, X86CPU *cpu, return true; } =20 +static bool kvm_xen_hcall_physdev_op(struct kvm_xen_exit *exit, X86CPU *cp= u, + int cmd, uint64_t arg) +{ + CPUState *cs =3D CPU(cpu); + int err; + + switch (cmd) { + case PHYSDEVOP_map_pirq: { + struct physdev_map_pirq map; + + if (hypercall_compat32(exit->u.hcall.longmode)) { + struct compat_physdev_map_pirq *map32 =3D (void *)↦ + + if (kvm_copy_from_gva(cs, arg, map32, sizeof(*map32))) { + return -EFAULT; + } + + /* + * The only thing that's different is the alignment of the + * uint64_t table_base at the end, which gets padding to make + * it 64-bit aligned in the 64-bit version. + */ + qemu_build_assert(sizeof(*map32) =3D=3D 36); + qemu_build_assert(offsetof(struct physdev_map_pirq, entry_nr) = =3D=3D + offsetof(struct compat_physdev_map_pirq, ent= ry_nr)); + memmove(&map.table_base, &map32->table_base, sizeof(map.table_= base)); + } else { + if (kvm_copy_from_gva(cs, arg, &map, sizeof(map))) { + err =3D -EFAULT; + break; + } + } + err =3D xen_physdev_map_pirq(&map); + /* + * Since table_base is an IN parameter and won't be changed, just + * copy the size of the compat structure back to the guest. + */ + if (!err && kvm_copy_to_gva(cs, arg, &map, + sizeof(struct compat_physdev_map_pirq)= )) { + err =3D -EFAULT; + } + break; + } + case PHYSDEVOP_unmap_pirq: { + struct physdev_unmap_pirq unmap; + + qemu_build_assert(sizeof(unmap) =3D=3D 8); + if (kvm_copy_from_gva(cs, arg, &unmap, sizeof(unmap))) { + err =3D -EFAULT; + break; + } + + err =3D xen_physdev_unmap_pirq(&unmap); + if (!err && kvm_copy_to_gva(cs, arg, &unmap, sizeof(unmap))) { + err =3D -EFAULT; + } + break; + } + case PHYSDEVOP_eoi: { + struct physdev_eoi eoi; + + qemu_build_assert(sizeof(eoi) =3D=3D 4); + if (kvm_copy_from_gva(cs, arg, &eoi, sizeof(eoi))) { + err =3D -EFAULT; + break; + } + + err =3D xen_physdev_eoi_pirq(&eoi); + if (!err && kvm_copy_to_gva(cs, arg, &eoi, sizeof(eoi))) { + err =3D -EFAULT; + } + break; + } + case PHYSDEVOP_irq_status_query: { + struct physdev_irq_status_query query; + + qemu_build_assert(sizeof(query) =3D=3D 8); + if (kvm_copy_from_gva(cs, arg, &query, sizeof(query))) { + err =3D -EFAULT; + break; + } + + err =3D xen_physdev_query_pirq(&query); + if (!err && kvm_copy_to_gva(cs, arg, &query, sizeof(query))) { + err =3D -EFAULT; + } + break; + } + case PHYSDEVOP_get_free_pirq: { + struct physdev_get_free_pirq get; + + qemu_build_assert(sizeof(get) =3D=3D 8); + if (kvm_copy_from_gva(cs, arg, &get, sizeof(get))) { + err =3D -EFAULT; + break; + } + + err =3D xen_physdev_get_free_pirq(&get); + if (!err && kvm_copy_to_gva(cs, arg, &get, sizeof(get))) { + err =3D -EFAULT; + } + break; + } + case PHYSDEVOP_pirq_eoi_gmfn_v2: // FreeBSD 13 makes this hypercall + err =3D -ENOSYS; + break; + + default: + return false; + } + + exit->u.hcall.result =3D err; + return true; +} + static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit) { uint16_t code =3D exit->u.hcall.input; @@ -1514,6 +1629,9 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struc= t kvm_xen_exit *exit) case __HYPERVISOR_memory_op: return kvm_xen_hcall_memory_op(exit, cpu, exit->u.hcall.params[0], exit->u.hcall.params[1]); + case __HYPERVISOR_physdev_op: + return kvm_xen_hcall_physdev_op(exit, cpu, exit->u.hcall.params[0], + exit->u.hcall.params[1]); case __HYPERVISOR_xen_version: return kvm_xen_hcall_xen_version(exit, cpu, exit->u.hcall.params[0= ], exit->u.hcall.params[1]); --=20 2.35.3 From nobody Fri Apr 19 01:53:53 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1673656849335998.4959598404895; Fri, 13 Jan 2023 16:40:49 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pGUa2-0004hT-Rx; Fri, 13 Jan 2023 19:39:31 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUa0-0004ge-3E for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:28 -0500 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZv-0005Md-Lr for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:27 -0500 Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZy-006abu-BP; Sat, 14 Jan 2023 00:39:26 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZk-001C2F-SB; Sat, 14 Jan 2023 00:39:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description; bh=JqQCDIJ+1Gc1rVXAy99kDVBLCB7ZHbgitI9/ZFJtP1g=; b=Y1UNdwIB7FM8tDr/ayAYooH1IR JoIQwv5uYOoyqcwOcmk0zEYGgHnGMzXZbxqio07UxsXMmuUw1KadLli1QtoyDR06RCtrv4bjSvixT Tq7aQFfI9HZcjyWrWGCkBz3LEq/7xQZkwRF/1QneXOxq781wIvyX52n3m9xUZWjdaX7utQtgGX4/F jHPLNNLfydnOcZcPjjMb6LxN1uZMIchyeZFksjmp6PTag1AcNo52D9/a5M5Kculo4W7YhS/qVk8ON iW4o7Ue082vbrr5DIVTx78xGhQK1inVmIs0sbiqf1gNbOEXvAuN2MdwpCg7ZBh9h/oFmwl2SQvAWc jRoJ0Ksw==; From: David Woodhouse To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Paul Durrant , Joao Martins , Ankur Arora , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Juan Quintela , "Dr . David Alan Gilbert" , Claudio Fontana , Julien Grall , "Michael S. Tsirkin" , arcel Apfelbaum Subject: [RFC PATCH 2/5] hw/xen: Implement emulated PIRQ hypercall support Date: Sat, 14 Jan 2023 00:39:06 +0000 Message-Id: <20230114003909.284331-3-dwmw2@infradead.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230114003909.284331-1-dwmw2@infradead.org> References: <20230114003909.284331-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2001:8b0:10b:1236::1; envelope-from=BATV+cc7f48ec5f75d1861b59+7083+infradead.org+dwmw2@casper.srs.infradead.org; helo=casper.infradead.org X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1673656849684100001 From: David Woodhouse This wires up the basic infrastructure but the actual interrupts aren't there yet, so don't advertise it to the guest. Signed-off-by: David Woodhouse --- hw/i386/kvm/trace-events | 4 + hw/i386/kvm/trace.h | 1 + hw/i386/kvm/xen_evtchn.c | 265 +++++++++++++++++++++++++++++++++++++- hw/i386/kvm/xen_evtchn.h | 2 + meson.build | 1 + target/i386/kvm/xen-emu.c | 15 +++ 6 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 hw/i386/kvm/trace-events create mode 100644 hw/i386/kvm/trace.h diff --git a/hw/i386/kvm/trace-events b/hw/i386/kvm/trace-events new file mode 100644 index 0000000000..04e60c5bb8 --- /dev/null +++ b/hw/i386/kvm/trace-events @@ -0,0 +1,4 @@ +kvm_xen_map_pirq(int pirq, int gsi) "pirq %d gsi %d" +kvm_xen_unmap_pirq(int pirq, int gsi) "pirq %d gsi %d" +kvm_xen_get_free_pirq(int pirq, int type) "pirq %d type %d" +kvm_xen_bind_pirq(int pirq, int port) "pirq %d port %d" diff --git a/hw/i386/kvm/trace.h b/hw/i386/kvm/trace.h new file mode 100644 index 0000000000..e55d0812fd --- /dev/null +++ b/hw/i386/kvm/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_i386_kvm.h" diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c index fd83d052f7..82250daecb 100644 --- a/hw/i386/kvm/xen_evtchn.c +++ b/hw/i386/kvm/xen_evtchn.c @@ -23,6 +23,7 @@ #include "exec/target_page.h" #include "exec/address-spaces.h" #include "migration/vmstate.h" +#include "trace.h" =20 #include "hw/sysbus.h" #include "hw/xen/xen.h" @@ -105,6 +106,23 @@ struct xenevtchn_handle { #define PORT_INFO_TYPEVAL_REMOTE_QEMU 0x8000 #define PORT_INFO_TYPEVAL_REMOTE_PORT_MASK 0x7FFF =20 +#define MAX_XEN_PIRQ 0x1048 /* Empirically */ + +/* + * These 'emuirq' values are used by Xen in the LM stream... and yes, I am + * insane enough to think about guest-transparent live migration from actu= al + * Xen to QEMU, and ensuring that we can convert/consume the stream. + */ +#define IRQ_UNBOUND -1 +#define IRQ_PT -2 +#define IRQ_MSI_EMU -3 + + +struct pirq_info { + int gsi; + uint16_t port; +}; + struct XenEvtchnState { /*< private >*/ SysBusDevice busdev; @@ -120,6 +138,14 @@ struct XenEvtchnState { qemu_irq gsis[GSI_NUM_PINS]; =20 struct xenevtchn_handle *be_handles[EVTCHN_2L_NR_CHANNELS]; + + /* GSI =E2=86=92 PIRQ mapping (serialized) */ + uint16_t gsi_pirq[GSI_NUM_PINS]; + /* Bitmap of allocated PIRQs (serialized) */ + uint64_t pirq_inuse[DIV_ROUND_UP(MAX_XEN_PIRQ, 64)]; + + /* Per-PIRQ information (rebuilt on migration) */ + struct pirq_info pirq[MAX_XEN_PIRQ]; }; =20 struct XenEvtchnState *xen_evtchn_singleton; @@ -179,6 +205,9 @@ static const VMStateDescription xen_evtchn_vmstate =3D { VMSTATE_UINT32(nr_ports, XenEvtchnState), VMSTATE_STRUCT_VARRAY_UINT32(port_table, XenEvtchnState, nr_ports,= 1, xen_evtchn_port_vmstate, XenEvtchnPor= t), + VMSTATE_UINT16_ARRAY(gsi_pirq, XenEvtchnState, GSI_NUM_PINS), + VMSTATE_UINT64_ARRAY(pirq_inuse, XenEvtchnState, + DIV_ROUND_UP(MAX_XEN_PIRQ, 64)), VMSTATE_END_OF_LIST() } }; @@ -247,6 +276,21 @@ static void xen_evtchn_register_types(void) =20 type_init(xen_evtchn_register_types) =20 +static int pirq_bind_port(XenEvtchnState *s, int pirq, uint16_t port) +{ + assert(pirq < MAX_XEN_PIRQ); + + if (port && s->pirq[pirq].port) { + return -EBUSY; + } + + s->pirq[pirq].port =3D port; + trace_kvm_xen_bind_pirq(pirq, port); + + /* XX: We need to unmask MSI here, when we get to that */ + return 0; +} + static int set_callback_pci_intx(XenEvtchnState *s, uint64_t param) { PCMachineState *pcms =3D PC_MACHINE(qdev_get_machine()); @@ -881,6 +925,10 @@ static int close_port(XenEvtchnState *s, evtchn_port_t= port) case EVTCHNSTAT_closed: return -ENOENT; =20 + case EVTCHNSTAT_pirq: + pirq_bind_port(s, p->type_val, 0); + break; + case EVTCHNSTAT_virq: kvm_xen_set_vcpu_virq(virq_is_global(p->type_val) ? 0 : p->vcpu, p->type_val, 0); @@ -1075,6 +1123,35 @@ int xen_evtchn_bind_virq_op(struct evtchn_bind_virq = *virq) return ret; } =20 +int xen_evtchn_bind_pirq_op(struct evtchn_bind_pirq *pirq) +{ + XenEvtchnState *s =3D xen_evtchn_singleton; + int ret; + + if (!s) { + return -ENOTSUP; + } + + if (pirq->pirq >=3D MAX_XEN_PIRQ) { + return -EINVAL; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + ret =3D allocate_port(s, 0, EVTCHNSTAT_pirq, pirq->pirq, + &pirq->port); + if (ret) { + return ret; + } + + ret =3D pirq_bind_port(s, pirq->pirq, pirq->port); + if (ret) { + free_port(s, pirq->port); + pirq->port =3D 0; + } + return ret; +} + int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi) { XenEvtchnState *s =3D xen_evtchn_singleton; @@ -1301,29 +1378,207 @@ int xen_evtchn_set_port(uint16_t port) return ret; } =20 +#define pirq_inuse_word(s, pirq) (s->pirq_inuse[((pirq) / 64)]) +#define pirq_inuse_bit(pirq) (1ULL << ((pirq) & 63)) + +#define pirq_inuse(s, pirq) (pirq_inuse_word(s, pirq) & pirq_inuse_bit(pir= q)) + +static int allocate_pirq(XenEvtchnState *s, int type, int gsi) +{ + uint16_t pirq; + + /* Preserve the allocation strategy that Xen has. It looks like + * we *never* give out PIRQ 0-15, we give out 16-nr_irqs_gsi only + * to GSIs (counting up from 16), and then we count backwards from + * the top for MSIs or when the GSI space is exhausted. */ + if (type =3D=3D MAP_PIRQ_TYPE_GSI) { + for (pirq =3D 16 ; pirq < GSI_NUM_PINS; pirq++) { + if (pirq_inuse(s, pirq)) { + continue; + } + + /* Found it */ + goto found; + } + } + for (pirq =3D MAX_XEN_PIRQ - 1; pirq >=3D GSI_NUM_PINS; pirq--) { + /* Skip whole words at a time when they're full */ + if (pirq_inuse_word(s, pirq) =3D=3D UINT64_MAX) { + pirq &=3D ~63ULL; + continue; + } + if (pirq_inuse(s, pirq)) { + continue; + } + + goto found; + } + return -ENOSPC; + + found: + pirq_inuse_word(s, pirq) |=3D pirq_inuse_bit(pirq); + if (gsi >=3D 0) { + assert(gsi <=3D GSI_NUM_PINS); + s->gsi_pirq[gsi] =3D pirq; + } + s->pirq[pirq].gsi =3D gsi; + return pirq; +} + int xen_physdev_map_pirq(struct physdev_map_pirq *map) { - return -ENOTSUP; + XenEvtchnState *s =3D xen_evtchn_singleton; + int pirq =3D map->pirq; + int gsi =3D map->index; + + if (!s) { + return -ENOTSUP; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + if (map->domid !=3D DOMID_SELF && map->domid !=3D xen_domid) { + return -EPERM; + } + if (map->type !=3D MAP_PIRQ_TYPE_GSI) { + return -EINVAL; + } + if (gsi < 0 || gsi >=3D GSI_NUM_PINS) { + return -EINVAL; + } + + if (pirq < 0) { + pirq =3D allocate_pirq(s, map->type, gsi); + if (pirq < 0) { + return pirq; + } + map->pirq =3D pirq; + } else if (pirq > MAX_XEN_PIRQ) { + return -EINVAL; + } else { + /* User specified a valid-looking PIRQ#. Allow it if it is + * allocated and not yet bound, or if it is unallocated */ + if (pirq_inuse(s, pirq)) { + if (s->pirq[pirq].gsi !=3D IRQ_UNBOUND) { + return -EBUSY; + } + } else { + /* If it was unused, mark it used now. */ + pirq_inuse_word(s, pirq) |=3D pirq_inuse_bit(pirq); + } + /* Set the mapping in both directions. */ + s->pirq[pirq].gsi =3D gsi; + s->gsi_pirq[gsi] =3D pirq; + } + + trace_kvm_xen_map_pirq(pirq, gsi); + return 0; } =20 int xen_physdev_unmap_pirq(struct physdev_unmap_pirq *unmap) { - return -ENOTSUP; + XenEvtchnState *s =3D xen_evtchn_singleton; + int pirq =3D unmap->pirq; + int gsi; + + if (!s) { + return -ENOTSUP; + } + + if (unmap->domid !=3D DOMID_SELF && unmap->domid !=3D xen_domid) + return -EPERM; + if (pirq < 0 || pirq >=3D MAX_XEN_PIRQ) + return -EINVAL; + + QEMU_LOCK_GUARD(&s->port_lock); + + if (!pirq_inuse(s, pirq)) { + return -ENOENT; + } + + gsi =3D s->pirq[pirq].gsi; + + /* We can only unmap GSI PIRQs */ + if (gsi < 0) { + return -EINVAL; + } + + s->gsi_pirq[gsi] =3D 0; + s->pirq[pirq].gsi =3D IRQ_UNBOUND; /* Doesn't actually matter because:= */ + pirq_inuse_word(s, pirq) &=3D ~pirq_inuse_bit(pirq); + + trace_kvm_xen_unmap_pirq(pirq, gsi); + return 0; } =20 int xen_physdev_eoi_pirq(struct physdev_eoi *eoi) { - return -ENOTSUP; + XenEvtchnState *s =3D xen_evtchn_singleton; + int pirq =3D eoi->irq; + int gsi; + + if (!s) { + return -ENOTSUP; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + if (!pirq_inuse(s, pirq)) { + return -ENOENT; + } + + gsi =3D s->pirq[pirq].gsi; + if (gsi < 0) { + return -EINVAL; + } + + // XX: Reassert a level IRQ if needed */ + return 0; } =20 int xen_physdev_query_pirq(struct physdev_irq_status_query *query) { - return -ENOTSUP; + XenEvtchnState *s =3D xen_evtchn_singleton; + int pirq =3D query->irq; + + if (!s) { + return -ENOTSUP; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + if (!pirq_inuse(s, pirq)) { + return -ENOENT; + } + + if (s->pirq[pirq].gsi >=3D 0) { + query->flags =3D XENIRQSTAT_needs_eoi; + } else { + query->flags =3D 0; + } + + return 0; } =20 int xen_physdev_get_free_pirq(struct physdev_get_free_pirq *get) { - return -ENOTSUP; + XenEvtchnState *s =3D xen_evtchn_singleton; + int pirq; + + if (!s) { + return -ENOTSUP; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + pirq =3D allocate_pirq(s, get->type, IRQ_UNBOUND); + if (pirq < 0) { + return pirq; + } + + get->pirq =3D pirq; + trace_kvm_xen_get_free_pirq(pirq, get->type); + return 0; } =20 struct xenevtchn_handle *xen_be_evtchn_open(void) diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h index ccf58aa796..2c12506cc2 100644 --- a/hw/i386/kvm/xen_evtchn.h +++ b/hw/i386/kvm/xen_evtchn.h @@ -48,6 +48,7 @@ struct evtchn_status; struct evtchn_close; struct evtchn_unmask; struct evtchn_bind_virq; +struct evtchn_bind_pirq; struct evtchn_bind_ipi; struct evtchn_send; struct evtchn_alloc_unbound; @@ -58,6 +59,7 @@ int xen_evtchn_status_op(struct evtchn_status *status); int xen_evtchn_close_op(struct evtchn_close *close); int xen_evtchn_unmask_op(struct evtchn_unmask *unmask); int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq); +int xen_evtchn_bind_pirq_op(struct evtchn_bind_pirq *pirq); int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi); int xen_evtchn_send_op(struct evtchn_send *send); int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc); diff --git a/meson.build b/meson.build index 72eec9c68a..8a58c381eb 100644 --- a/meson.build +++ b/meson.build @@ -2943,6 +2943,7 @@ if have_system 'hw/i2c', 'hw/i386', 'hw/i386/xen', + 'hw/i386/kvm', 'hw/ide', 'hw/input', 'hw/intc', diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c index 3fa58e33bd..c956390e2c 100644 --- a/target/i386/kvm/xen-emu.c +++ b/target/i386/kvm/xen-emu.c @@ -1215,6 +1215,21 @@ static bool kvm_xen_hcall_evtchn_op(struct kvm_xen_e= xit *exit, X86CPU *cpu, } break; } + case EVTCHNOP_bind_pirq: { + struct evtchn_bind_pirq pirq; + + qemu_build_assert(sizeof(pirq) =3D=3D 12); + if (kvm_copy_from_gva(cs, arg, &pirq, sizeof(pirq))) { + err =3D -EFAULT; + break; + } + + err =3D xen_evtchn_bind_pirq_op(&pirq); + if (!err && kvm_copy_to_gva(cs, arg, &pirq, sizeof(pirq))) { + err =3D -EFAULT; + } + break; + } case EVTCHNOP_bind_ipi: { struct evtchn_bind_ipi ipi; =20 --=20 2.35.3 From nobody Fri Apr 19 01:53:53 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1673656786866779.4665018241578; Fri, 13 Jan 2023 16:39:46 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pGUa9-0004jD-Pe; Fri, 13 Jan 2023 19:39:38 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUa1-0004hR-HX for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:29 -0500 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZy-0005NM-FH for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:29 -0500 Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by desiato.infradead.org with esmtpsa (Exim 4.96 #2 (Red Hat Linux)) id 1pGUZf-004X3t-2C; Sat, 14 Jan 2023 00:39:11 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZk-001C2K-Tf; Sat, 14 Jan 2023 00:39:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=8hNGFMyfTFAFgJuKdemn2tiMcclWhMauUWQBow9Js6M=; b=g/uP+I6LsToSzpRfzg+8OHWCpO PTWVT6hIIHudgtSDG5pLmufz6okx8uZyUPpoKJ1wBi29uPt+DIfShkdSafBlljAqrZ8krN51nfE83 Klb9KamI5aN82UsiuBwavRPIAogXIFc5PsOUW9jP1HksFeGOlQvTVb/jW+gvZ9d+Nq9lCZnYp4u2+ dC7f+3uztzNTh994HPS3VnPazkTbxYOm/bMbrgb6Fe7dvfkp5d+F4lhpzHbnWUqgAySHHp+tdyJty XBvzyNgfBy4wpJWdcKuOmnsLwZBL+hAq1m9/P3KTeTACFponFdSNq37nyJBpXqhJ8UGaReN6MQkTL +K6kzUCA==; From: David Woodhouse To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Paul Durrant , Joao Martins , Ankur Arora , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Juan Quintela , "Dr . David Alan Gilbert" , Claudio Fontana , Julien Grall , "Michael S. Tsirkin" , arcel Apfelbaum Subject: [RFC PATCH 3/5] hw/xen: Support GSI mapping to PIRQ Date: Sat, 14 Jan 2023 00:39:07 +0000 Message-Id: <20230114003909.284331-4-dwmw2@infradead.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230114003909.284331-1-dwmw2@infradead.org> References: <20230114003909.284331-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SRS-Rewrite: SMTP reverse-path rewritten from by desiato.infradead.org. See http://www.infradead.org/rpr.html Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; envelope-from=BATV+3a1a5416dcf0d1877a74+7083+infradead.org+dwmw2@desiato.srs.infradead.org; helo=desiato.infradead.org X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1673656789967100007 Content-Type: text/plain; charset="utf-8" From: David Woodhouse If I advertise XENFEAT_hvm_pirqs then a guest now boots successfully as long as I tell it 'pci=3Dnomsi'. [root@localhost ~]# cat /proc/interrupts CPU0 0: 52 IO-APIC 2-edge timer 1: 16 xen-pirq 1-ioapic-edge i8042 4: 1534 xen-pirq 4-ioapic-edge ttyS0 8: 1 xen-pirq 8-ioapic-edge rtc0 9: 0 xen-pirq 9-ioapic-level acpi 11: 5648 xen-pirq 11-ioapic-level ahci[0000:00:04.0] 12: 257 xen-pirq 12-ioapic-edge i8042 ... Signed-off-by: David Woodhouse --- hw/i386/kvm/xen_evtchn.c | 38 +++++++++++++++++++++++++++++++++++++- hw/i386/kvm/xen_evtchn.h | 2 ++ hw/i386/x86.c | 15 +++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c index 82250daecb..18c88229ab 100644 --- a/hw/i386/kvm/xen_evtchn.c +++ b/hw/i386/kvm/xen_evtchn.c @@ -143,6 +143,7 @@ struct XenEvtchnState { uint16_t gsi_pirq[GSI_NUM_PINS]; /* Bitmap of allocated PIRQs (serialized) */ uint64_t pirq_inuse[DIV_ROUND_UP(MAX_XEN_PIRQ, 64)]; + uint32_t pirq_gsi_set; =20 /* Per-PIRQ information (rebuilt on migration) */ struct pirq_info pirq[MAX_XEN_PIRQ]; @@ -208,6 +209,7 @@ static const VMStateDescription xen_evtchn_vmstate =3D { VMSTATE_UINT16_ARRAY(gsi_pirq, XenEvtchnState, GSI_NUM_PINS), VMSTATE_UINT64_ARRAY(pirq_inuse, XenEvtchnState, DIV_ROUND_UP(MAX_XEN_PIRQ, 64)), + VMSTATE_UINT32(pirq_gsi_set, XenEvtchnState), VMSTATE_END_OF_LIST() } }; @@ -1425,6 +1427,35 @@ static int allocate_pirq(XenEvtchnState *s, int type= , int gsi) return pirq; } =20 +bool xen_evtchn_set_gsi(int gsi, int level) +{ + XenEvtchnState *s =3D xen_evtchn_singleton; + int pirq; + + if (!s || gsi < 0 || gsi > GSI_NUM_PINS) { + return false; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + pirq =3D s->gsi_pirq[gsi]; + if (!pirq) { + return false; + } + + if (level) { + int port =3D s->pirq[pirq].port; + + s->pirq_gsi_set |=3D (1U << gsi); + if (port) { + set_port_pending(s, port); + } + } else { + s->pirq_gsi_set &=3D ~(1U << gsi); + } + return true; +} + int xen_physdev_map_pirq(struct physdev_map_pirq *map) { XenEvtchnState *s =3D xen_evtchn_singleton; @@ -1531,8 +1562,13 @@ int xen_physdev_eoi_pirq(struct physdev_eoi *eoi) if (gsi < 0) { return -EINVAL; } + if (s->pirq_gsi_set & (1U << gsi)) { + int port =3D s->pirq[pirq].port; + if (port) { + set_port_pending(s, port); + } + } =20 - // XX: Reassert a level IRQ if needed */ return 0; } =20 diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h index 2c12506cc2..dba9d6b021 100644 --- a/hw/i386/kvm/xen_evtchn.h +++ b/hw/i386/kvm/xen_evtchn.h @@ -24,6 +24,8 @@ void xen_evtchn_set_callback_level(int level); =20 int xen_evtchn_set_port(uint16_t port); =20 +bool xen_evtchn_set_gsi(int gsi, int level); + /* * These functions mirror the libxenevtchn library API, providing the QEMU * backend side of "interdomain" event channels. diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 78cc131926..201fd5626c 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -61,6 +61,10 @@ #include CONFIG_DEVICES #include "kvm/kvm_i386.h" =20 +#ifdef CONFIG_XEN_EMU +#include "hw/i386/kvm/xen_evtchn.h" +#endif + /* Physical Address of PVH entry point read from kernel ELF NOTE */ static size_t pvh_start_addr; =20 @@ -608,6 +612,17 @@ void gsi_handler(void *opaque, int n, int level) } /* fall through */ case ISA_NUM_IRQS ... IOAPIC_NUM_PINS - 1: +#ifdef CONFIG_XEN_EMU + /* + * Xen delivers the GSI to the Legacy PIC (not that Legacy PIC + * routing actually works properly under Xen). And then to + * *either* the PIRQ handling or the I/OAPIC depending on + * whether the former wants it. + */ + if (xen_evtchn_set_gsi(n, level)) { + break; + } +#endif qemu_set_irq(s->ioapic_irq[n], level); break; case IO_APIC_SECONDARY_IRQBASE --=20 2.35.3 From nobody Fri Apr 19 01:53:53 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1673656842821545.5241076300952; Fri, 13 Jan 2023 16:40:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pGUa6-0004iy-HG; Fri, 13 Jan 2023 19:39:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUa0-0004gv-DF for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:28 -0500 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZy-0005NN-EC for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:28 -0500 Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by desiato.infradead.org with esmtpsa (Exim 4.96 #2 (Red Hat Linux)) id 1pGUZf-004X3u-2C; Sat, 14 Jan 2023 00:39:10 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZk-001C2O-Up; Sat, 14 Jan 2023 00:39:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=0BzRiPtT6Te/hfyx5tNsli16NvieteYxvnY7I5GXBoo=; b=GzhQbxnyhJiYcaVfOJ8utxNMPj x5ISbUeNB3Hd/qjf8102Z/e2QObt/0qPNoo6BAg+Sj+YP2FhS4pcQd/qd7SXM1xIjO3J/bUQxbQFb CYRZIGUwbOQIieXuwqQvDIsYPa/S3BKPpCdsEhPGyGwH/4POC0z4dCNWsz4TvuXrRHSgfsBvVlcKy nLE/URkJR5Fp0CyPkJZFMO5KTjUfBlQXYA6BBdHf9fr1CWi86SbGfqYyAYDADYYjlSJX0Jd/HeQ++ tI6E0jdz/ZQz/Dnhivxu2YqJbje5BgfZ4XvrJ71u3fcIhzEwbe1N5ArKp9oYvGo5SV79yvK5h2If3 Pmm26gIQ==; From: David Woodhouse To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Paul Durrant , Joao Martins , Ankur Arora , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Juan Quintela , "Dr . David Alan Gilbert" , Claudio Fontana , Julien Grall , "Michael S. Tsirkin" , arcel Apfelbaum Subject: [RFC PATCH 4/5] hw/xen: [FIXME] Avoid deadlock in xen_evtchn_set_gsi() Date: Sat, 14 Jan 2023 00:39:08 +0000 Message-Id: <20230114003909.284331-5-dwmw2@infradead.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230114003909.284331-1-dwmw2@infradead.org> References: <20230114003909.284331-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SRS-Rewrite: SMTP reverse-path rewritten from by desiato.infradead.org. See http://www.infradead.org/rpr.html Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; envelope-from=BATV+3a1a5416dcf0d1877a74+7083+infradead.org+dwmw2@desiato.srs.infradead.org; helo=desiato.infradead.org X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1673656843602100001 Content-Type: text/plain; charset="utf-8" From: David Woodhouse Signed-off-by: David Woodhouse --- hw/i386/kvm/xen_evtchn.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c index 18c88229ab..c4103ee98b 100644 --- a/hw/i386/kvm/xen_evtchn.c +++ b/hw/i386/kvm/xen_evtchn.c @@ -1436,6 +1436,14 @@ bool xen_evtchn_set_gsi(int gsi, int level) return false; } =20 + /* + * XXX: We access this without locking. Because we'd deadlock + * if it was the callback_gsi. Do something cleverer. + */ + if (gsi && gsi =3D=3D s->callback_gsi) { + return false; + } + QEMU_LOCK_GUARD(&s->port_lock); =20 pirq =3D s->gsi_pirq[gsi]; --=20 2.35.3 From nobody Fri Apr 19 01:53:53 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1673656850373754.126603009407; Fri, 13 Jan 2023 16:40:50 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pGUa5-0004i7-4L; Fri, 13 Jan 2023 19:39:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZz-0004gI-0x for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:27 -0500 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pGUZv-0005Mc-Lu for qemu-devel@nongnu.org; Fri, 13 Jan 2023 19:39:26 -0500 Received: from i7.infradead.org ([2001:8b0:10b:1:21e:67ff:fecb:7a92]) by casper.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZy-006abv-Ey; Sat, 14 Jan 2023 00:39:26 +0000 Received: from dwoodhou by i7.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUZk-001C2S-Vu; Sat, 14 Jan 2023 00:39:13 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Reply-To:Content-ID:Content-Description; bh=kHw7tETYwFwxNEq4tlw8FwStK2cp7IVPRKCbN8zHAro=; b=GQNCxeTXLN4PKcDwNkoHei3XI9 hEMcSEG4B4iX2ycunjjIGfwIQu4jo+tTGK7y6Zx4l0/FAuPxqYa37fGIdV7HKKbSsY0Qj49NJX89y 0IbwTDCFXHVY0DULuO1nXr8NNEkpnYYm4qunH1GfghKnr9k+oqTjXP6lU9gjv1M7T91DtP+YRmSHE 6qmAmwi48y0n9LOylHghbJ0dtLutiWlxZ/gkPDYSE07XqzHooVcJBADqG/P8eDEEIRMDXeLnxK8iq tJy2K09YAftScSoktShoAcOv892vmGHWJSenySQgd1YTwyNnab/ieJICVKcQZKbbHRLQpz+POWtN+ bf/oxzag==; From: David Woodhouse To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Paul Durrant , Joao Martins , Ankur Arora , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Juan Quintela , "Dr . David Alan Gilbert" , Claudio Fontana , Julien Grall , "Michael S. Tsirkin" , arcel Apfelbaum Subject: [RFC PATCH 5/5] hw/xen: Support MSI mapping to PIRQ Date: Sat, 14 Jan 2023 00:39:09 +0000 Message-Id: <20230114003909.284331-6-dwmw2@infradead.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230114003909.284331-1-dwmw2@infradead.org> References: <20230114003909.284331-1-dwmw2@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2001:8b0:10b:1236::1; envelope-from=BATV+cc7f48ec5f75d1861b59+7083+infradead.org+dwmw2@casper.srs.infradead.org; helo=casper.infradead.org X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1673656855780100001 From: David Woodhouse The way that Xen handles MSI PIRQs is kind of awful. There is a special MSI message which targets a PIRQ. The vector in the low bits of data must be zero. The low 8 bits of the PIRQ# are in the destination ID field, the extended destination ID field is unused, and instead the high bits of the PIRQ# are in the high 32 bits of the address. Using the high bits of the address means that we can't intercept and translate these messages in kvm_send_msi(), because they won't be caught by the APIC =E2=80=94 addresses like 0x1000fee46000 aren't in the APIC's ra= nge. So we catch them in pci_msi_trigger() instead, and deliver the event channel directly. That isn't even the worst part. The worst part is that Xen snoops on writes to devices' MSI vectors while they are *masked*. When a MSI message is written which looks like it targets a PIRQ, it remembers the device and vector for later. When the guest makes a hypercall to bind that PIRQ# (snooped from a marked MSI vector) to an event channel port, Xen *unmasks* that MSI vector on the device. Xen guests using PIRQ delivery of MSI don't ever actually unmask the MSI for themselves. Now that this is working we can finally enable XENFEAT_hvm_pirqs and let the guest use it all. 0: 36 0 IO-APIC 2-edge timer 1: 0 16 xen-pirq 1-ioapic-edge i8042 4: 0 960 xen-pirq 4-ioapic-edge ttyS0 8: 1 0 xen-pirq 8-ioapic-edge rtc0 9: 0 0 xen-pirq 9-ioapic-level acpi 12: 257 0 xen-pirq 12-ioapic-edge i8042 14: 0 0 IO-APIC 14-edge ata_piix 15: 0 0 IO-APIC 15-edge ata_piix 24: 11667 0 xen-percpu -virq timer0 25: 3074 0 xen-percpu -ipi resched0 26: 0 0 xen-percpu -ipi callfunc0 27: 0 0 xen-percpu -virq debug0 28: 488 0 xen-percpu -ipi callfuncsingle0 29: 0 0 xen-percpu -ipi spinlock0 30: 0 14209 xen-percpu -virq timer1 31: 0 12386 xen-percpu -ipi resched1 32: 0 0 xen-percpu -ipi callfunc1 33: 0 0 xen-percpu -virq debug1 34: 0 401 xen-percpu -ipi callfuncsingle1 35: 0 0 xen-percpu -ipi spinlock1 36: 8 0 xen-dyn -event xenbus 37: 0 5693 xen-pirq -msi ahci[0000:00:04.0] Signed-off-by: David Woodhouse --- hw/i386/kvm/xen-stubs.c | 11 +++ hw/i386/kvm/xen_evtchn.c | 141 ++++++++++++++++++++++++++++++++++++- hw/i386/kvm/xen_evtchn.h | 7 ++ hw/pci/msi.c | 13 ++++ hw/pci/msix.c | 7 +- hw/pci/pci.c | 14 ++++ target/i386/kvm/kvm.c | 12 +++- target/i386/kvm/kvm_i386.h | 2 + target/i386/kvm/xen-emu.c | 3 +- 9 files changed, 202 insertions(+), 8 deletions(-) diff --git a/hw/i386/kvm/xen-stubs.c b/hw/i386/kvm/xen-stubs.c index 6f433dc995..8b64fcf6c5 100644 --- a/hw/i386/kvm/xen-stubs.c +++ b/hw/i386/kvm/xen-stubs.c @@ -12,6 +12,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" +#include "xen_evtchn.h" =20 EvtchnInfoList *qmp_xen_event_list(Error **errp) { @@ -23,3 +24,13 @@ void qmp_xen_event_inject(uint32_t port, Error **errp) { error_setg(errp, "Xen event channel emulation not enabled"); } + +void xen_evtchn_snoop_msi(PCIDevice *dev, bool is_msix, unsigned int vecto= r, + uint64_t addr, uint32_t data, bool is_masked) +{ +} + +bool xen_evtchn_deliver_pirq_msi(uint64_t address, uint32_t data) +{ + return false; +} diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c index c4103ee98b..8e128ff8bc 100644 --- a/hw/i386/kvm/xen_evtchn.c +++ b/hw/i386/kvm/xen_evtchn.c @@ -30,9 +30,10 @@ #include "hw/i386/x86.h" #include "hw/i386/pc.h" #include "hw/pci/pci.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" #include "hw/irq.h" #include "hw/xen/xen_backend_ops.h" - #include "xen_evtchn.h" #include "xen_overlay.h" #include "xen_xenstore.h" @@ -45,6 +46,9 @@ #include "standard-headers/xen/memory.h" #include "standard-headers/xen/hvm/params.h" =20 +/* XX: For kvm_update_msi_routes_all() */ +#include "target/i386/kvm/kvm_i386.h" + #define TYPE_XEN_EVTCHN "xen-evtchn" OBJECT_DECLARE_SIMPLE_TYPE(XenEvtchnState, XEN_EVTCHN) =20 @@ -121,6 +125,10 @@ struct xenevtchn_handle { struct pirq_info { int gsi; uint16_t port; + PCIDevice *dev; + int vector; + bool is_msix; + bool is_masked; }; =20 struct XenEvtchnState { @@ -289,7 +297,18 @@ static int pirq_bind_port(XenEvtchnState *s, int pirq,= uint16_t port) s->pirq[pirq].port =3D port; trace_kvm_xen_bind_pirq(pirq, port); =20 - /* XX: We need to unmask MSI here, when we get to that */ + if (port && s->pirq[pirq].gsi =3D=3D IRQ_MSI_EMU) { + if (s->pirq[pirq].is_msix) { + msix_set_mask(s->pirq[pirq].dev, s->pirq[pirq].vector, + false); + } else { + msi_set_mask(s->pirq[pirq].dev, s->pirq[pirq].vector, + false, &error_fatal); + } + } + if (!port) { + /* XX: Want to invalidate MSI routing here but we'd deadlock */ + } return 0; } =20 @@ -1464,6 +1483,115 @@ bool xen_evtchn_set_gsi(int gsi, int level) return true; } =20 +static uint32_t msi_pirq_target(uint64_t addr, uint32_t data) +{ + /* The vector (in low 8 bits of data) must be zero */ + if (data & 0xff) + return 0; + + uint32_t pirq =3D (addr & 0xff000) >> 12; + pirq |=3D (addr >> 32) & 0xffffff00; + + return pirq; +} + +void xen_evtchn_snoop_msi(PCIDevice *dev, bool is_msix, unsigned int vecto= r, + uint64_t addr, uint32_t data, bool is_masked) +{ + XenEvtchnState *s =3D xen_evtchn_singleton; + uint32_t pirq; + + if (!s) { + return; + } + + pirq =3D msi_pirq_target(addr, data); + if (!pirq || pirq >=3D MAX_XEN_PIRQ) { + return; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + if (s->pirq[pirq].gsi !=3D IRQ_UNBOUND && s->pirq[pirq].gsi !=3D IRQ_M= SI_EMU) { + return; + } + + if (s->pirq[pirq].dev !=3D dev) { + if (s->pirq[pirq].dev) { + object_unref(OBJECT(s->pirq[pirq].dev)); + } + object_ref(OBJECT(dev)); + s->pirq[pirq].dev =3D dev; + } + + s->pirq[pirq].gsi =3D IRQ_MSI_EMU; + s->pirq[pirq].is_msix =3D is_msix; + s->pirq[pirq].vector =3D vector; + s->pirq[pirq].is_masked =3D is_masked; + +} + +bool xen_evtchn_translate_pirq_msi(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ + XenEvtchnState *s =3D xen_evtchn_singleton; + uint32_t pirq, port; + CPUState *cpu; + + if (!s) { + return false; + } + + pirq =3D msi_pirq_target(address, data); + if (!pirq || pirq >=3D MAX_XEN_PIRQ) { + return false; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + port =3D s->pirq[pirq].port; + if (!valid_port(port)) { + return false; + } + + cpu =3D qemu_get_cpu(s->port_table[port].vcpu); + if (!cpu) { + return false; + } + + route->type =3D KVM_IRQ_ROUTING_XEN_EVTCHN; + route->u.xen_evtchn.port =3D port; + route->u.xen_evtchn.vcpu =3D kvm_arch_vcpu_id(cpu); + route->u.xen_evtchn.priority =3D KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVE= L; + + return true; +} + +bool xen_evtchn_deliver_pirq_msi(uint64_t address, uint32_t data) +{ + XenEvtchnState *s =3D xen_evtchn_singleton; + uint32_t pirq, port; + + if (!s) { + return false; + } + + pirq =3D msi_pirq_target(address, data); + if (!pirq || pirq >=3D MAX_XEN_PIRQ) { + return false; + } + + QEMU_LOCK_GUARD(&s->port_lock); + + port =3D s->pirq[pirq].port; + if (!valid_port(port)) { + return false; + } + + set_port_pending(s, port); + return true; +} + int xen_physdev_map_pirq(struct physdev_map_pirq *map) { XenEvtchnState *s =3D xen_evtchn_singleton; @@ -1529,9 +1657,10 @@ int xen_physdev_unmap_pirq(struct physdev_unmap_pirq= *unmap) if (pirq < 0 || pirq >=3D MAX_XEN_PIRQ) return -EINVAL; =20 - QEMU_LOCK_GUARD(&s->port_lock); + qemu_mutex_lock(&s->port_lock); =20 if (!pirq_inuse(s, pirq)) { + qemu_mutex_unlock(&s->port_lock); return -ENOENT; } =20 @@ -1539,6 +1668,7 @@ int xen_physdev_unmap_pirq(struct physdev_unmap_pirq = *unmap) =20 /* We can only unmap GSI PIRQs */ if (gsi < 0) { + qemu_mutex_unlock(&s->port_lock); return -EINVAL; } =20 @@ -1547,6 +1677,11 @@ int xen_physdev_unmap_pirq(struct physdev_unmap_pirq= *unmap) pirq_inuse_word(s, pirq) &=3D ~pirq_inuse_bit(pirq); =20 trace_kvm_xen_unmap_pirq(pirq, gsi); + qemu_mutex_unlock(&s->port_lock); + + if (gsi =3D=3D IRQ_MSI_EMU) + kvm_update_msi_routes_all(NULL, true, 0, 0); + return 0; } =20 diff --git a/hw/i386/kvm/xen_evtchn.h b/hw/i386/kvm/xen_evtchn.h index dba9d6b021..3f8b757194 100644 --- a/hw/i386/kvm/xen_evtchn.h +++ b/hw/i386/kvm/xen_evtchn.h @@ -25,6 +25,13 @@ void xen_evtchn_set_callback_level(int level); int xen_evtchn_set_port(uint16_t port); =20 bool xen_evtchn_set_gsi(int gsi, int level); +void xen_evtchn_snoop_msi(PCIDevice *dev, bool is_msix, unsigned int vecto= r, + uint64_t addr, uint32_t data, bool is_masked); +struct kvm_irq_routing_entry; +bool xen_evtchn_translate_pirq_msi(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data); +bool xen_evtchn_deliver_pirq_msi(uint64_t address, uint32_t data); + =20 /* * These functions mirror the libxenevtchn library API, providing the QEMU diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 1cadf150bc..f09b7f3fca 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -24,6 +24,8 @@ #include "qemu/range.h" #include "qapi/error.h" =20 +#include "hw/i386/kvm/xen_evtchn.h" + /* PCI_MSI_ADDRESS_LO */ #define PCI_MSI_ADDRESS_LO_MASK (~0x3) =20 @@ -431,6 +433,17 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, u= int32_t val, int len) */ pci_device_deassert_intx(dev); =20 + if (xen_mode =3D=3D XEN_EMULATE) { + for (vector =3D 0; vector < msi_nr_vectors(flags); vector++) { + MSIMessage msg =3D msi_prepare_message(dev, vector); + + xen_evtchn_snoop_msi(dev, false, vector, msg.address, msg.data, + msi_is_masked(dev, vector)); + } + } + + + /* * nr_vectors might be set bigger than capable. So clamp it. * This is not legal by spec, so we can do anything we like, diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 9e70fcd6fa..afa77b8d71 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -26,6 +26,8 @@ #include "qapi/error.h" #include "trace.h" =20 +#include "hw/i386/kvm/xen_evtchn.h" + /* MSI enable bit and maskall bit are in byte 1 in FLAGS register */ #define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1) #define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8) @@ -105,16 +107,17 @@ bool msix_is_masked(PCIDevice *dev, unsigned int vect= or) static void msix_fire_vector_notifier(PCIDevice *dev, unsigned int vector, bool is_masked) { - MSIMessage msg; + MSIMessage msg =3D msi_get_message(dev, vector); int ret; =20 + xen_evtchn_snoop_msi(dev, true, vector, msg.address, msg.data, is_mask= ed); + if (!dev->msix_vector_use_notifier) { return; } if (is_masked) { dev->msix_vector_release_notifier(dev, vector); } else { - msg =3D msix_get_message(dev, vector); ret =3D dev->msix_vector_use_notifier(dev, vector, msg); assert(ret >=3D 0); } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index c2fb88f9a3..fdb8d4abc9 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -49,6 +49,9 @@ #include "qemu/cutils.h" #include "pci-internal.h" =20 +#include "hw/xen/xen.h" +#include "hw/i386/kvm/xen_evtchn.h" + //#define DEBUG_PCI #ifdef DEBUG_PCI # define PCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) @@ -318,6 +321,17 @@ static void pci_msi_trigger(PCIDevice *dev, MSIMessage= msg) { MemTxAttrs attrs =3D {}; =20 + /* + * Xen uses the high bits of the address to contain some of the bits + * of the PIRQ#. Therefore we can't just send the write cycle and + * trust that it's caught by the APIC at 0xfee00000 because the + * target of the write might be e.g. 0x0x1000fee46000 for PIRQ#4166. + * So we intercept the delivery here instead of in kvm_send_msi(). + */ + if (xen_mode =3D=3D XEN_EMULATE && + xen_evtchn_deliver_pirq_msi(msg.address, msg.data)) { + return; + } attrs.requester_id =3D pci_requester_id(dev); address_space_stl_le(&dev->bus_master_as, msg.address, msg.data, attrs, NULL); diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 76bdd9d7ea..6d307cdcad 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -43,6 +43,7 @@ #include "qemu/error-report.h" #include "qemu/memalign.h" #include "hw/i386/x86.h" +#include "hw/i386/kvm/xen_evtchn.h" #include "hw/i386/pc.h" #include "hw/i386/apic.h" #include "hw/i386/apic_internal.h" @@ -5640,6 +5641,13 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_= entry *route, } } =20 +#ifdef CONFIG_XEN_EMU + if (xen_mode =3D=3D XEN_EMULATE && + xen_evtchn_translate_pirq_msi(route, address, data)) { + return 0; + } +#endif + address =3D kvm_swizzle_msi_ext_dest_id(address); route->u.msi.address_hi =3D address >> VTD_MSI_ADDR_HI_SHIFT; route->u.msi.address_lo =3D address & VTD_MSI_ADDR_LO_MASK; @@ -5659,8 +5667,8 @@ struct MSIRouteEntry { static QLIST_HEAD(, MSIRouteEntry) msi_route_list =3D \ QLIST_HEAD_INITIALIZER(msi_route_list); =20 -static void kvm_update_msi_routes_all(void *private, bool global, - uint32_t index, uint32_t mask) +void kvm_update_msi_routes_all(void *private, bool global, + uint32_t index, uint32_t mask) { int cnt =3D 0, vector; MSIRouteEntry *entry; diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h index 6a5c24e3dc..e24753abfe 100644 --- a/target/i386/kvm/kvm_i386.h +++ b/target/i386/kvm/kvm_i386.h @@ -51,6 +51,8 @@ bool kvm_hv_vpindex_settable(void); bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp); =20 uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address); +void kvm_update_msi_routes_all(void *private, bool global, + uint32_t index, uint32_t mask); =20 bool kvm_enable_sgx_provisioning(KVMState *s); void kvm_request_xsave_components(X86CPU *cpu, uint64_t mask); diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c index c956390e2c..0f1a7c8edf 100644 --- a/target/i386/kvm/xen-emu.c +++ b/target/i386/kvm/xen-emu.c @@ -266,7 +266,8 @@ static bool kvm_xen_hcall_xen_version(struct kvm_xen_ex= it *exit, X86CPU *cpu, 1 << XENFEAT_auto_translated_physmap | 1 << XENFEAT_supervisor_mode_kernel | 1 << XENFEAT_hvm_callback_vector | - 1 << XENFEAT_hvm_safe_pvclock; + 1 << XENFEAT_hvm_safe_pvclock | + 1 << XENFEAT_hvm_pirqs; } =20 err =3D kvm_copy_to_gva(CPU(cpu), arg, &fi, sizeof(fi)); --=20 2.35.3