Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2196934/?format=api
{ "id": 2196934, "url": "http://patchwork.ozlabs.org/api/patches/2196934/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260216160349.3079657-2-peter.maydell@linaro.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": "<20260216160349.3079657-2-peter.maydell@linaro.org>", "list_archive_url": null, "date": "2026-02-16T16:03:48", "name": "[1/2] target/arm: Move TCG-specific code out of debug_helper.c", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "3b2eb3472e24dc4e6770030d314d7b96eb7e75b5", "submitter": { "id": 5111, "url": "http://patchwork.ozlabs.org/api/people/5111/?format=api", "name": "Peter Maydell", "email": "peter.maydell@linaro.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260216160349.3079657-2-peter.maydell@linaro.org/mbox/", "series": [ { "id": 492324, "url": "http://patchwork.ozlabs.org/api/series/492324/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=492324", "date": "2026-02-16T16:03:48", "name": "target/arm: Don't use HELPER_H in non-tcg files", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/492324/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2196934/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2196934/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=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=CaQB0WN0;\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=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists.gnu.org (lists.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 4fF6z55TR9z1xtN\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 17 Feb 2026 03:04:17 +1100 (AEDT)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1vs150-00029e-6A; Mon, 16 Feb 2026 11:04:10 -0500", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <peter.maydell@linaro.org>)\n id 1vs14p-000287-GM\n for qemu-devel@nongnu.org; Mon, 16 Feb 2026 11:04:00 -0500", "from mail-wm1-x32c.google.com ([2a00:1450:4864:20::32c])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <peter.maydell@linaro.org>)\n id 1vs14k-0005nE-JY\n for qemu-devel@nongnu.org; Mon, 16 Feb 2026 11:03:59 -0500", "by mail-wm1-x32c.google.com with SMTP id\n 5b1f17b1804b1-483487335c2so31597945e9.2\n for <qemu-devel@nongnu.org>; Mon, 16 Feb 2026 08:03:54 -0800 (PST)", "from lanath.. (wildly.archaic.org.uk. [81.2.115.145])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-4835d92267bsm661713185e9.0.2026.02.16.08.03.51\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 16 Feb 2026 08:03:51 -0800 (PST)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1771257833; x=1771862633; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=9hAfYiBKs2xPmH/RRmNpRM+W3+7eJf2RUtEtIWW8ULA=;\n b=CaQB0WN0bExZICoaoXyUaGWkqZlV/8iFB2+ikfsQsHDOUgFou+aoHKZmmkFAfAUY2Y\n xEWvAANQ1nD4TOp8cCGEil/6dOVNfFWjKev8FzdJAkT4rugfjL+IRU9ZfeGwCqY5UEpI\n UffCZO8LL+Kptn0LD+oJKMUI8pxPzFQoXkn+Z/UM95LufkFshgajy6ONDQoKE/LIgPqp\n FzV5ALYSc5QEhaEiKpdh1rjuoSRmq57afOs7NTZHKT/O2mZPTUOL1ojQAsktVHlbmycA\n qQQkPh5Jlqnq/BXWUT7RRD2NVgrbo7aiuILZbFX9lP4GJJdJmxSfhGfPbdj5i88C4B+j\n kY/g==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771257833; x=1771862633;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=9hAfYiBKs2xPmH/RRmNpRM+W3+7eJf2RUtEtIWW8ULA=;\n b=saTjBWPG1zqx8HFD2+wGF7s+B3qk6CA5UyeJjpQpT4Zd6cC1L4zN+ChG8ZGn+nPhIV\n 4B8cG3a/EdzwQluPD0K1V/AKDcP4KZZEfPK/f/KdGQd1LWwjcomm7o3jtj9QV29vcdT6\n OCjIS/YLXOnuSx+Dq3Ga/2pPv/qCrLfAzgo59VqfVFkUJhomH6qKLYyi1SMh1bzxl28d\n IEI7bTFxAfHBBkeWngklroRf2Rb4o85KPd77a0UfBwVaW+QndtpPhhuE8axD8Pc/nQCV\n /0EuTK94iR6u3oqyJ/Spon8mgoOQlWZESS3YIO+WV0Kqwu/U9IXssnSMLN29hQ2PyKnp\n PjkQ==", "X-Forwarded-Encrypted": "i=1;\n AJvYcCUyWlDiDqkpVdfvW/IzljzOtFichvVK+RClDu1Z7+FgkC0PI77fdhBz1xXu3hWLbtARDOqWhxFRwUY/@nongnu.org", "X-Gm-Message-State": "AOJu0YxPfMlocWt8MY0agnJwWym7hJa6DZfvuKMeAF81QFl2iZxQGfnK\n yRr4bpJ6BBZ4zERwx32j1B39K6anI+13mKXBdvodW7ZWJknMLDTFxlR8PxZxuZBvIPYNWvm3P+p\n 4uSBL", "X-Gm-Gg": "AZuq6aKh9gT86VDxChjJqzfqw0QeP248158DewTfubKs+PCG1/GgpIBrVJkI751nzvw\n 530yHrBdyokQEu99uC/V+nmKEQThV+dnbn6AfO1v9VJKsEUeHp7lTIMO4i45DcW1X3SsFjBDy9i\n B820kkHZ5yoasb9kzh4Vy2GQU087kSZkiph2OtYu9vZhCp4uIv6xyGq5FRcmTYFMysN6VJFqLuD\n 1fuIDUxAxHbmtkPSl2y1J0V2oB++fwx5iM87K8YrKlJEykwB2bscqSpMWAeyEa2SUo6RJqPoB86\n icWNKpeTm1hZIfYtfyNLvnlNk8yC7w4KJwHmVJM/HrTHfHE5Z0G9tHstmvmqpH6tPDDgyNKNeBX\n dNb+V6NLTt6kvwL9WJNirQzFbJn6Hr/2sKtv8oR+49SQF5z6Sl7fYlfgiUdaU7rZG+ScIcn3ZmI\n om71+YA0yC2B5BVFxR+rdMxqUKQQhb6M601i/1SpS1KrHTHRPC4XiG5jLhZrfgXV4XnmEMIv7kN\n GVZwIQXB532UfDwmAP6D7Jb3qIncJ4=", "X-Received": "by 2002:a05:600c:6096:b0:483:612d:7a9a with SMTP id\n 5b1f17b1804b1-483737b89a4mr155698545e9.0.1771257832437;\n Mon, 16 Feb 2026 08:03:52 -0800 (PST)", "From": "Peter Maydell <peter.maydell@linaro.org>", "To": "qemu-arm@nongnu.org,\n\tqemu-devel@nongnu.org", "Cc": "Pierrick Bouvier <pierrick.bouvier@linaro.org>", "Subject": "[PATCH 1/2] target/arm: Move TCG-specific code out of debug_helper.c", "Date": "Mon, 16 Feb 2026 16:03:48 +0000", "Message-ID": "<20260216160349.3079657-2-peter.maydell@linaro.org>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20260216160349.3079657-1-peter.maydell@linaro.org>", "References": "<20260216160349.3079657-1-peter.maydell@linaro.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2a00:1450:4864:20::32c;\n envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32c.google.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 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_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no", "X-Spam_action": "no action", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "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 target/arm/debug_helper.c file has some code which we need\nfor non-TCG accelerators, but quite a lot which is guarded by\na CONFIG_TCG ifdef. Move all this TCG-only code out to a\nnew file target/arm/tcg/debug.c.\n\nIn particular all the code requiring access to the TCG\nhelper function prototypes is in the moved code, so we can\ndrop the use of tcg/helper.h from debug_helper.c.\n\nSigned-off-by: Peter Maydell <peter.maydell@linaro.org>\n---\n target/arm/debug_helper.c | 769 ---------------------\n target/arm/{debug_helper.c => tcg/debug.c} | 542 +--------------\n target/arm/tcg/meson.build | 2 +\n 3 files changed, 3 insertions(+), 1310 deletions(-)\n copy target/arm/{debug_helper.c => tcg/debug.c} (53%)", "diff": "diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c\nindex 579516e154..352c8e5c8e 100644\n--- a/target/arm/debug_helper.c\n+++ b/target/arm/debug_helper.c\n@@ -14,775 +14,6 @@\n #include \"exec/watchpoint.h\"\n #include \"system/tcg.h\"\n \n-#define HELPER_H \"tcg/helper.h\"\n-#include \"exec/helper-proto.h.inc\"\n-\n-#ifdef CONFIG_TCG\n-/* Return the Exception Level targeted by debug exceptions. */\n-static int arm_debug_target_el(CPUARMState *env)\n-{\n- bool secure = arm_is_secure(env);\n- bool route_to_el2 = false;\n-\n- if (arm_feature(env, ARM_FEATURE_M)) {\n- return 1;\n- }\n-\n- if (arm_is_el2_enabled(env)) {\n- route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||\n- env->cp15.mdcr_el2 & MDCR_TDE;\n- }\n-\n- if (route_to_el2) {\n- return 2;\n- } else if (arm_feature(env, ARM_FEATURE_EL3) &&\n- !arm_el_is_aa64(env, 3) && secure) {\n- return 3;\n- } else {\n- return 1;\n- }\n-}\n-\n-/*\n- * Raise an exception to the debug target el.\n- * Modify syndrome to indicate when origin and target EL are the same.\n- */\n-G_NORETURN static void\n-raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome)\n-{\n- int debug_el = arm_debug_target_el(env);\n- int cur_el = arm_current_el(env);\n-\n- /*\n- * If singlestep is targeting a lower EL than the current one, then\n- * DisasContext.ss_active must be false and we can never get here.\n- * Similarly for watchpoint and breakpoint matches.\n- */\n- assert(debug_el >= cur_el);\n- syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;\n- raise_exception(env, excp, syndrome, debug_el);\n-}\n-\n-/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */\n-static bool aa64_generate_debug_exceptions(CPUARMState *env)\n-{\n- int cur_el = arm_current_el(env);\n- int debug_el;\n-\n- if (cur_el == 3) {\n- return false;\n- }\n-\n- /* MDCR_EL3.SDD disables debug events from Secure state */\n- if (arm_is_secure_below_el3(env)\n- && extract32(env->cp15.mdcr_el3, 16, 1)) {\n- return false;\n- }\n-\n- /*\n- * Same EL to same EL debug exceptions need MDSCR_KDE enabled\n- * while not masking the (D)ebug bit in DAIF.\n- */\n- debug_el = arm_debug_target_el(env);\n-\n- if (cur_el == debug_el) {\n- return extract32(env->cp15.mdscr_el1, 13, 1)\n- && !(env->daif & PSTATE_D);\n- }\n-\n- /* Otherwise the debug target needs to be a higher EL */\n- return debug_el > cur_el;\n-}\n-\n-static bool aa32_generate_debug_exceptions(CPUARMState *env)\n-{\n- int el = arm_current_el(env);\n-\n- if (el == 0 && arm_el_is_aa64(env, 1)) {\n- return aa64_generate_debug_exceptions(env);\n- }\n-\n- if (arm_is_secure(env)) {\n- int spd;\n-\n- if (el == 0 && (env->cp15.sder & 1)) {\n- /*\n- * SDER.SUIDEN means debug exceptions from Secure EL0\n- * are always enabled. Otherwise they are controlled by\n- * SDCR.SPD like those from other Secure ELs.\n- */\n- return true;\n- }\n-\n- spd = extract32(env->cp15.mdcr_el3, 14, 2);\n- switch (spd) {\n- case 1:\n- /* SPD == 0b01 is reserved, but behaves as 0b00. */\n- case 0:\n- /*\n- * For 0b00 we return true if external secure invasive debug\n- * is enabled. On real hardware this is controlled by external\n- * signals to the core. QEMU always permits debug, and behaves\n- * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.\n- */\n- return true;\n- case 2:\n- return false;\n- case 3:\n- return true;\n- }\n- }\n-\n- return el != 2;\n-}\n-\n-/*\n- * Return true if debugging exceptions are currently enabled.\n- * This corresponds to what in ARM ARM pseudocode would be\n- * if UsingAArch32() then\n- * return AArch32.GenerateDebugExceptions()\n- * else\n- * return AArch64.GenerateDebugExceptions()\n- * We choose to push the if() down into this function for clarity,\n- * since the pseudocode has it at all callsites except for the one in\n- * CheckSoftwareStep(), where it is elided because both branches would\n- * always return the same value.\n- */\n-bool arm_generate_debug_exceptions(CPUARMState *env)\n-{\n- if ((env->cp15.oslsr_el1 & 1) || (env->cp15.osdlr_el1 & 1)) {\n- return false;\n- }\n- if (is_a64(env)) {\n- return aa64_generate_debug_exceptions(env);\n- } else {\n- return aa32_generate_debug_exceptions(env);\n- }\n-}\n-\n-/*\n- * Is single-stepping active? (Note that the \"is EL_D AArch64?\" check\n- * implicitly means this always returns false in pre-v8 CPUs.)\n- */\n-bool arm_singlestep_active(CPUARMState *env)\n-{\n- return extract32(env->cp15.mdscr_el1, 0, 1)\n- && arm_el_is_aa64(env, arm_debug_target_el(env))\n- && arm_generate_debug_exceptions(env);\n-}\n-\n-/* Return true if the linked breakpoint entry lbn passes its checks */\n-static bool linked_bp_matches(ARMCPU *cpu, int lbn)\n-{\n- CPUARMState *env = &cpu->env;\n- uint64_t bcr = env->cp15.dbgbcr[lbn];\n- int brps = arm_num_brps(cpu);\n- int ctx_cmps = arm_num_ctx_cmps(cpu);\n- int bt;\n- uint32_t contextidr;\n- uint64_t hcr_el2;\n-\n- /*\n- * Links to unimplemented or non-context aware breakpoints are\n- * CONSTRAINED UNPREDICTABLE: either behave as if disabled, or\n- * as if linked to an UNKNOWN context-aware breakpoint (in which\n- * case DBGWCR<n>_EL1.LBN must indicate that breakpoint).\n- * We choose the former.\n- */\n- if (lbn >= brps || lbn < (brps - ctx_cmps)) {\n- return false;\n- }\n-\n- bcr = env->cp15.dbgbcr[lbn];\n-\n- if (extract64(bcr, 0, 1) == 0) {\n- /* Linked breakpoint disabled : generate no events */\n- return false;\n- }\n-\n- bt = extract64(bcr, 20, 4);\n- hcr_el2 = arm_hcr_el2_eff(env);\n-\n- switch (bt) {\n- case 3: /* linked context ID match */\n- switch (arm_current_el(env)) {\n- default:\n- /* Context matches never fire in AArch64 EL3 */\n- return false;\n- case 2:\n- if (!(hcr_el2 & HCR_E2H)) {\n- /* Context matches never fire in EL2 without E2H enabled. */\n- return false;\n- }\n- contextidr = env->cp15.contextidr_el[2];\n- break;\n- case 1:\n- contextidr = env->cp15.contextidr_el[1];\n- break;\n- case 0:\n- if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {\n- contextidr = env->cp15.contextidr_el[2];\n- } else {\n- contextidr = env->cp15.contextidr_el[1];\n- }\n- break;\n- }\n- break;\n-\n- case 7: /* linked contextidr_el1 match */\n- contextidr = env->cp15.contextidr_el[1];\n- break;\n- case 13: /* linked contextidr_el2 match */\n- contextidr = env->cp15.contextidr_el[2];\n- break;\n-\n- case 9: /* linked VMID match (reserved if no EL2) */\n- case 11: /* linked context ID and VMID match (reserved if no EL2) */\n- case 15: /* linked full context ID match */\n- default:\n- /*\n- * Links to Unlinked context breakpoints must generate no\n- * events; we choose to do the same for reserved values too.\n- */\n- return false;\n- }\n-\n- /*\n- * We match the whole register even if this is AArch32 using the\n- * short descriptor format (in which case it holds both PROCID and ASID),\n- * since we don't implement the optional v7 context ID masking.\n- */\n- return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];\n-}\n-\n-static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)\n-{\n- CPUARMState *env = &cpu->env;\n- uint64_t cr;\n- int pac, hmc, ssc, wt, lbn;\n- /*\n- * Note that for watchpoints the check is against the CPU security\n- * state, not the S/NS attribute on the offending data access.\n- */\n- bool is_secure = arm_is_secure(env);\n- int access_el = arm_current_el(env);\n-\n- if (is_wp) {\n- CPUWatchpoint *wp = env->cpu_watchpoint[n];\n-\n- if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {\n- return false;\n- }\n- cr = env->cp15.dbgwcr[n];\n- if (wp->hitattrs.user) {\n- /*\n- * The LDRT/STRT/LDT/STT \"unprivileged access\" instructions should\n- * match watchpoints as if they were accesses done at EL0, even if\n- * the CPU is at EL1 or higher.\n- */\n- access_el = 0;\n- }\n- } else {\n- uint64_t pc = is_a64(env) ? env->pc : env->regs[15];\n-\n- if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) {\n- return false;\n- }\n- cr = env->cp15.dbgbcr[n];\n- }\n- /*\n- * The WATCHPOINT_HIT flag guarantees us that the watchpoint is\n- * enabled and that the address and access type match; for breakpoints\n- * we know the address matched; check the remaining fields, including\n- * linked breakpoints. We rely on WCR and BCR having the same layout\n- * for the LBN, SSC, HMC, PAC/PMC and is-linked fields.\n- * Note that some combinations of {PAC, HMC, SSC} are reserved and\n- * must act either like some valid combination or as if the watchpoint\n- * were disabled. We choose the former, and use this together with\n- * the fact that EL3 must always be Secure and EL2 must always be\n- * Non-Secure to simplify the code slightly compared to the full\n- * table in the ARM ARM.\n- */\n- pac = FIELD_EX64(cr, DBGWCR, PAC);\n- hmc = FIELD_EX64(cr, DBGWCR, HMC);\n- ssc = FIELD_EX64(cr, DBGWCR, SSC);\n-\n- switch (ssc) {\n- case 0:\n- break;\n- case 1:\n- case 3:\n- if (is_secure) {\n- return false;\n- }\n- break;\n- case 2:\n- if (!is_secure) {\n- return false;\n- }\n- break;\n- }\n-\n- switch (access_el) {\n- case 3:\n- case 2:\n- if (!hmc) {\n- return false;\n- }\n- break;\n- case 1:\n- if (extract32(pac, 0, 1) == 0) {\n- return false;\n- }\n- break;\n- case 0:\n- if (extract32(pac, 1, 1) == 0) {\n- return false;\n- }\n- break;\n- default:\n- g_assert_not_reached();\n- }\n-\n- wt = FIELD_EX64(cr, DBGWCR, WT);\n- lbn = FIELD_EX64(cr, DBGWCR, LBN);\n-\n- if (wt && !linked_bp_matches(cpu, lbn)) {\n- return false;\n- }\n-\n- return true;\n-}\n-\n-static bool check_watchpoints(ARMCPU *cpu)\n-{\n- CPUARMState *env = &cpu->env;\n- int n;\n-\n- /*\n- * If watchpoints are disabled globally or we can't take debug\n- * exceptions here then watchpoint firings are ignored.\n- */\n- if (extract32(env->cp15.mdscr_el1, 15, 1) == 0\n- || !arm_generate_debug_exceptions(env)) {\n- return false;\n- }\n-\n- for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) {\n- if (bp_wp_matches(cpu, n, true)) {\n- return true;\n- }\n- }\n- return false;\n-}\n-\n-bool arm_debug_check_breakpoint(CPUState *cs)\n-{\n- ARMCPU *cpu = ARM_CPU(cs);\n- CPUARMState *env = &cpu->env;\n- vaddr pc;\n- int n;\n-\n- /*\n- * If breakpoints are disabled globally or we can't take debug\n- * exceptions here then breakpoint firings are ignored.\n- */\n- if (extract32(env->cp15.mdscr_el1, 15, 1) == 0\n- || !arm_generate_debug_exceptions(env)) {\n- return false;\n- }\n-\n- /*\n- * Single-step exceptions have priority over breakpoint exceptions.\n- * If single-step state is active-pending, suppress the bp.\n- */\n- if (arm_singlestep_active(env) && !(env->pstate & PSTATE_SS)) {\n- return false;\n- }\n-\n- /*\n- * PC alignment faults have priority over breakpoint exceptions.\n- */\n- pc = is_a64(env) ? env->pc : env->regs[15];\n- if ((is_a64(env) || !env->thumb) && (pc & 3) != 0) {\n- return false;\n- }\n-\n- /*\n- * Instruction aborts have priority over breakpoint exceptions.\n- * TODO: We would need to look up the page for PC and verify that\n- * it is present and executable.\n- */\n-\n- for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {\n- if (bp_wp_matches(cpu, n, false)) {\n- return true;\n- }\n- }\n- return false;\n-}\n-\n-bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)\n-{\n- /*\n- * Called by core code when a CPU watchpoint fires; need to check if this\n- * is also an architectural watchpoint match.\n- */\n- ARMCPU *cpu = ARM_CPU(cs);\n-\n- return check_watchpoints(cpu);\n-}\n-\n-/*\n- * Return the FSR value for a debug exception (watchpoint, hardware\n- * breakpoint or BKPT insn) targeting the specified exception level.\n- */\n-static uint32_t arm_debug_exception_fsr(CPUARMState *env)\n-{\n- ARMMMUFaultInfo fi = { .type = ARMFault_Debug };\n- int target_el = arm_debug_target_el(env);\n- bool using_lpae;\n-\n- if (arm_feature(env, ARM_FEATURE_M)) {\n- using_lpae = false;\n- } else if (target_el == 2 || arm_el_is_aa64(env, target_el)) {\n- using_lpae = true;\n- } else if (arm_feature(env, ARM_FEATURE_PMSA) &&\n- arm_feature(env, ARM_FEATURE_V8)) {\n- using_lpae = true;\n- } else if (arm_feature(env, ARM_FEATURE_LPAE) &&\n- (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {\n- using_lpae = true;\n- } else {\n- using_lpae = false;\n- }\n-\n- if (using_lpae) {\n- return arm_fi_to_lfsc(&fi);\n- } else {\n- return arm_fi_to_sfsc(&fi);\n- }\n-}\n-\n-void arm_debug_excp_handler(CPUState *cs)\n-{\n- /*\n- * Called by core code when a watchpoint or breakpoint fires;\n- * need to check which one and raise the appropriate exception.\n- */\n- ARMCPU *cpu = ARM_CPU(cs);\n- CPUARMState *env = &cpu->env;\n- CPUWatchpoint *wp_hit = cs->watchpoint_hit;\n-\n- if (wp_hit) {\n- if (wp_hit->flags & BP_CPU) {\n- bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;\n-\n- cs->watchpoint_hit = NULL;\n-\n- env->exception.fsr = arm_debug_exception_fsr(env);\n- env->exception.vaddress = wp_hit->hitaddr;\n- raise_exception_debug(env, EXCP_DATA_ABORT,\n- syn_watchpoint(0, 0, wnr));\n- }\n- } else {\n- uint64_t pc = is_a64(env) ? env->pc : env->regs[15];\n-\n- /*\n- * (1) GDB breakpoints should be handled first.\n- * (2) Do not raise a CPU exception if no CPU breakpoint has fired,\n- * since singlestep is also done by generating a debug internal\n- * exception.\n- */\n- if (cpu_breakpoint_test(cs, pc, BP_GDB)\n- || !cpu_breakpoint_test(cs, pc, BP_CPU)) {\n- return;\n- }\n-\n- env->exception.fsr = arm_debug_exception_fsr(env);\n- /*\n- * FAR is UNKNOWN: clear vaddress to avoid potentially exposing\n- * values to the guest that it shouldn't be able to see at its\n- * exception/security level.\n- */\n- env->exception.vaddress = 0;\n- raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));\n- }\n-}\n-\n-/*\n- * Raise an EXCP_BKPT with the specified syndrome register value,\n- * targeting the correct exception level for debug exceptions.\n- */\n-void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)\n-{\n- int debug_el = arm_debug_target_el(env);\n- int cur_el = arm_current_el(env);\n-\n- /* FSR will only be used if the debug target EL is AArch32. */\n- env->exception.fsr = arm_debug_exception_fsr(env);\n- /*\n- * FAR is UNKNOWN: clear vaddress to avoid potentially exposing\n- * values to the guest that it shouldn't be able to see at its\n- * exception/security level.\n- */\n- env->exception.vaddress = 0;\n- /*\n- * Other kinds of architectural debug exception are ignored if\n- * they target an exception level below the current one (in QEMU\n- * this is checked by arm_generate_debug_exceptions()). Breakpoint\n- * instructions are special because they always generate an exception\n- * to somewhere: if they can't go to the configured debug exception\n- * level they are taken to the current exception level.\n- */\n- if (debug_el < cur_el) {\n- debug_el = cur_el;\n- }\n- raise_exception(env, EXCP_BKPT, syndrome, debug_el);\n-}\n-\n-void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)\n-{\n- raise_exception_debug(env, EXCP_UDEF, syndrome);\n-}\n-\n-void hw_watchpoint_update(ARMCPU *cpu, int n)\n-{\n- CPUARMState *env = &cpu->env;\n- vaddr len = 0;\n- vaddr wvr = env->cp15.dbgwvr[n];\n- uint64_t wcr = env->cp15.dbgwcr[n];\n- int mask;\n- int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;\n-\n- if (env->cpu_watchpoint[n]) {\n- cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]);\n- env->cpu_watchpoint[n] = NULL;\n- }\n-\n- if (!FIELD_EX64(wcr, DBGWCR, E)) {\n- /* E bit clear : watchpoint disabled */\n- return;\n- }\n-\n- switch (FIELD_EX64(wcr, DBGWCR, LSC)) {\n- case 0:\n- /* LSC 00 is reserved and must behave as if the wp is disabled */\n- return;\n- case 1:\n- flags |= BP_MEM_READ;\n- break;\n- case 2:\n- flags |= BP_MEM_WRITE;\n- break;\n- case 3:\n- flags |= BP_MEM_ACCESS;\n- break;\n- }\n-\n- /*\n- * Attempts to use both MASK and BAS fields simultaneously are\n- * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case,\n- * thus generating a watchpoint for every byte in the masked region.\n- */\n- mask = FIELD_EX64(wcr, DBGWCR, MASK);\n- if (mask == 1 || mask == 2) {\n- /*\n- * Reserved values of MASK; we must act as if the mask value was\n- * some non-reserved value, or as if the watchpoint were disabled.\n- * We choose the latter.\n- */\n- return;\n- } else if (mask) {\n- /* Watchpoint covers an aligned area up to 2GB in size */\n- len = 1ULL << mask;\n- /*\n- * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE\n- * whether the watchpoint fires when the unmasked bits match; we opt\n- * to generate the exceptions.\n- */\n- wvr &= ~(len - 1);\n- } else {\n- /* Watchpoint covers bytes defined by the byte address select bits */\n- int bas = FIELD_EX64(wcr, DBGWCR, BAS);\n- int basstart;\n-\n- if (extract64(wvr, 2, 1)) {\n- /*\n- * Deprecated case of an only 4-aligned address. BAS[7:4] are\n- * ignored, and BAS[3:0] define which bytes to watch.\n- */\n- bas &= 0xf;\n- }\n-\n- if (bas == 0) {\n- /* This must act as if the watchpoint is disabled */\n- return;\n- }\n-\n- /*\n- * The BAS bits are supposed to be programmed to indicate a contiguous\n- * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether\n- * we fire for each byte in the word/doubleword addressed by the WVR.\n- * We choose to ignore any non-zero bits after the first range of 1s.\n- */\n- basstart = ctz32(bas);\n- len = cto32(bas >> basstart);\n- wvr += basstart;\n- }\n-\n- cpu_watchpoint_insert(CPU(cpu), wvr, len, flags,\n- &env->cpu_watchpoint[n]);\n-}\n-\n-void hw_watchpoint_update_all(ARMCPU *cpu)\n-{\n- int i;\n- CPUARMState *env = &cpu->env;\n-\n- /*\n- * Completely clear out existing QEMU watchpoints and our array, to\n- * avoid possible stale entries following migration load.\n- */\n- cpu_watchpoint_remove_all(CPU(cpu), BP_CPU);\n- memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint));\n-\n- for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) {\n- hw_watchpoint_update(cpu, i);\n- }\n-}\n-\n-void hw_breakpoint_update(ARMCPU *cpu, int n)\n-{\n- CPUARMState *env = &cpu->env;\n- uint64_t bvr = env->cp15.dbgbvr[n];\n- uint64_t bcr = env->cp15.dbgbcr[n];\n- vaddr addr;\n- int bt;\n- int flags = BP_CPU;\n-\n- if (env->cpu_breakpoint[n]) {\n- cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]);\n- env->cpu_breakpoint[n] = NULL;\n- }\n-\n- if (!extract64(bcr, 0, 1)) {\n- /* E bit clear : watchpoint disabled */\n- return;\n- }\n-\n- bt = extract64(bcr, 20, 4);\n-\n- switch (bt) {\n- case 4: /* unlinked address mismatch (reserved if AArch64) */\n- case 5: /* linked address mismatch (reserved if AArch64) */\n- qemu_log_mask(LOG_UNIMP,\n- \"arm: address mismatch breakpoint types not implemented\\n\");\n- return;\n- case 0: /* unlinked address match */\n- case 1: /* linked address match */\n- {\n- /*\n- * Bits [1:0] are RES0.\n- *\n- * It is IMPLEMENTATION DEFINED whether bits [63:49]\n- * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit\n- * of the VA field ([48] or [52] for FEAT_LVA), or whether the\n- * value is read as written. It is CONSTRAINED UNPREDICTABLE\n- * whether the RESS bits are ignored when comparing an address.\n- * Therefore we are allowed to compare the entire register, which\n- * lets us avoid considering whether FEAT_LVA is actually enabled.\n- *\n- * The BAS field is used to allow setting breakpoints on 16-bit\n- * wide instructions; it is CONSTRAINED UNPREDICTABLE whether\n- * a bp will fire if the addresses covered by the bp and the addresses\n- * covered by the insn overlap but the insn doesn't start at the\n- * start of the bp address range. We choose to require the insn and\n- * the bp to have the same address. The constraints on writing to\n- * BAS enforced in dbgbcr_write mean we have only four cases:\n- * 0b0000 => no breakpoint\n- * 0b0011 => breakpoint on addr\n- * 0b1100 => breakpoint on addr + 2\n- * 0b1111 => breakpoint on addr\n- * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c).\n- */\n- int bas = extract64(bcr, 5, 4);\n- addr = bvr & ~3ULL;\n- if (bas == 0) {\n- return;\n- }\n- if (bas == 0xc) {\n- addr += 2;\n- }\n- break;\n- }\n- case 2: /* unlinked context ID match */\n- case 8: /* unlinked VMID match (reserved if no EL2) */\n- case 10: /* unlinked context ID and VMID match (reserved if no EL2) */\n- qemu_log_mask(LOG_UNIMP,\n- \"arm: unlinked context breakpoint types not implemented\\n\");\n- return;\n- case 9: /* linked VMID match (reserved if no EL2) */\n- case 11: /* linked context ID and VMID match (reserved if no EL2) */\n- case 3: /* linked context ID match */\n- default:\n- /*\n- * We must generate no events for Linked context matches (unless\n- * they are linked to by some other bp/wp, which is handled in\n- * updates for the linking bp/wp). We choose to also generate no events\n- * for reserved values.\n- */\n- return;\n- }\n-\n- cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]);\n-}\n-\n-void hw_breakpoint_update_all(ARMCPU *cpu)\n-{\n- int i;\n- CPUARMState *env = &cpu->env;\n-\n- /*\n- * Completely clear out existing QEMU breakpoints and our array, to\n- * avoid possible stale entries following migration load.\n- */\n- cpu_breakpoint_remove_all(CPU(cpu), BP_CPU);\n- memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint));\n-\n- for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) {\n- hw_breakpoint_update(cpu, i);\n- }\n-}\n-\n-#if !defined(CONFIG_USER_ONLY)\n-\n-vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)\n-{\n- ARMCPU *cpu = ARM_CPU(cs);\n- CPUARMState *env = &cpu->env;\n-\n- /*\n- * In BE32 system mode, target memory is stored byteswapped (on a\n- * little-endian host system), and by the time we reach here (via an\n- * opcode helper) the addresses of subword accesses have been adjusted\n- * to account for that, which means that watchpoints will not match.\n- * Undo the adjustment here.\n- */\n- if (arm_sctlr_b(env)) {\n- if (len == 1) {\n- addr ^= 3;\n- } else if (len == 2) {\n- addr ^= 2;\n- }\n- }\n-\n- return addr;\n-}\n-\n-#endif /* !CONFIG_USER_ONLY */\n-#endif /* CONFIG_TCG */\n-\n /*\n * Check for traps to \"powerdown debug\" registers, which are controlled\n * by MDCR.TDOSA\ndiff --git a/target/arm/debug_helper.c b/target/arm/tcg/debug.c\nsimilarity index 53%\ncopy from target/arm/debug_helper.c\ncopy to target/arm/tcg/debug.c\nindex 579516e154..8edaeebd8a 100644\n--- a/target/arm/debug_helper.c\n+++ b/target/arm/tcg/debug.c\n@@ -1,5 +1,5 @@\n /*\n- * ARM debug helpers.\n+ * ARM debug helpers used by TCG\n *\n * This code is licensed under the GNU GPL v2 or later.\n *\n@@ -17,7 +17,6 @@\n #define HELPER_H \"tcg/helper.h\"\n #include \"exec/helper-proto.h.inc\"\n \n-#ifdef CONFIG_TCG\n /* Return the Exception Level targeted by debug exceptions. */\n static int arm_debug_target_el(CPUARMState *env)\n {\n@@ -781,542 +780,3 @@ vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)\n }\n \n #endif /* !CONFIG_USER_ONLY */\n-#endif /* CONFIG_TCG */\n-\n-/*\n- * Check for traps to \"powerdown debug\" registers, which are controlled\n- * by MDCR.TDOSA\n- */\n-static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri,\n- bool isread)\n-{\n- int el = arm_current_el(env);\n- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);\n- bool mdcr_el2_tdosa = (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TDE) ||\n- (arm_hcr_el2_eff(env) & HCR_TGE);\n-\n- if (el < 2 && mdcr_el2_tdosa) {\n- return CP_ACCESS_TRAP_EL2;\n- }\n- if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) {\n- return CP_ACCESS_TRAP_EL3;\n- }\n- return CP_ACCESS_OK;\n-}\n-\n-/*\n- * Check for traps to \"debug ROM\" registers, which are controlled\n- * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3.\n- */\n-static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri,\n- bool isread)\n-{\n- int el = arm_current_el(env);\n- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);\n- bool mdcr_el2_tdra = (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE) ||\n- (arm_hcr_el2_eff(env) & HCR_TGE);\n-\n- if (el < 2 && mdcr_el2_tdra) {\n- return CP_ACCESS_TRAP_EL2;\n- }\n- if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {\n- return CP_ACCESS_TRAP_EL3;\n- }\n- return CP_ACCESS_OK;\n-}\n-\n-/*\n- * Check for traps to general debug registers, which are controlled\n- * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3.\n- */\n-static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,\n- bool isread)\n-{\n- int el = arm_current_el(env);\n- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);\n- bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||\n- (arm_hcr_el2_eff(env) & HCR_TGE);\n-\n- if (el < 2 && mdcr_el2_tda) {\n- return CP_ACCESS_TRAP_EL2;\n- }\n- if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {\n- return CP_ACCESS_TRAP_EL3;\n- }\n- return CP_ACCESS_OK;\n-}\n-\n-static CPAccessResult access_dbgvcr32(CPUARMState *env, const ARMCPRegInfo *ri,\n- bool isread)\n-{\n- /* MCDR_EL3.TDMA doesn't apply for FEAT_NV traps */\n- if (arm_current_el(env) == 2 && (env->cp15.mdcr_el3 & MDCR_TDA)) {\n- return CP_ACCESS_TRAP_EL3;\n- }\n- return CP_ACCESS_OK;\n-}\n-\n-/*\n- * Check for traps to Debug Comms Channel registers. If FEAT_FGT\n- * is implemented then these are controlled by MDCR_EL2.TDCC for\n- * EL2 and MDCR_EL3.TDCC for EL3. They are also controlled by\n- * the general debug access trap bits MDCR_EL2.TDA and MDCR_EL3.TDA.\n- * For EL0, they are also controlled by MDSCR_EL1.TDCC.\n- */\n-static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri,\n- bool isread)\n-{\n- int el = arm_current_el(env);\n- uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);\n- bool mdscr_el1_tdcc = extract32(env->cp15.mdscr_el1, 12, 1);\n- bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||\n- (arm_hcr_el2_eff(env) & HCR_TGE);\n- bool mdcr_el2_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&\n- (mdcr_el2 & MDCR_TDCC);\n- bool mdcr_el3_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&\n- (env->cp15.mdcr_el3 & MDCR_TDCC);\n-\n- if (el < 1 && mdscr_el1_tdcc) {\n- return CP_ACCESS_TRAP_EL1;\n- }\n- if (el < 2 && (mdcr_el2_tda || mdcr_el2_tdcc)) {\n- return CP_ACCESS_TRAP_EL2;\n- }\n- if (!arm_is_el3_or_mon(env) &&\n- ((env->cp15.mdcr_el3 & MDCR_TDA) || mdcr_el3_tdcc)) {\n- return CP_ACCESS_TRAP_EL3;\n- }\n- return CP_ACCESS_OK;\n-}\n-\n-static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- /*\n- * Writes to OSLAR_EL1 may update the OS lock status, which can be\n- * read via a bit in OSLSR_EL1.\n- */\n- int oslock;\n-\n- if (ri->state == ARM_CP_STATE_AA32) {\n- oslock = (value == 0xC5ACCE55);\n- } else {\n- oslock = value & 1;\n- }\n-\n- env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock);\n-}\n-\n-static void osdlr_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- ARMCPU *cpu = env_archcpu(env);\n- /*\n- * Only defined bit is bit 0 (DLK); if Feat_DoubleLock is not\n- * implemented this is RAZ/WI.\n- */\n- if(arm_feature(env, ARM_FEATURE_AARCH64)\n- ? cpu_isar_feature(aa64_doublelock, cpu)\n- : cpu_isar_feature(aa32_doublelock, cpu)) {\n- env->cp15.osdlr_el1 = value & 1;\n- }\n-}\n-\n-static void dbgclaimset_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- env->cp15.dbgclaim |= (value & 0xFF);\n-}\n-\n-static uint64_t dbgclaimset_read(CPUARMState *env, const ARMCPRegInfo *ri)\n-{\n- /* CLAIM bits are RAO */\n- return 0xFF;\n-}\n-\n-static void dbgclaimclr_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- env->cp15.dbgclaim &= ~(value & 0xFF);\n-}\n-\n-static CPAccessResult access_bogus(CPUARMState *env, const ARMCPRegInfo *ri,\n- bool isread)\n-{\n- /* Always UNDEF, as if this cpreg didn't exist */\n- return CP_ACCESS_UNDEFINED;\n-}\n-\n-static const ARMCPRegInfo debug_cp_reginfo[] = {\n- /*\n- * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped\n- * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1;\n- * unlike DBGDRAR it is never accessible from EL0.\n- * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AArch64\n- * accessor.\n- */\n- { .name = \"DBGDRAR\", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,\n- .access = PL0_R, .accessfn = access_tdra,\n- .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 },\n- { .name = \"MDRAR_EL1\", .state = ARM_CP_STATE_AA64,\n- .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0,\n- .access = PL1_R, .accessfn = access_tdra,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- { .name = \"DBGDSAR\", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,\n- .access = PL0_R, .accessfn = access_tdra,\n- .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 },\n- /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */\n- { .name = \"MDSCR_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_MDSCR_EL1,\n- .nv2_redirect_offset = 0x158,\n- .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),\n- .resetvalue = 0 },\n- /*\n- * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external\n- * Debug Communication Channel is not implemented.\n- */\n- { .name = \"MDCCSR_EL0\", .state = ARM_CP_STATE_AA64,\n- .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,\n- .access = PL0_R, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /*\n- * These registers belong to the Debug Communications Channel,\n- * which is not implemented. However we implement RAZ/WI behaviour\n- * with trapping to prevent spurious SIGILLs if the guest OS does\n- * access them as the support cannot be probed for.\n- */\n- { .name = \"OSDTRRX_EL1\", .state = ARM_CP_STATE_BOTH, .cp = 14,\n- .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,\n- .access = PL1_RW, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- { .name = \"OSDTRTX_EL1\", .state = ARM_CP_STATE_BOTH, .cp = 14,\n- .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,\n- .access = PL1_RW, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /* Architecturally DBGDTRTX is named DBGDTRRX when used for reads */\n- { .name = \"DBGDTRTX_EL0\", .state = ARM_CP_STATE_AA64,\n- .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,\n- .access = PL0_RW, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- { .name = \"DBGDTRTX\", .state = ARM_CP_STATE_AA32, .cp = 14,\n- .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,\n- .access = PL0_RW, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /* This is AArch64-only and is a combination of DBGDTRTX and DBGDTRRX */\n- { .name = \"DBGDTR_EL0\", .state = ARM_CP_STATE_AA64,\n- .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 4, .opc2 = 0,\n- .access = PL0_RW, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /*\n- * This is not a real AArch32 register. We used to incorrectly expose\n- * this due to a QEMU bug; to avoid breaking migration compatibility we\n- * need to continue to provide it so that we don't fail the inbound\n- * migration when it tells us about a sysreg that we don't have.\n- * We set an always-fails .accessfn, which means that the guest doesn't\n- * actually see this register (it will always UNDEF, identically to if\n- * there were no cpreg definition for it other than that we won't print\n- * a LOG_UNIMP message about it), and we set the ARM_CP_NO_GDB flag so the\n- * gdbstub won't see it either.\n- * (We can't just set .access = 0, because add_cpreg_to_hashtable()\n- * helpfully ignores cpregs which aren't accessible to the highest\n- * implemented EL.)\n- *\n- * TODO: implement a system for being able to describe \"this register\n- * can be ignored if it appears in the inbound stream\"; then we can\n- * remove this temporary hack.\n- */\n- { .name = \"BOGUS_DBGDTR_EL0\", .state = ARM_CP_STATE_AA32,\n- .cp = 14, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,\n- .access = PL0_RW, .accessfn = access_bogus,\n- .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 },\n- /*\n- * OSECCR_EL1 provides a mechanism for an operating system\n- * to access the contents of EDECCR. EDECCR is not implemented though,\n- * as is the rest of external device mechanism.\n- */\n- { .name = \"OSECCR_EL1\", .state = ARM_CP_STATE_BOTH, .cp = 14,\n- .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_OSECCR_EL1,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /*\n- * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as\n- * it is unlikely a guest will care.\n- * We don't implement the configurable EL0 access.\n- */\n- { .name = \"DBGDSCRint\", .state = ARM_CP_STATE_AA32,\n- .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,\n- .type = ARM_CP_ALIAS,\n- .access = PL1_R, .accessfn = access_tda,\n- .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },\n- { .name = \"OSLAR_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,\n- .access = PL1_W, .type = ARM_CP_NO_RAW,\n- .accessfn = access_tdosa,\n- .fgt = FGT_OSLAR_EL1,\n- .writefn = oslar_write },\n- { .name = \"OSLSR_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4,\n- .access = PL1_R, .resetvalue = 10,\n- .accessfn = access_tdosa,\n- .fgt = FGT_OSLSR_EL1,\n- .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) },\n- /* Dummy OSDLR_EL1: 32-bit Linux will read this */\n- { .name = \"OSDLR_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4,\n- .access = PL1_RW, .accessfn = access_tdosa,\n- .fgt = FGT_OSDLR_EL1,\n- .writefn = osdlr_write,\n- .fieldoffset = offsetof(CPUARMState, cp15.osdlr_el1) },\n- /*\n- * Dummy DBGVCR: Linux wants to clear this on startup, but we don't\n- * implement vector catch debug events yet.\n- */\n- { .name = \"DBGVCR\",\n- .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,\n- .access = PL1_RW, .accessfn = access_tda,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /*\n- * Dummy MDCCINT_EL1, since we don't implement the Debug Communications\n- * Channel but Linux may try to access this register. The 32-bit\n- * alias is DBGDCCINT.\n- */\n- { .name = \"MDCCINT_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,\n- .access = PL1_RW, .accessfn = access_tdcc,\n- .type = ARM_CP_CONST, .resetvalue = 0 },\n- /*\n- * Dummy DBGCLAIM registers.\n- * \"The architecture does not define any functionality for the CLAIM tag bits.\",\n- * so we only keep the raw bits\n- */\n- { .name = \"DBGCLAIMSET_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 6,\n- .type = ARM_CP_ALIAS,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_DBGCLAIM,\n- .writefn = dbgclaimset_write, .readfn = dbgclaimset_read },\n- { .name = \"DBGCLAIMCLR_EL1\", .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 6,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_DBGCLAIM,\n- .writefn = dbgclaimclr_write, .raw_writefn = raw_write,\n- .fieldoffset = offsetof(CPUARMState, cp15.dbgclaim) },\n-};\n-\n-/* These are present only when EL1 supports AArch32 */\n-static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {\n- /*\n- * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor\n- * to save and restore a 32-bit guest's DBGVCR)\n- */\n- { .name = \"DBGVCR32_EL2\", .state = ARM_CP_STATE_AA64,\n- .opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,\n- .access = PL2_RW, .accessfn = access_dbgvcr32,\n- .type = ARM_CP_CONST | ARM_CP_EL3_NO_EL2_KEEP,\n- .resetvalue = 0 },\n-};\n-\n-static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {\n- /* 64 bit access versions of the (dummy) debug registers */\n- { .name = \"DBGDRAR\", .cp = 14, .crm = 1, .opc1 = 0,\n- .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT | ARM_CP_NO_GDB,\n- .resetvalue = 0 },\n- { .name = \"DBGDSAR\", .cp = 14, .crm = 2, .opc1 = 0,\n- .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT | ARM_CP_NO_GDB,\n- .resetvalue = 0 },\n-};\n-\n-static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- ARMCPU *cpu = env_archcpu(env);\n- int i = ri->crm;\n-\n- /*\n- * Bits [1:0] are RES0.\n- *\n- * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA)\n- * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if\n- * they contain the value written. It is CONSTRAINED UNPREDICTABLE\n- * whether the RESS bits are ignored when comparing an address.\n- *\n- * Therefore we are allowed to compare the entire register, which lets\n- * us avoid considering whether or not FEAT_LVA is actually enabled.\n- */\n- value &= ~3ULL;\n-\n- raw_write(env, ri, value);\n- if (tcg_enabled()) {\n- hw_watchpoint_update(cpu, i);\n- }\n-}\n-\n-static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- ARMCPU *cpu = env_archcpu(env);\n- int i = ri->crm;\n-\n- raw_write(env, ri, value);\n- if (tcg_enabled()) {\n- hw_watchpoint_update(cpu, i);\n- }\n-}\n-\n-static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- ARMCPU *cpu = env_archcpu(env);\n- int i = ri->crm;\n-\n- raw_write(env, ri, value);\n- if (tcg_enabled()) {\n- hw_breakpoint_update(cpu, i);\n- }\n-}\n-\n-static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,\n- uint64_t value)\n-{\n- ARMCPU *cpu = env_archcpu(env);\n- int i = ri->crm;\n-\n- /*\n- * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only\n- * copy of BAS[0].\n- */\n- value = deposit64(value, 6, 1, extract64(value, 5, 1));\n- value = deposit64(value, 8, 1, extract64(value, 7, 1));\n-\n- raw_write(env, ri, value);\n- if (tcg_enabled()) {\n- hw_breakpoint_update(cpu, i);\n- }\n-}\n-\n-void define_debug_regs(ARMCPU *cpu)\n-{\n- /*\n- * Define v7 and v8 architectural debug registers.\n- * These are just dummy implementations for now.\n- */\n- int i;\n- int wrps, brps, ctx_cmps;\n-\n- /*\n- * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot\n- * use AArch32. Given that bit 15 is RES1, if the value is 0 then\n- * the register must not exist for this cpu.\n- */\n- if (cpu->isar.dbgdidr != 0) {\n- ARMCPRegInfo dbgdidr = {\n- .name = \"DBGDIDR\", .cp = 14, .crn = 0, .crm = 0,\n- .opc1 = 0, .opc2 = 0,\n- .access = PL0_R, .accessfn = access_tda,\n- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,\n- };\n- define_one_arm_cp_reg(cpu, &dbgdidr);\n- }\n-\n- /*\n- * DBGDEVID is present in the v7 debug architecture if\n- * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is\n- * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist\n- * from v7.1 of the debug architecture. Because no fields have yet\n- * been defined in DBGDEVID2 (and quite possibly none will ever\n- * be) we don't define an ARMISARegisters field for it.\n- * These registers exist only if EL1 can use AArch32, but that\n- * happens naturally because they are only PL1 accessible anyway.\n- */\n- if (extract32(cpu->isar.dbgdidr, 15, 1)) {\n- ARMCPRegInfo dbgdevid = {\n- .name = \"DBGDEVID\",\n- .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 2, .crn = 7,\n- .access = PL1_R, .accessfn = access_tda,\n- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid,\n- };\n- define_one_arm_cp_reg(cpu, &dbgdevid);\n- }\n- if (cpu_isar_feature(aa32_debugv7p1, cpu)) {\n- ARMCPRegInfo dbgdevid12[] = {\n- {\n- .name = \"DBGDEVID1\",\n- .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 1, .crn = 7,\n- .access = PL1_R, .accessfn = access_tda,\n- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid1,\n- }, {\n- .name = \"DBGDEVID2\",\n- .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 0, .crn = 7,\n- .access = PL1_R, .accessfn = access_tda,\n- .type = ARM_CP_CONST, .resetvalue = 0,\n- },\n- };\n- define_arm_cp_regs(cpu, dbgdevid12);\n- }\n-\n- brps = arm_num_brps(cpu);\n- wrps = arm_num_wrps(cpu);\n- ctx_cmps = arm_num_ctx_cmps(cpu);\n-\n- assert(ctx_cmps <= brps);\n-\n- define_arm_cp_regs(cpu, debug_cp_reginfo);\n- if (cpu_isar_feature(aa64_aa32_el1, cpu)) {\n- define_arm_cp_regs(cpu, debug_aa32_el1_reginfo);\n- }\n-\n- if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {\n- define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);\n- }\n-\n- for (i = 0; i < brps; i++) {\n- char *dbgbvr_el1_name = g_strdup_printf(\"DBGBVR%d_EL1\", i);\n- char *dbgbcr_el1_name = g_strdup_printf(\"DBGBCR%d_EL1\", i);\n- ARMCPRegInfo dbgregs[] = {\n- { .name = dbgbvr_el1_name, .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_DBGBVRN_EL1,\n- .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]),\n- .writefn = dbgbvr_write, .raw_writefn = raw_write\n- },\n- { .name = dbgbcr_el1_name, .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_DBGBCRN_EL1,\n- .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),\n- .writefn = dbgbcr_write, .raw_writefn = raw_write\n- },\n- };\n- define_arm_cp_regs(cpu, dbgregs);\n- g_free(dbgbvr_el1_name);\n- g_free(dbgbcr_el1_name);\n- }\n-\n- for (i = 0; i < wrps; i++) {\n- char *dbgwvr_el1_name = g_strdup_printf(\"DBGWVR%d_EL1\", i);\n- char *dbgwcr_el1_name = g_strdup_printf(\"DBGWCR%d_EL1\", i);\n- ARMCPRegInfo dbgregs[] = {\n- { .name = dbgwvr_el1_name, .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_DBGWVRN_EL1,\n- .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]),\n- .writefn = dbgwvr_write, .raw_writefn = raw_write\n- },\n- { .name = dbgwcr_el1_name, .state = ARM_CP_STATE_BOTH,\n- .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7,\n- .access = PL1_RW, .accessfn = access_tda,\n- .fgt = FGT_DBGWCRN_EL1,\n- .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),\n- .writefn = dbgwcr_write, .raw_writefn = raw_write\n- },\n- };\n- define_arm_cp_regs(cpu, dbgregs);\n- g_free(dbgwvr_el1_name);\n- g_free(dbgwcr_el1_name);\n- }\n-}\ndiff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build\nindex 1b115656c4..6e9aed3e5d 100644\n--- a/target/arm/tcg/meson.build\n+++ b/target/arm/tcg/meson.build\n@@ -65,6 +65,7 @@ arm_common_ss.add(files(\n \n arm_common_system_ss.add(files(\n 'cpregs-at.c',\n+ 'debug.c',\n 'hflags.c',\n 'neon_helper.c',\n 'tlb_helper.c',\n@@ -72,6 +73,7 @@ arm_common_system_ss.add(files(\n 'vfp_helper.c',\n ))\n arm_user_ss.add(files(\n+ 'debug.c',\n 'hflags.c',\n 'neon_helper.c',\n 'tlb_helper.c',\n", "prefixes": [ "1/2" ] }