get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2234273,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2234273/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260507040153.14565-2-matthew@pq.io/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.2/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": "<20260507040153.14565-2-matthew@pq.io>",
    "list_archive_url": null,
    "date": "2026-05-07T04:01:52",
    "name": "[1/2] hw/misc/applesmc: fix GET_KEY_BY_INDEX to return real keys, accept WRITE/TYPE commands",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "d6e0d6367d01b8342fccb7349f85a80bada505c0",
    "submitter": {
        "id": 93356,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/93356/?format=api",
        "name": "Matthew Jackson",
        "email": "matthew@pq.io"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260507040153.14565-2-matthew@pq.io/mbox/",
    "series": [
        {
            "id": 503191,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/503191/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=503191",
            "date": "2026-05-07T04:01:53",
            "name": "hw/misc/applesmc: fix GET_KEY_BY_INDEX iteration and populate Apple SMC key set",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/503191/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2234273/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2234273/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@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=pq.io header.i=@pq.io header.a=rsa-sha256\n header.s=protonmail3 header.b=EmYhYA//;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4gBDll0W3dz1y04\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 08 May 2026 00:14:43 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wKzUD-0007Ak-CB; Thu, 07 May 2026 10:13:57 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <matthew@pq.io>) id 1wKpwH-0005nn-9M\n for qemu-devel@nongnu.org; Thu, 07 May 2026 00:02:17 -0400",
            "from mail-07.mail-europe.com ([188.165.51.139])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <matthew@pq.io>) id 1wKpwE-0004lR-SL\n for qemu-devel@nongnu.org; Thu, 07 May 2026 00:02:16 -0400"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=pq.io;\n s=protonmail3; t=1778126519; x=1778385719;\n bh=QoT6ZV0zp2yCk/oaO3p5EzNmYDCXteG6Q8NREGInOLI=;\n h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To:\n Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector;\n b=EmYhYA//9Wh0jPzyeEjb4d7pK60XHxV8YTSidMF32B/un6iFBhdLUbXXoMruKy/5W\n RTZ2Xk2BCdQrWWJPNFjAJGtY3c8lY7NbqONUUJ8d6y2F0Jskd+MAxv0XNjM0k8zxHG\n Q3ShnERv9+ik6W00yBIyVFW5Xb5RWVfVFmy0cKyScYIXAZpZIfxwvFke3tS/maRfUf\n xex3Kbe2CNwTJjRoy1S8zgLUOyTbKkM6xzeGLiH2t3YIVXLquwuxnbuPLsT7a0YGEo\n Ca8jX7QyveT/zNwYx6EewU+U/lyClH8NOJCduVf3XCZFs3l3T4GV1DIH/uUHnIAwor\n OfA7qCKM1lWew==",
        "X-Pm-Submission-Id": "4g9z8j2VCjz1DFFg",
        "From": "Matthew Jackson <matthew@pq.io>",
        "To": "qemu-devel@nongnu.org",
        "Cc": "stefanha@redhat.com",
        "Subject": "[PATCH 1/2] hw/misc/applesmc: fix GET_KEY_BY_INDEX to return real\n keys, accept WRITE/TYPE commands",
        "Date": "Wed,  6 May 2026 21:01:52 -0700",
        "Message-ID": "<20260507040153.14565-2-matthew@pq.io>",
        "X-Mailer": "git-send-email 2.50.1",
        "In-Reply-To": "<20260507040153.14565-1-matthew@pq.io>",
        "References": "<20260507040153.14565-1-matthew@pq.io>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=188.165.51.139; envelope-from=matthew@pq.io;\n helo=mail-07.mail-europe.com",
        "X-Spam_score_int": "-27",
        "X-Spam_score": "-2.8",
        "X-Spam_bar": "--",
        "X-Spam_report": "(-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=0.001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no",
        "X-Spam_action": "no action",
        "X-Mailman-Approved-At": "Thu, 07 May 2026 10:13:41 -0400",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "qemu development <qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://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 <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "The applesmc device implements just enough of the Apple SMC PMIO\nprotocol to satisfy the OSK boot check on older macOS versions.\nOn modern macOS guests (x86 10.14+, all 15.x), the AppleSMC kext\nenumerates the SMC key space at boot via APPLESMC_GET_KEY_BY_INDEX_CMD\n(0x12). The current device only acknowledges APPLESMC_READ_CMD\n(0x10) at the command port; every other command falls through to\nthe default arm of the switch and sets ST_1E_BAD_CMD.\n\nThe macOS driver interprets the resulting 0x82 reply as\n\"spurious data\" and enters a retry loop that floods the kernel\nlog with kSMCSpuriousData (0x81) / kSMCKeyNotFound errors at\nroughly 1800 events per second, pegging kernel_task at ~70%\nCPU and WindowServer at ~509% CPU. This reproduces reliably\non any recent macOS 15 guest booted with -device\nisa-applesmc,osk=<valid-OSK>.\n\nThis patch:\n\n  * Accepts APPLESMC_WRITE_CMD, APPLESMC_GET_KEY_BY_INDEX_CMD,\n    and APPLESMC_GET_KEY_TYPE_CMD at the command port (in\n    addition to the existing READ_CMD path).\n\n  * Implements GET_KEY_BY_INDEX by walking s->data_def and\n    returning the 4-byte ASCII key name at the requested index;\n    returns APPLESMC_ST_1E_BAD_INDEX (0xb8) once the index is\n    past the end of the list so the guest stops iterating.\n\n  * Implements GET_KEY_TYPE by looking up the key in s->data_def\n    and returning a 6-byte response (type[4] + size[1] + attr[1])\n    matching VirtualSMC's kern_pmio.cpp behaviour.\n\n  * Implements WRITE by accepting the key name, length, and\n    payload and logging at LOG_UNIMP. macOS writes SMC keys\n    during normal power management; silent acceptance avoids\n    BAD_CMD on every write.\n\n  * Replaces the unknown-key NOEXIST (0x84) reply on READ with\n    a zeroed payload of the requested length, logged at\n    LOG_UNIMP. Early-boot probes hit hundreds of undocumented\n    keys per second; NOEXIST triggers retry storms while a\n    zeroed payload satisfies the probe semantics without\n    asserting a particular value.\n\n  * Routes the BAD_CMD path through qemu_log_mask\n    (LOG_GUEST_ERROR) instead of the smc_debug printf.\n\n  * Fixes a typo in the MSSD key initialiser (\"\\0x3\" -> \"\\x03\").\n    The original literal was three bytes ('\\\\0', 'x', '3')\n    truncated to one ('\\\\0') by the size argument, so MSSD has\n    been silently returning 0 since introduction; the corrected\n    value matches what a real iMac20,1 SMC reports.\n\nReported-by: macOS guests booted with -device isa-applesmc since 10.14.\nSigned-off-by: Matthew Jackson <matthew@pq.io>\n---\n hw/misc/applesmc.c | 177 +++++++++++++++++++++++++++++++++++++++++++--\n 1 file changed, 170 insertions(+), 7 deletions(-)",
    "diff": "diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c\nindex fd96f5f..2b5ef3c 100644\n--- a/hw/misc/applesmc.c\n+++ b/hw/misc/applesmc.c\n@@ -35,6 +35,7 @@\n #include \"hw/core/qdev-properties.h\"\n #include \"ui/console.h\"\n #include \"qemu/error-report.h\"\n+#include \"qemu/log.h\"\n #include \"qemu/module.h\"\n #include \"qemu/timer.h\"\n #include \"qom/object.h\"\n@@ -126,7 +127,14 @@ static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val,\n     smc_debug(\"CMD received: 0x%02x\\n\", (uint8_t)val);\n     switch (val) {\n     case APPLESMC_READ_CMD:\n-        /* did last command run through OK? */\n+    case APPLESMC_WRITE_CMD:\n+    case APPLESMC_GET_KEY_BY_INDEX_CMD:\n+    case APPLESMC_GET_KEY_TYPE_CMD:\n+        /*\n+         * Accept all standard SMC commands. Pre-existing code only handled\n+         * READ_CMD; macOS boots hang if WRITE/TYPE/GET_KEY_BY_INDEX commands\n+         * return BAD_CMD during early AppleSMC driver init.\n+         */\n         if (status == APPLESMC_ST_CMD_DONE || status == APPLESMC_ST_NEW_CMD) {\n             s->cmd = val;\n             s->status = APPLESMC_ST_NEW_CMD | APPLESMC_ST_ACK;\n@@ -137,7 +145,8 @@ static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val,\n         }\n         break;\n     default:\n-        smc_debug(\"UNEXPECTED CMD 0x%02x\\n\", (uint8_t)val);\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"applesmc: unexpected CMD 0x%02x\\n\", (uint8_t)val);\n         s->status = APPLESMC_ST_NEW_CMD;\n         s->status_1e = APPLESMC_ST_1E_BAD_CMD;\n     }\n@@ -179,17 +188,170 @@ static void applesmc_io_data_write(void *opaque, hwaddr addr, uint64_t val,\n                 s->data_len = d->len;\n                 s->data_pos = 0;\n                 s->status = APPLESMC_ST_ACK | APPLESMC_ST_DATA_READY;\n-                s->status_1e = APPLESMC_ST_CMD_DONE;  /* clear on valid key */\n+                s->status_1e = APPLESMC_ST_CMD_DONE;\n             } else {\n-                smc_debug(\"READ_CMD: key '%c%c%c%c' not found!\\n\",\n-                          s->key[0], s->key[1], s->key[2], s->key[3]);\n+                /*\n+                 * Return zeros for unknown keys instead of NOEXIST. Early\n+                 * macOS boot probes many undocumented keys; responding\n+                 * NOEXIST triggers retry storms. A zeroed payload satisfies\n+                 * the probe without asserting a particular value.\n+                 */\n+                qemu_log_mask(LOG_UNIMP,\n+                              \"applesmc: READ unknown key '%c%c%c%c' len=%d\\n\",\n+                              s->key[0], s->key[1], s->key[2], s->key[3],\n+                              (uint8_t)val);\n+                memset(s->data, 0, APPLESMC_MAX_DATA_LENGTH);\n+                s->data_len = (uint8_t)val;\n+                s->data_pos = 0;\n+                s->status = APPLESMC_ST_ACK | APPLESMC_ST_DATA_READY;\n+                s->status_1e = APPLESMC_ST_CMD_DONE;\n+            }\n+        }\n+        s->read_pos++;\n+        break;\n+    case APPLESMC_WRITE_CMD:\n+        /*\n+         * Accept writes silently. macOS writes SMC keys during power\n+         * management, fan control, etc. Log at LOG_UNIMP for visibility\n+         * without treating the write as an error.\n+         */\n+        if ((s->status & 0x0f) == APPLESMC_ST_CMD_DONE) {\n+            break;\n+        }\n+        if (s->read_pos < 4) {\n+            s->key[s->read_pos] = val;\n+            s->status = APPLESMC_ST_ACK;\n+        } else if (s->read_pos == 4) {\n+            s->data_len = (uint8_t)val;\n+            s->data_pos = 0;\n+            s->status = APPLESMC_ST_ACK;\n+        } else {\n+            if (s->data_pos < s->data_len) {\n+                s->data[s->data_pos] = (uint8_t)val;\n+                s->data_pos++;\n+                if (s->data_pos == s->data_len) {\n+                    qemu_log_mask(LOG_UNIMP,\n+                                  \"applesmc: WRITE key '%c%c%c%c' len=%d\\n\",\n+                                  s->key[0], s->key[1], s->key[2], s->key[3],\n+                                  s->data_len);\n+                    s->status = APPLESMC_ST_CMD_DONE;\n+                    s->status_1e = APPLESMC_ST_CMD_DONE;\n+                } else {\n+                    s->status = APPLESMC_ST_ACK;\n+                }\n+            }\n+        }\n+        s->read_pos++;\n+        break;\n+    case APPLESMC_GET_KEY_TYPE_CMD:\n+        /*\n+         * Return key type info. Protocol (matches VirtualSMC):\n+         * - Receive 4 bytes of key name.\n+         * - After the 4th byte, immediately set DATA_READY with response.\n+         * - Response is 6 bytes: type[4] + size[1] + attr[1].\n+         * Unlike READ_CMD there is no length byte between key name and\n+         * response.\n+         */\n+        if ((s->status & 0x0f) == APPLESMC_ST_CMD_DONE) {\n+            break;\n+        }\n+        if (s->read_pos < 3) {\n+            s->key[s->read_pos] = val;\n+            s->status = APPLESMC_ST_ACK;\n+        } else if (s->read_pos == 3) {\n+            /* 4th and final key byte. Unlike READ_CMD which has a 5th byte\n+             * for data length, GET_KEY_TYPE responds immediately after the\n+             * 4-byte key name (matching VirtualSMC kern_pmio.cpp behavior). */\n+            s->key[3] = val;\n+            d = applesmc_find_key(s);\n+            if (d != NULL) {\n+                switch (d->len) {\n+                case 1:\n+                    s->data[0] = 'u'; s->data[1] = 'i';\n+                    s->data[2] = '8'; s->data[3] = ' ';\n+                    break;\n+                case 2:\n+                    s->data[0] = 'u'; s->data[1] = 'i';\n+                    s->data[2] = '1'; s->data[3] = '6';\n+                    break;\n+                case 4:\n+                    s->data[0] = 'u'; s->data[1] = 'i';\n+                    s->data[2] = '3'; s->data[3] = '2';\n+                    break;\n+                default:\n+                    s->data[0] = 'c'; s->data[1] = 'h';\n+                    s->data[2] = '8'; s->data[3] = '*';\n+                    break;\n+                }\n+                s->data[4] = d->len;\n+                s->data[5] = 0xD0;\n+            } else {\n+                qemu_log_mask(LOG_UNIMP,\n+                              \"applesmc: GET_KEY_TYPE unknown '%c%c%c%c'\\n\",\n+                              s->key[0], s->key[1], s->key[2], s->key[3]);\n+                s->data[0] = 'u'; s->data[1] = 'i';\n+                s->data[2] = '8'; s->data[3] = ' ';\n+                s->data[4] = 1;\n+                s->data[5] = 0xD0;\n+            }\n+            s->data_len = 6;\n+            s->data_pos = 0;\n+            s->status = APPLESMC_ST_ACK | APPLESMC_ST_DATA_READY;\n+            s->status_1e = APPLESMC_ST_CMD_DONE;\n+        }\n+        s->read_pos++;\n+        break;\n+    case APPLESMC_GET_KEY_BY_INDEX_CMD:\n+        /*\n+         * Return key name by index. macOS sends a 4-byte big-endian index\n+         * and expects the 4-byte ASCII key name at that position. The\n+         * previous implementation returned 4 zero bytes, which macOS\n+         * treated as kSMCSpuriousData (0x81) and retried indefinitely,\n+         * flooding the kernel log at ~1800 errors/sec. Walk the keys list\n+         * to return the actual key name, or APPLESMC_ST_1E_BAD_INDEX\n+         * (0xb8) once the index is past the end of the list so the guest\n+         * stops iterating.\n+         */\n+        if ((s->status & 0x0f) == APPLESMC_ST_CMD_DONE) {\n+            break;\n+        }\n+        if (s->read_pos < 3) {\n+            s->key[s->read_pos] = val;\n+            s->status = APPLESMC_ST_ACK;\n+        } else if (s->read_pos == 3) {\n+            s->key[3] = val;\n+            uint32_t idx = ((uint8_t)s->key[0] << 24)\n+                         | ((uint8_t)s->key[1] << 16)\n+                         | ((uint8_t)s->key[2] << 8)\n+                         |  (uint8_t)s->key[3];\n+            struct AppleSMCData *def;\n+            uint32_t i = 0;\n+            bool found = false;\n+            QLIST_FOREACH(def, &s->data_def, node) {\n+                if (i == idx) {\n+                    memcpy(s->data, def->key, 4);\n+                    s->data_len = 4;\n+                    s->data_pos = 0;\n+                    found = true;\n+                    break;\n+                }\n+                i++;\n+            }\n+            if (!found) {\n+                s->data_len = 0;\n+                s->status_1e = APPLESMC_ST_1E_BAD_INDEX;\n                 s->status = APPLESMC_ST_CMD_DONE;\n-                s->status_1e = APPLESMC_ST_1E_NOEXIST;\n+                s->read_pos++;\n+                break;\n             }\n+            s->status = APPLESMC_ST_ACK | APPLESMC_ST_DATA_READY;\n+            s->status_1e = APPLESMC_ST_CMD_DONE;\n         }\n         s->read_pos++;\n         break;\n     default:\n+        qemu_log_mask(LOG_GUEST_ERROR,\n+                      \"applesmc: unhandled data for cmd 0x%02x\\n\", s->cmd);\n         s->status = APPLESMC_ST_CMD_DONE;\n         s->status_1e = APPLESMC_ST_1E_STILL_BAD_CMD;\n     }\n@@ -330,12 +492,13 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)\n     }\n \n     QLIST_INIT(&s->data_def);\n+\n     applesmc_add_key(s, \"REV \", 6, \"\\x01\\x13\\x0f\\x00\\x00\\x03\");\n     applesmc_add_key(s, \"OSK0\", 32, s->osk);\n     applesmc_add_key(s, \"OSK1\", 32, s->osk + 32);\n     applesmc_add_key(s, \"NATJ\", 1, \"\\0\");\n     applesmc_add_key(s, \"MSSP\", 1, \"\\0\");\n-    applesmc_add_key(s, \"MSSD\", 1, \"\\0x3\");\n+    applesmc_add_key(s, \"MSSD\", 1, \"\\x03\");\n }\n \n static void applesmc_unrealize(DeviceState *dev)\n",
    "prefixes": [
        "1/2"
    ]
}