Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/812474/?format=api
{ "id": 812474, "url": "http://patchwork.ozlabs.org/api/patches/812474/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20170911171235.29331-18-clg@kaod.org/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170911171235.29331-18-clg@kaod.org>", "list_archive_url": null, "date": "2017-09-11T17:12:31", "name": "[RFC,v2,17/21] ppc/xive: add hcalls support", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "97f86885e42bfc73c5c3c5734e800f0950b414bd", "submitter": { "id": 68548, "url": "http://patchwork.ozlabs.org/api/people/68548/?format=api", "name": "Cédric Le Goater", "email": "clg@kaod.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20170911171235.29331-18-clg@kaod.org/mbox/", "series": [ { "id": 2526, "url": "http://patchwork.ozlabs.org/api/series/2526/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2526", "date": "2017-09-11T17:12:14", "name": "Guest exploitation of the XIVE interrupt controller (POWER9)", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/2526/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/812474/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/812474/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)", "Received": [ "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xrZb53Sj1z9s81\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 12 Sep 2017 03:26:09 +1000 (AEST)", "from localhost ([::1]:59338 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1drSTH-0002pF-El\n\tfor incoming@patchwork.ozlabs.org; Mon, 11 Sep 2017 13:26:07 -0400", "from eggs.gnu.org ([2001:4830:134:3::10]:35753)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <clg@kaod.org>) id 1drSIS-0001y2-U6\n\tfor qemu-devel@nongnu.org; Mon, 11 Sep 2017 13:15:05 -0400", "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <clg@kaod.org>) id 1drSIO-0004pY-Lh\n\tfor qemu-devel@nongnu.org; Mon, 11 Sep 2017 13:14:56 -0400", "from 1.mo2.mail-out.ovh.net ([46.105.63.121]:50444)\n\tby eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <clg@kaod.org>) id 1drSIO-0004om-8d\n\tfor qemu-devel@nongnu.org; Mon, 11 Sep 2017 13:14:52 -0400", "from player770.ha.ovh.net (b6.ovh.net [213.186.33.56])\n\tby mo2.mail-out.ovh.net (Postfix) with ESMTP id 4BEFCAB215\n\tfor <qemu-devel@nongnu.org>; Mon, 11 Sep 2017 19:14:51 +0200 (CEST)", "from zorba.kaod.org.com (LFbn-1-2231-173.w90-76.abo.wanadoo.fr\n\t[90.76.52.173]) (Authenticated sender: clg@kaod.org)\n\tby player770.ha.ovh.net (Postfix) with ESMTPSA id 13D143C0073;\n\tMon, 11 Sep 2017 19:14:44 +0200 (CEST)" ], "From": "=?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org>", "To": "qemu-ppc@nongnu.org, qemu-devel@nongnu.org,\n\tDavid Gibson <david@gibson.dropbear.id.au>,\n\tBenjamin Herrenschmidt <benh@kernel.crashing.org>,\n\tAlexey Kardashevskiy <aik@ozlabs.ru>, Alexander Graf <agraf@suse.de>", "Date": "Mon, 11 Sep 2017 19:12:31 +0200", "Message-Id": "<20170911171235.29331-18-clg@kaod.org>", "X-Mailer": "git-send-email 2.13.5", "In-Reply-To": "<20170911171235.29331-1-clg@kaod.org>", "References": "<20170911171235.29331-1-clg@kaod.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "X-Ovh-Tracer-Id": "14162413455515945811", "X-VR-SPAMSTATE": "OK", "X-VR-SPAMSCORE": "-100", "X-VR-SPAMCAUSE": "gggruggvucftvghtrhhoucdtuddrfeelledrgedtgdduudehucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm", "Content-Transfer-Encoding": "quoted-printable", "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]\n\t[fuzzy]", "X-Received-From": "46.105.63.121", "Subject": "[Qemu-devel] [RFC PATCH v2 17/21] ppc/xive: add hcalls support", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.21", "Precedence": "list", "List-Id": "<qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Cc": "=?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>" }, "content": "A set of Hypervisor's call are used to configure the interrupt sources\nand the event/notification queues of the guest:\n\n - H_INT_GET_SOURCE_INFO\n\n used to obtain the address of the MMIO page of the Event State\n Buffer (PQ bits) entry associated with the source.\n\n - H_INT_SET_SOURCE_CONFIG\n\n assigns a source to a \"target\".\n\n - H_INT_GET_SOURCE_CONFIG\n\n determines to which \"target\" and \"priority\" is assigned to a source\n\n - H_INT_GET_QUEUE_INFO\n\n returns the address of the notification management page associated\n with the specified \"target\" and \"priority\".\n\n - H_INT_SET_QUEUE_CONFIG\n\n sets or resets the event queue for a given \"target\" and \"priority\".\n It is also used to set the notification config associated with the\n queue, only unconditional notification for the moment. Reset is\n performed with a queue size of 0 and queueing is disabled in that\n case.\n\n - H_INT_GET_QUEUE_CONFIG\n\n returns the queue settings for a given \"target\" and \"priority\".\n\n - H_INT_RESET\n\n resets all of the partition's interrupt exploitation structures to\n their initial state, losing all configuration set via the hcalls\n H_INT_SET_SOURCE_CONFIG and H_INT_SET_QUEUE_CONFIG.\n\n - H_INT_SYNC\n\n issue a synchronisation on a source to make sure sure all\n notifications have reached their queue.\n\nCalls that still need to be addressed :\n\n H_INT_SET_OS_REPORTING_LINE\n H_INT_GET_OS_REPORTING_LINE\n\nSee the code for more documentation on each hcall.\n\nSigned-off-by: Cédric Le Goater <clg@kaod.org>\n---\n hw/intc/Makefile.objs | 2 +-\n hw/intc/spapr_xive_hcall.c | 876 ++++++++++++++++++++++++++++++++++++++++++++\n hw/ppc/spapr.c | 2 +\n include/hw/ppc/spapr.h | 15 +-\n include/hw/ppc/spapr_xive.h | 4 +\n 5 files changed, 897 insertions(+), 2 deletions(-)\n create mode 100644 hw/intc/spapr_xive_hcall.c", "diff": "diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs\nindex 2dae80bdf611..00a9aea2dd29 100644\n--- a/hw/intc/Makefile.objs\n+++ b/hw/intc/Makefile.objs\n@@ -35,7 +35,7 @@ obj-$(CONFIG_SH4) += sh_intc.o\n obj-$(CONFIG_XICS) += xics.o\n obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o\n obj-$(CONFIG_XICS_KVM) += xics_kvm.o\n-obj-$(CONFIG_XIVE_SPAPR) += spapr_xive.o\n+obj-$(CONFIG_XIVE_SPAPR) += spapr_xive.o spapr_xive_hcall.o\n obj-$(CONFIG_POWERNV) += xics_pnv.o\n obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o\n obj-$(CONFIG_S390_FLIC) += s390_flic.o\ndiff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c\nnew file mode 100644\nindex 000000000000..4c77b65683de\n--- /dev/null\n+++ b/hw/intc/spapr_xive_hcall.c\n@@ -0,0 +1,876 @@\n+/*\n+ * QEMU PowerPC sPAPR XIVE model\n+ *\n+ * Copyright (c) 2017, IBM Corporation.\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License, version 2, as\n+ * published by the Free Software Foundation.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, see <http://www.gnu.org/licenses/>.\n+ */\n+#include \"qemu/osdep.h\"\n+#include \"qemu/log.h\"\n+#include \"qapi/error.h\"\n+#include \"cpu.h\"\n+#include \"hw/ppc/spapr.h\"\n+#include \"hw/ppc/spapr_xive.h\"\n+#include \"hw/ppc/fdt.h\"\n+#include \"monitor/monitor.h\"\n+\n+#include \"xive-internal.h\"\n+\n+/*\n+ * TODO: check the valid priorities from the ranges listed in the\n+ * \"ibm,plat-res-int-priorities\" property. Be simple for the moment.\n+ */\n+static bool priority_is_valid(int priority)\n+{\n+ return priority >= 0 && priority < 8;\n+}\n+\n+/*\n+ * The H_INT_GET_SOURCE_INFO hcall() is used to obtain the logical\n+ * real address of the MMIO page through which the Event State Buffer\n+ * entry associated with the value of the \"lisn\" parameter is managed.\n+ *\n+ * Parameters:\n+ * Input\n+ * - \"flags\"\n+ * Bits 0-63 reserved\n+ * - \"lisn\" is per \"interrupts\", \"interrupt-map\", or\n+ * \"ibm,xive-lisn-ranges\" properties, or as returned by the\n+ * ibm,query-interrupt-source-number RTAS call, or as returned\n+ * by the H_ALLOCATE_VAS_WINDOW hcall\n+ *\n+ * Output\n+ * - R4: \"flags\"\n+ * Bits 0-59: Reserved\n+ * Bit 60: H_INT_ESB must be used for Event State Buffer\n+ * management\n+ * Bit 61: 1 == LSI 0 == MSI\n+ * Bit 62: the full function page supports trigger\n+ * Bit 63: Store EOI Supported\n+ * - R5: Logical Real address of full function Event State Buffer\n+ * management page, -1 if ESB hcall flag is set to 1.\n+ * - R6: Logical Real Address of trigger only Event State Buffer\n+ * management page or -1.\n+ * - R7: Power of 2 page size for the ESB management pages returned in\n+ * R5 and R6.\n+ */\n+static target_ulong h_int_get_source_info(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ sPAPRXive *xive = spapr->xive;\n+ XiveIVE *ive;\n+ target_ulong flags = args[0];\n+ target_ulong lisn = args[1];\n+ uint64_t mmio_base;\n+ ICSIRQState *irq;\n+ uint32_t srcno = lisn - spapr->ics->offset;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags) {\n+ return H_PARAMETER;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ ive = spapr_xive_get_ive(spapr->xive, srcno);\n+ if (!ive || !(ive->w & IVE_VALID)) {\n+ return H_P2;\n+ }\n+\n+ mmio_base = (uint64_t)xive->esb_base + (1ull << xive->esb_shift) * srcno;\n+ irq = &spapr->ics->irqs[srcno];\n+\n+ args[0] = 0;\n+ if (irq->flags & XICS_FLAGS_IRQ_LSI) {\n+ args[0] |= XIVE_SRC_LSI;\n+ }\n+ if (xive->flags & XIVE_SRC_TRIGGER) {\n+ args[0] |= XIVE_SRC_TRIGGER;\n+ }\n+\n+ if (xive->flags & XIVE_SRC_H_INT_ESB) {\n+ args[1] = -1; /* never used in QEMU */\n+ args[2] = -1;\n+ } else {\n+ args[1] = mmio_base;\n+ if (xive->flags & XIVE_SRC_TRIGGER) {\n+ args[2] = -1; /* No specific trigger page */\n+ } else {\n+ args[2] = -1; /* TODO: support for specific trigger page */\n+ }\n+ }\n+\n+ args[3] = xive->esb_shift;\n+\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_SET_SOURCE_CONFIG hcall() is used to assign a Logical\n+ * Interrupt Source to a target. The Logical Interrupt Source is\n+ * designated with the \"lisn\" parameter and the target is designated\n+ * with the \"target\" and \"priority\" parameters. Upon return from the\n+ * hcall(), no additional interrupts will be directed to the old EQ.\n+ *\n+ * TODO: The old EQ should be investigated for interrupts that\n+ * occurred prior to or during the hcall().\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-61: Reserved\n+ * Bit 62: set the \"eisn\" in the EA\n+ * Bit 63: masks the interrupt source in the hardware interrupt\n+ * control structure. An interrupt masked by this mechanism will\n+ * be dropped, but it's source state bits will still be\n+ * set. There is no race-free way of unmasking and restoring the\n+ * source. Thus this should only be used in interrupts that are\n+ * also masked at the source, and only in cases where the\n+ * interrupt is not meant to be used for a large amount of time\n+ * because no valid target exists for it for example\n+ * - \"lisn\" is per \"interrupts\", \"interrupt-map\", or\n+ * \"ibm,xive-lisn-ranges\" properties, or as returned by the\n+ * ibm,query-interrupt-source-number RTAS call, or as returned by\n+ * the H_ALLOCATE_VAS_WINDOW hcall\n+ * - \"target\" is per \"ibm,ppc-interrupt-server#s\" or\n+ * \"ibm,ppc-interrupt-gserver#s\"\n+ * - \"priority\" is a valid priority not in\n+ * \"ibm,plat-res-int-priorities\"\n+ * - \"eisn\" is the guest EISN associated with the \"lisn\"\n+ *\n+ * Output:\n+ * - None\n+ */\n+\n+#define XIVE_SRC_SET_EISN (1ull << (63 - 62))\n+#define XIVE_SRC_MASK (1ull << (63 - 63))\n+\n+static target_ulong h_int_set_source_config(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ XiveIVE *ive;\n+ uint64_t new_ive;\n+ target_ulong flags = args[0];\n+ target_ulong lisn = args[1];\n+ target_ulong target = args[2];\n+ target_ulong priority = args[3];\n+ target_ulong eisn = args[4];\n+ uint32_t eq_idx;\n+ uint32_t srcno = lisn - spapr->ics->offset;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags & ~(XIVE_SRC_SET_EISN | XIVE_SRC_MASK)) {\n+ return H_PARAMETER;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ ive = spapr_xive_get_ive(spapr->xive, srcno);\n+ if (!ive || !(ive->w & IVE_VALID)) {\n+ return H_P2;\n+ }\n+\n+ /* priority 0xff is used to reset the IVE */\n+ if (priority == 0xff) {\n+ new_ive = IVE_VALID | IVE_MASKED;\n+ goto out;\n+ }\n+\n+ new_ive = ive->w;\n+\n+ if (flags & XIVE_SRC_MASK) {\n+ new_ive = ive->w | IVE_MASKED;\n+ } else {\n+ new_ive = ive->w & ~IVE_MASKED;\n+ }\n+\n+ if (!priority_is_valid(priority)) {\n+ return H_P4;\n+ }\n+\n+ /* TODO: If the partition thread count is greater than the\n+ * hardware thread count, validate the \"target\" has a\n+ * corresponding hardware thread else return H_NOT_AVAILABLE.\n+ */\n+\n+ /* Validate that \"target\" is part of the list of threads allocated\n+ * to the partition. For that, find the EQ corresponding to the\n+ * target.\n+ */\n+ if (!spapr_xive_eq_for_target(spapr->xive, target, priority, &eq_idx)) {\n+ return H_P3;\n+ }\n+\n+ new_ive = SETFIELD(IVE_EQ_BLOCK, new_ive, 0ul);\n+ new_ive = SETFIELD(IVE_EQ_INDEX, new_ive, eq_idx);\n+\n+ if (flags & XIVE_SRC_SET_EISN) {\n+ new_ive = SETFIELD(IVE_EQ_DATA, new_ive, eisn);\n+ }\n+\n+out:\n+ /* TODO: handle syncs ? */\n+\n+ /* And update */\n+ ive->w = new_ive;\n+\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_GET_SOURCE_CONFIG hcall() is used to determine to which\n+ * target/priority pair is assigned to the specified Logical Interrupt\n+ * Source.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-63 Reserved\n+ * - \"lisn\" is per \"interrupts\", \"interrupt-map\", or\n+ * \"ibm,xive-lisn-ranges\" properties, or as returned by the\n+ * ibm,query-interrupt-source-number RTAS call, or as\n+ * returned by the H_ALLOCATE_VAS_WINDOW hcall\n+ *\n+ * Output:\n+ * - R4: Target to which the specified Logical Interrupt Source is\n+ * assigned\n+ * - R5: Priority to which the specified Logical Interrupt Source is\n+ * assigned\n+ * - R6: EISN for the specified Logical Interrupt Source (this will be\n+ * equivalent to the LISN if not changed by H_INT_SET_SOURCE_CONFIG)\n+ */\n+static target_ulong h_int_get_source_config(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ target_ulong flags = args[0];\n+ target_ulong lisn = args[1];\n+ XiveIVE *ive;\n+ XiveEQ *eq;\n+ uint32_t eq_idx;\n+ uint32_t srcno = lisn - spapr->ics->offset;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags) {\n+ return H_PARAMETER;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ ive = spapr_xive_get_ive(spapr->xive, srcno);\n+ if (!ive || !(ive->w & IVE_VALID)) {\n+ return H_P2;\n+ }\n+\n+ eq_idx = GETFIELD(IVE_EQ_INDEX, ive->w);\n+ eq = spapr_xive_get_eq(spapr->xive, eq_idx);\n+ if (!eq) {\n+ return H_HARDWARE;\n+ }\n+\n+ args[0] = GETFIELD(EQ_W6_NVT_INDEX, eq->w6);\n+\n+ if (ive->w & IVE_MASKED) {\n+ args[1] = 0xff;\n+ } else {\n+ args[1] = GETFIELD(EQ_W7_F0_PRIORITY, eq->w7);\n+ }\n+\n+ args[2] = GETFIELD(IVE_EQ_DATA, ive->w);\n+\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_GET_QUEUE_INFO hcall() is used to get the logical real\n+ * address of the notification management page associated with the\n+ * specified target and priority.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-63 Reserved\n+ * - \"target\" is per \"ibm,ppc-interrupt-server#s\" or\n+ * \"ibm,ppc-interrupt-gserver#s\"\n+ * - \"priority\" is a valid priority not in\n+ * \"ibm,plat-res-int-priorities\"\n+ *\n+ * Output:\n+ * - R4: Logical real address of notification page\n+ * - R5: Power of 2 page size of the notification page\n+ */\n+static target_ulong h_int_get_queue_info(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ target_ulong flags = args[0];\n+ target_ulong target = args[1];\n+ target_ulong priority = args[2];\n+ uint32_t eq_idx;\n+ XiveEQ *eq;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags) {\n+ return H_PARAMETER;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ if (!priority_is_valid(priority)) {\n+ return H_P3;\n+ }\n+\n+ /* Validate that \"target\" is part of the list of threads allocated\n+ * to the partition. For that, find the EQ corresponding to the\n+ * target.\n+ */\n+ if (!spapr_xive_eq_for_target(spapr->xive, target, priority, &eq_idx)) {\n+ return H_P2;\n+ }\n+\n+ /* TODO: If the partition thread count is greater than the\n+ * hardware thread count, validate the \"target\" has a\n+ * corresponding hardware thread else return H_NOT_AVAILABLE.\n+ */\n+\n+ eq = spapr_xive_get_eq(spapr->xive, eq_idx);\n+ if (!eq) {\n+ return H_HARDWARE;\n+ }\n+\n+ args[0] = -1; /* TODO: return ESn page */\n+ if (eq->w0 & EQ_W0_ENQUEUE) {\n+ args[1] = GETFIELD(EQ_W0_QSIZE, eq->w0) + 12;\n+ } else {\n+ args[1] = 0;\n+ }\n+\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_SET_QUEUE_CONFIG hcall() is used to set or reset a EQ for\n+ * a given \"target\" and \"priority\". It is also used to set the\n+ * notification config associated with the EQ. An EQ size of 0 is\n+ * used to reset the EQ config for a given target and priority. If\n+ * resetting the EQ config, the END associated with the given \"target\"\n+ * and \"priority\" will be changed to disable queueing.\n+ *\n+ * Upon return from the hcall(), no additional interrupts will be\n+ * directed to the old EQ (if one was set). The old EQ (if one was\n+ * set) should be investigated for interrupts that occurred prior to\n+ * or during the hcall().\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-62: Reserved\n+ * Bit 63: Unconditional Notify (n) per the XIVE spec\n+ * - \"target\" is per \"ibm,ppc-interrupt-server#s\" or\n+ * \"ibm,ppc-interrupt-gserver#s\"\n+ * - \"priority\" is a valid priority not in\n+ * \"ibm,plat-res-int-priorities\"\n+ * - \"eventQueue\": The logical real address of the start of the EQ\n+ * - \"eventQueueSize\": The power of 2 EQ size per \"ibm,xive-eq-sizes\"\n+ *\n+ * Output:\n+ * - None\n+ */\n+\n+#define XIVE_EQ_ALWAYS_NOTIFY (1ull << (63 - 63))\n+\n+static target_ulong h_int_set_queue_config(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ target_ulong flags = args[0];\n+ target_ulong target = args[1];\n+ target_ulong priority = args[2];\n+ target_ulong qpage = args[3];\n+ target_ulong qsize = args[4];\n+ uint32_t eq_idx;\n+ XiveEQ *old_eq;\n+ XiveEQ eq;\n+ uint32_t qdata;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags & ~XIVE_EQ_ALWAYS_NOTIFY) {\n+ return H_PARAMETER;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ if (!priority_is_valid(priority)) {\n+ return H_P3;\n+ }\n+\n+ /* Validate that \"target\" is part of the list of threads allocated\n+ * to the partition. For that, find the EQ corresponding to the\n+ * target.\n+ */\n+ if (!spapr_xive_eq_for_target(spapr->xive, target, priority, &eq_idx)) {\n+ return H_P2;\n+ }\n+\n+ /* TODO: If the partition thread count is greater than the\n+ * hardware thread count, validate the \"target\" has a\n+ * corresponding hardware thread else return H_NOT_AVAILABLE.\n+ */\n+\n+ old_eq = spapr_xive_get_eq(spapr->xive, eq_idx);\n+ if (!old_eq) {\n+ return H_HARDWARE;\n+ }\n+\n+ eq = *old_eq;\n+\n+ switch (qsize) {\n+ case 12:\n+ case 16:\n+ case 21:\n+ case 24:\n+ eq.w3 = ((uint64_t)qpage) & 0xffffffff;\n+ eq.w2 = (((uint64_t)qpage)) >> 32 & 0x0fffffff;\n+ eq.w0 |= EQ_W0_ENQUEUE;\n+ eq.w0 = SETFIELD(EQ_W0_QSIZE, eq.w0, qsize - 12);\n+ break;\n+ case 0:\n+ /* reset queue and disable queueing */\n+ eq.w2 = eq.w3 = 0;\n+ eq.w0 &= ~EQ_W0_ENQUEUE;\n+ break;\n+ default:\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: invalid EQ size %\"PRIx64\"\\n\",\n+ __func__, qsize);\n+ return H_P5;\n+ }\n+\n+ if (qsize) {\n+ /*\n+ * Let's validate the EQ address with a read of the first EQ\n+ * entry. We could also check that the full queue has been\n+ * zeroed by the OS.\n+ */\n+ if (address_space_read(&address_space_memory, qpage,\n+ MEMTXATTRS_UNSPECIFIED,\n+ (uint8_t *) &qdata, sizeof(qdata))) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: failed to read EQ data @0x%\"\n+ HWADDR_PRIx \"\\n\", __func__, qpage);\n+ return H_P4;\n+ }\n+ }\n+\n+ /* Ensure the priority and target are correctly set (they will not\n+ * be right after allocation)\n+ */\n+ eq.w6 = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, 0ul) |\n+ SETFIELD(EQ_W6_NVT_INDEX, 0ul, target);\n+ eq.w7 = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, priority);\n+\n+ /* TODO: depends on notitification page (ESn) from H_INT_GET_QUEUE_INFO */\n+ if (flags & XIVE_EQ_ALWAYS_NOTIFY) {\n+ eq.w0 |= EQ_W0_UCOND_NOTIFY;\n+ }\n+\n+ /* The generation bit for the EQ starts at 1 and The EQ page\n+ * offset counter starts at 0.\n+ */\n+ eq.w1 = EQ_W1_GENERATION | SETFIELD(EQ_W1_PAGE_OFF, 0ul, 0ul);\n+ eq.w0 |= EQ_W0_VALID;\n+\n+ /* TODO: issue syncs required to ensure all in-flight interrupts\n+ * are complete on the old EQ */\n+\n+ /* Update EQ */\n+ *old_eq = eq;\n+\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_GET_QUEUE_CONFIG hcall() is used to get a EQ for a given\n+ * target and priority.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-62: Reserved\n+ * Bit 63: Debug: Return debug data\n+ * - \"target\" is per \"ibm,ppc-interrupt-server#s\" or\n+ * \"ibm,ppc-interrupt-gserver#s\"\n+ * - \"priority\" is a valid priority not in\n+ * \"ibm,plat-res-int-priorities\"\n+ *\n+ * Output:\n+ * - R4: \"flags\":\n+ * Bits 0-62: Reserved\n+ * Bit 63: The value of Unconditional Notify (n) per the XIVE spec\n+ * - R5: The logical real address of the start of the EQ\n+ * - R6: The power of 2 EQ size per \"ibm,xive-eq-sizes\"\n+ * - R7: The value of Event Queue Offset Counter per XIVE spec\n+ * if \"Debug\" = 1, else 0\n+ *\n+ */\n+\n+#define XIVE_EQ_DEBUG (1ull << (63 - 63))\n+\n+static target_ulong h_int_get_queue_config(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ target_ulong flags = args[0];\n+ target_ulong target = args[1];\n+ target_ulong priority = args[2];\n+ uint32_t eq_idx;\n+ XiveEQ *eq;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags & ~XIVE_EQ_DEBUG) {\n+ return H_PARAMETER;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ if (!priority_is_valid(priority)) {\n+ return H_P3;\n+ }\n+\n+ /* Validate that \"target\" is part of the list of threads allocated\n+ * to the partition. For that, find the EQ corresponding to the\n+ * target.\n+ */\n+ if (!spapr_xive_eq_for_target(spapr->xive, target, priority, &eq_idx)) {\n+ return H_P2;\n+ }\n+\n+ /* TODO: If the partition thread count is greater than the\n+ * hardware thread count, validate the \"target\" has a\n+ * corresponding hardware thread else return H_NOT_AVAILABLE.\n+ */\n+\n+ eq = spapr_xive_get_eq(spapr->xive, eq_idx);\n+ if (!eq) {\n+ return H_HARDWARE;\n+ }\n+\n+ args[0] = 0;\n+ if (eq->w0 & EQ_W0_UCOND_NOTIFY) {\n+ args[0] |= XIVE_EQ_ALWAYS_NOTIFY;\n+ }\n+\n+ if (eq->w0 & EQ_W0_ENQUEUE) {\n+ args[1] =\n+ (((uint64_t)(eq->w2 & 0x0fffffff)) << 32) | eq->w3;\n+ args[2] = GETFIELD(EQ_W0_QSIZE, eq->w0) + 12;\n+ } else {\n+ args[1] = 0;\n+ args[2] = 0;\n+ }\n+\n+ /* TODO: do we need any locking on the EQ ? */\n+ if (flags & XIVE_EQ_DEBUG) {\n+ /* Load the event queue generation number into the return flags */\n+ args[0] |= GETFIELD(EQ_W1_GENERATION, eq->w1);\n+\n+ /* Load R7 with the event queue offset counter */\n+ args[3] = GETFIELD(EQ_W1_PAGE_OFF, eq->w1);\n+ }\n+\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_SET_OS_REPORTING_LINE hcall() is used to set the\n+ * reporting cache line pair for the calling thread. The reporting\n+ * cache lines will contain the OS interrupt context when the OS\n+ * issues a CI store byte to @TIMA+0xC10 to acknowledge the OS\n+ * interrupt. The reporting cache lines can be reset by inputting -1\n+ * in \"reportingLine\". Issuing the CI store byte without reporting\n+ * cache lines registered will result in the data not being accessible\n+ * to the OS.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-63: Reserved\n+ * - \"reportingLine\": The logical real address of the reporting cache\n+ * line pair\n+ *\n+ * Output:\n+ * - None\n+ */\n+static target_ulong h_int_set_os_reporting_line(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ /* TODO: H_INT_SET_OS_REPORTING_LINE */\n+ return H_FUNCTION;\n+}\n+\n+/*\n+ * The H_INT_GET_OS_REPORTING_LINE hcall() is used to get the logical\n+ * real address of the reporting cache line pair set for the input\n+ * \"target\". If no reporting cache line pair has been set, -1 is\n+ * returned.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-63: Reserved\n+ * - \"target\" is per \"ibm,ppc-interrupt-server#s\" or\n+ * \"ibm,ppc-interrupt-gserver#s\"\n+ * - \"reportingLine\": The logical real address of the reporting cache\n+ * line pair\n+ *\n+ * Output:\n+ * - R4: The logical real address of the reporting line if set, else -1\n+ */\n+static target_ulong h_int_get_os_reporting_line(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ /* TODO: H_INT_GET_OS_REPORTING_LINE */\n+ return H_FUNCTION;\n+}\n+\n+/*\n+ * The H_INT_ESB hcall() is used to issue a load or store to the ESB\n+ * page for the input \"lisn\". This hcall is only supported for LISNs\n+ * that have the ESB hcall flag set to 1 when returned from hcall()\n+ * H_INT_GET_SOURCE_INFO.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-62: Reserved\n+ * bit 63: Store: Store=1, store operation, else load operation\n+ * - \"lisn\" is per \"interrupts\", \"interrupt-map\", or\n+ * \"ibm,xive-lisn-ranges\" properties, or as returned by the\n+ * ibm,query-interrupt-source-number RTAS call, or as\n+ * returned by the H_ALLOCATE_VAS_WINDOW hcall\n+ * - \"esbOffset\" is the offset into the ESB page for the load or store operation\n+ * - \"storeData\" is the data to write for a store operation\n+ *\n+ * Output:\n+ * - R4: R4: The value of the load if load operation, else -1\n+ */\n+\n+#define XIVE_ESB_STORE (1ull << (63 - 63))\n+\n+static target_ulong h_int_esb(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ sPAPRXive *xive = spapr->xive;\n+ XiveIVE *ive;\n+ target_ulong flags = args[0];\n+ target_ulong lisn = args[1];\n+ target_ulong offset = args[2];\n+ target_ulong data = args[3];\n+ uint64_t esb_base;\n+ uint32_t srcno = lisn - spapr->ics->offset;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags & ~XIVE_ESB_STORE) {\n+ return H_PARAMETER;\n+ }\n+\n+ ive = spapr_xive_get_ive(xive, srcno);\n+ if (!ive || !(ive->w & IVE_VALID)) {\n+ return H_P2;\n+ }\n+\n+ if (offset > (1ull << xive->esb_shift)) {\n+ return H_P3;\n+ }\n+\n+ srcno = lisn - spapr->ics->offset;\n+ esb_base = (uint64_t)xive->esb_base + (1ull << xive->esb_shift) * srcno;\n+ esb_base += offset;\n+\n+ if (dma_memory_rw(&address_space_memory, esb_base, &data, 8,\n+ (flags & XIVE_ESB_STORE))) {\n+ qemu_log_mask(LOG_GUEST_ERROR, \"%s: failed to rw data @0x%\"\n+ HWADDR_PRIx \"\\n\", __func__, esb_base);\n+ return H_HARDWARE;\n+ }\n+ args[0] = (flags & XIVE_ESB_STORE) ? -1 : data;\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_SYNC hcall() is used to issue hardware syncs that will\n+ * ensure any in flight events for the input lisn are in the event\n+ * queue.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-63: Reserved\n+ * - \"lisn\" is per \"interrupts\", \"interrupt-map\", or\n+ * \"ibm,xive-lisn-ranges\" properties, or as returned by the\n+ * ibm,query-interrupt-source-number RTAS call, or as\n+ * returned by the H_ALLOCATE_VAS_WINDOW hcall\n+ *\n+ * Output:\n+ * - None\n+ */\n+static target_ulong h_int_sync(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ XiveIVE *ive;\n+ target_ulong flags = args[0];\n+ target_ulong lisn = args[1];\n+ uint32_t srcno = lisn - spapr->ics->offset;\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags) {\n+ return H_PARAMETER;\n+ }\n+\n+ ive = spapr_xive_get_ive(spapr->xive, srcno);\n+ if (!ive || !(ive->w & IVE_VALID)) {\n+ return H_P2;\n+ }\n+\n+ /*\n+ * H_STATE should be returned if a H_INT_RESET is in progress.\n+ * This is not needed when running the emulation under QEMU\n+ */\n+\n+ /* This is not real hardware. Nothing to be done */\n+ return H_SUCCESS;\n+}\n+\n+/*\n+ * The H_INT_RESET hcall() is used to reset all of the partition's\n+ * interrupt exploitation structures to their initial state. This\n+ * means losing all previously set interrupt state set via\n+ * H_INT_SET_SOURCE_CONFIG and H_INT_SET_QUEUE_CONFIG.\n+ *\n+ * Parameters:\n+ * Input:\n+ * - \"flags\"\n+ * Bits 0-63: Reserved\n+ *\n+ * Output:\n+ * - None\n+ */\n+static target_ulong h_int_reset(PowerPCCPU *cpu,\n+ sPAPRMachineState *spapr,\n+ target_ulong opcode,\n+ target_ulong *args)\n+{\n+ target_ulong flags = args[0];\n+\n+ if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {\n+ return H_FUNCTION;\n+ }\n+\n+ if (flags) {\n+ return H_PARAMETER;\n+ }\n+\n+ spapr_xive_reset(spapr->xive);\n+ return H_SUCCESS;\n+}\n+\n+void spapr_xive_hcall_init(sPAPRMachineState *spapr)\n+{\n+ spapr_register_hypercall(H_INT_GET_SOURCE_INFO, h_int_get_source_info);\n+ spapr_register_hypercall(H_INT_SET_SOURCE_CONFIG, h_int_set_source_config);\n+ spapr_register_hypercall(H_INT_GET_SOURCE_CONFIG, h_int_get_source_config);\n+ spapr_register_hypercall(H_INT_GET_QUEUE_INFO, h_int_get_queue_info);\n+ spapr_register_hypercall(H_INT_SET_QUEUE_CONFIG, h_int_set_queue_config);\n+ spapr_register_hypercall(H_INT_GET_QUEUE_CONFIG, h_int_get_queue_config);\n+ spapr_register_hypercall(H_INT_SET_OS_REPORTING_LINE,\n+ h_int_set_os_reporting_line);\n+ spapr_register_hypercall(H_INT_GET_OS_REPORTING_LINE,\n+ h_int_get_os_reporting_line);\n+ spapr_register_hypercall(H_INT_ESB, h_int_esb);\n+ spapr_register_hypercall(H_INT_SYNC, h_int_sync);\n+ spapr_register_hypercall(H_INT_RESET, h_int_reset);\n+}\ndiff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c\nindex b6577dbecdea..c2011cb2dc72 100644\n--- a/hw/ppc/spapr.c\n+++ b/hw/ppc/spapr.c\n@@ -227,6 +227,8 @@ static sPAPRXive *spapr_spapr_xive_create(sPAPRMachineState *spapr, int nr_irqs,\n goto error;\n }\n \n+ spapr_xive_hcall_init(spapr);\n+\n return SPAPR_XIVE(obj);\n error:\n error_propagate(errp, local_err);\ndiff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h\nindex 6cd5ab73c5dc..b7683fae6415 100644\n--- a/include/hw/ppc/spapr.h\n+++ b/include/hw/ppc/spapr.h\n@@ -387,7 +387,20 @@ struct sPAPRMachineState {\n #define H_INVALIDATE_PID 0x378\n #define H_REGISTER_PROC_TBL 0x37C\n #define H_SIGNAL_SYS_RESET 0x380\n-#define MAX_HCALL_OPCODE H_SIGNAL_SYS_RESET\n+\n+#define H_INT_GET_SOURCE_INFO 0x3A8\n+#define H_INT_SET_SOURCE_CONFIG 0x3AC\n+#define H_INT_GET_SOURCE_CONFIG 0x3B0\n+#define H_INT_GET_QUEUE_INFO 0x3B4\n+#define H_INT_SET_QUEUE_CONFIG 0x3B8\n+#define H_INT_GET_QUEUE_CONFIG 0x3BC\n+#define H_INT_SET_OS_REPORTING_LINE 0x3C0\n+#define H_INT_GET_OS_REPORTING_LINE 0x3C4\n+#define H_INT_ESB 0x3C8\n+#define H_INT_SYNC 0x3CC\n+#define H_INT_RESET 0x3D0\n+\n+#define MAX_HCALL_OPCODE H_INT_RESET\n \n /* The hcalls above are standardized in PAPR and implemented by pHyp\n * as well.\ndiff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h\nindex 3af01a0a4b22..ae5ff89533c0 100644\n--- a/include/hw/ppc/spapr_xive.h\n+++ b/include/hw/ppc/spapr_xive.h\n@@ -66,4 +66,8 @@ struct sPAPRXive {\n MemoryRegion tm_iomem;\n };\n \n+typedef struct sPAPRMachineState sPAPRMachineState;\n+\n+void spapr_xive_hcall_init(sPAPRMachineState *spapr);\n+\n #endif /* PPC_SPAPR_XIVE_H */\n", "prefixes": [ "RFC", "v2", "17/21" ] }