get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/812474/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "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"
    ]
}