get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 808321,
    "url": "http://patchwork.ozlabs.org/api/patches/808321/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/1504198860-12951-3-git-send-email-Dave.Martin@arm.com/",
    "project": {
        "id": 41,
        "url": "http://patchwork.ozlabs.org/api/projects/41/?format=api",
        "name": "GNU C Library",
        "link_name": "glibc",
        "list_id": "libc-alpha.sourceware.org",
        "list_email": "libc-alpha@sourceware.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1504198860-12951-3-git-send-email-Dave.Martin@arm.com>",
    "list_archive_url": null,
    "date": "2017-08-31T17:00:34",
    "name": "[v2,02/28] arm64: KVM: Hide unsupported AArch64 CPU features from guests",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "5866dcf60303e672b3b3aab4a191fadc9f14929f",
    "submitter": {
        "id": 26612,
        "url": "http://patchwork.ozlabs.org/api/people/26612/?format=api",
        "name": "Dave Martin",
        "email": "Dave.Martin@arm.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/1504198860-12951-3-git-send-email-Dave.Martin@arm.com/mbox/",
    "series": [
        {
            "id": 882,
            "url": "http://patchwork.ozlabs.org/api/series/882/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=882",
            "date": "2017-08-31T17:00:32",
            "name": "ARM Scalable Vector Extension (SVE)",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/882/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/808321/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/808321/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<libc-alpha-return-83963-incoming=patchwork.ozlabs.org@sourceware.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "mailing list libc-alpha@sourceware.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=sourceware.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=libc-alpha-return-83963-incoming=patchwork.ozlabs.org@sourceware.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org; dkim=pass (1024-bit key;\n\tsecure) header.d=sourceware.org header.i=@sourceware.org\n\theader.b=\"Xb3pLmlZ\"; dkim-atps=neutral",
            "sourceware.org; auth=none"
        ],
        "Received": [
            "from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xjpZ81Fkzz9sPt\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri,  1 Sep 2017 03:01:51 +1000 (AEST)",
            "(qmail 78353 invoked by alias); 31 Aug 2017 17:01:30 -0000",
            "(qmail 78244 invoked by uid 89); 31 Aug 2017 17:01:30 -0000"
        ],
        "DomainKey-Signature": "a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:from:to:cc:subject:date:message-id:in-reply-to\n\t:references; q=dns; s=default; b=RV8/H1YYp1UK6r7pYL5nFopeS8c4zeR\n\t+Tx489M5vi8JZQPNTPALInwJ6594kZSFciml+KUda1QKYjZYwZpirK6b4GTolWaA\n\tzZGChORxrHNj03D+2DOZekoQ7T8pSSvYUmIhcp5D4cpw2snbMvRGOQCYoRkaIeqm\n\tj0AX+CQUjrxM=",
        "DKIM-Signature": "v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id\n\t:list-unsubscribe:list-subscribe:list-archive:list-post\n\t:list-help:sender:from:to:cc:subject:date:message-id:in-reply-to\n\t:references; s=default; bh=7gvA/Pd1bHEunYYkQAks9YMPddc=; b=Xb3pL\n\tmlZPIckeiL6zj1x3HqU/pJlaKD4BEGKoQ1A1QHejWF5qQKKnPRCo7xwHNGLdYrMX\n\tZG45r7NpNevjz7C1e5cFeigJyIZtVQc45rY9+TTJFeYmIJi4rY2+3IzK66170bV3\n\t4/6RnmfAvKyn7ghadKxdZeABprniJdE/P8F6kU=",
        "Mailing-List": "contact libc-alpha-help@sourceware.org; run by ezmlm",
        "Precedence": "bulk",
        "List-Id": "<libc-alpha.sourceware.org>",
        "List-Unsubscribe": "<mailto:libc-alpha-unsubscribe-incoming=patchwork.ozlabs.org@sourceware.org>",
        "List-Subscribe": "<mailto:libc-alpha-subscribe@sourceware.org>",
        "List-Archive": "<http://sourceware.org/ml/libc-alpha/>",
        "List-Post": "<mailto:libc-alpha@sourceware.org>",
        "List-Help": "<mailto:libc-alpha-help@sourceware.org>,\n\t<http://sourceware.org/ml/#faqs>",
        "Sender": "libc-alpha-owner@sourceware.org",
        "X-Virus-Found": "No",
        "X-Spam-SWARE-Status": "No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0,\n\tGIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=guest, crm, guests,\n\t20316",
        "X-HELO": "foss.arm.com",
        "From": "Dave Martin <Dave.Martin@arm.com>",
        "To": "linux-arm-kernel@lists.infradead.org",
        "Cc": "Catalin Marinas <catalin.marinas@arm.com>, Will Deacon\n\t<will.deacon@arm.com>, \tArd Biesheuvel <ard.biesheuvel@linaro.org>,\n\t=?utf-8?q?Alex_Benn=C3=A9?= =?utf-8?q?e?= <alex.bennee@linaro.org>,\n\tSzabolcs Nagy <szabolcs.nagy@arm.com>, Richard Sandiford\n\t<richard.sandiford@arm.com>, \tkvmarm@lists.cs.columbia.edu,\n\tlibc-alpha@sourceware.org, \tlinux-arch@vger.kernel.org, Christoffer Dall\n\t<christoffer.dall@linaro.org>, \tMarc Zyngier <marc.zyngier@arm.com>",
        "Subject": "[PATCH v2 02/28] arm64: KVM: Hide unsupported AArch64 CPU features\n\tfrom guests",
        "Date": "Thu, 31 Aug 2017 18:00:34 +0100",
        "Message-Id": "<1504198860-12951-3-git-send-email-Dave.Martin@arm.com>",
        "In-Reply-To": "<1504198860-12951-1-git-send-email-Dave.Martin@arm.com>",
        "References": "<1504198860-12951-1-git-send-email-Dave.Martin@arm.com>"
    },
    "content": "Currently, a guest kernel sees the true CPU feature registers\n(ID_*_EL1) when it reads them using MRS instructions.  This means\nthat the guest will observe features that are present in the\nhardware but the host doesn't understand or doesn't provide support\nfor.  A guest may legimitately try to use such a feature as per the\narchitecture, but use of the feature may trap instead of working\nnormally, triggering undef injection into the guest.\n\nThis is not a problem for the host, but the guest may go wrong when\nrunning on newer hardware than the host knows about.\n\nThis patch hides from guest VMs any AArch64-specific CPU features\nthat the host doesn't support, by exposing to the guest the\nsanitised versions of the registers computed by the cpufeatures\nframework, instead of the true hardware registers.  To achieve\nthis, HCR_EL2.TID3 is now set for AArch64 guests, and emulation\ncode is added to KVM to report the sanitised versions of the\naffected registers in response to MRS and register reads from\nuserspace.\n\nThe affected registers are removed from invariant_sys_regs[] (since\nthe invariant_sys_regs handling is no longer quite correct for\nthem) and added to sys_reg_desgs[], with appropriate access(),\nget_user() and set_user() methods.  No runtime vcpu storage is\nallocated for the registers: instead, they are read on demand from\nthe cpufeatures framework.  This may need modification in the\nfuture if there is a need for userspace to customise the features\nvisible to the guest.\n\nAttempts by userspace to write the registers are handled similarly\nto the current invariant_sys_regs handling: writes are permitted,\nbut only if they don't attempt to change the value.  This is\nsufficient to support VM snapshot/restore from userspace.\n\nBecause of the additional registers, restoring a VM on an older\nkernel may not work unless userspace knows how to handle the extra\nVM registers exposed to the KVM user ABI by this patch.\n\nUnder the principle of least damage, this patch makes no attempt to\nhandle any of the other registers currently in\ninvariant_sys_regs[], or to emulate registers for AArch32: however,\nthese could be handled in a similar way in future, as necessary.\n\nSigned-off-by: Dave Martin <Dave.Martin@arm.com>\nCc: Marc Zyngier <marc.zyngier@arm.com>\n\n---\n\nChanges since v1\n----------------\n\nRequested by Marc Zyngier:\n\n* Get rid of ternary operator use in walk_sys_regs().\n\n* Call write_to_read_only() if an attempt to write an ID reg is\ntrapped, rather than reinventing.\nProbably we won't get there anyway: the architecture says that this\nshould undef at EL1 instead.\n\n* Make ID register sysreg table less cryptic and spread the entries one\nper line.\nAlso, make the architecturally unallocated and allocated but hidden\ncases more clearly distinct.  These require the same behaviour but for\ndifferent reasons, so it's better to identify them as separate.\n\nOther:\n\n* Delete BUG_ON()s that are skipped by construction:\nThese check that the result of sys_reg_to_index() is a 64-bit\nregister, which is always true because sys_reg_to_index()\nexplicitly sets this.\n\n* Remove duplicate const in __access_id_reg args [sparse]\n---\n arch/arm64/include/asm/sysreg.h |   3 +\n arch/arm64/kvm/hyp/switch.c     |   6 +\n arch/arm64/kvm/sys_regs.c       | 282 +++++++++++++++++++++++++++++++++-------\n 3 files changed, 246 insertions(+), 45 deletions(-)",
    "diff": "diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h\nindex f707fed..480ecd6 100644\n--- a/arch/arm64/include/asm/sysreg.h\n+++ b/arch/arm64/include/asm/sysreg.h\n@@ -149,6 +149,9 @@\n #define SYS_ID_AA64DFR0_EL1\t\tsys_reg(3, 0, 0, 5, 0)\n #define SYS_ID_AA64DFR1_EL1\t\tsys_reg(3, 0, 0, 5, 1)\n \n+#define SYS_ID_AA64AFR0_EL1\t\tsys_reg(3, 0, 0, 5, 4)\n+#define SYS_ID_AA64AFR1_EL1\t\tsys_reg(3, 0, 0, 5, 5)\n+\n #define SYS_ID_AA64ISAR0_EL1\t\tsys_reg(3, 0, 0, 6, 0)\n #define SYS_ID_AA64ISAR1_EL1\t\tsys_reg(3, 0, 0, 6, 1)\n \ndiff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c\nindex 945e79c..35a90b8 100644\n--- a/arch/arm64/kvm/hyp/switch.c\n+++ b/arch/arm64/kvm/hyp/switch.c\n@@ -81,11 +81,17 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)\n \t * it will cause an exception.\n \t */\n \tval = vcpu->arch.hcr_el2;\n+\n \tif (!(val & HCR_RW) && system_supports_fpsimd()) {\n \t\twrite_sysreg(1 << 30, fpexc32_el2);\n \t\tisb();\n \t}\n+\n+\tif (val & HCR_RW) /* for AArch64 only: */\n+\t\tval |= HCR_TID3; /* TID3: trap feature register accesses */\n+\n \twrite_sysreg(val, hcr_el2);\n+\n \t/* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */\n \twrite_sysreg(1 << 15, hstr_el2);\n \t/*\ndiff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c\nindex 2e070d3..b1f7552 100644\n--- a/arch/arm64/kvm/sys_regs.c\n+++ b/arch/arm64/kvm/sys_regs.c\n@@ -892,6 +892,137 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu,\n \treturn true;\n }\n \n+/* Read a sanitised cpufeature ID register by sys_reg_desc */\n+static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)\n+{\n+\tu32 id = sys_reg((u32)r->Op0, (u32)r->Op1,\n+\t\t\t (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);\n+\n+\treturn raz ? 0 : read_sanitised_ftr_reg(id);\n+}\n+\n+/* cpufeature ID register access trap handlers */\n+\n+static bool __access_id_reg(struct kvm_vcpu *vcpu,\n+\t\t\t    struct sys_reg_params *p,\n+\t\t\t    const struct sys_reg_desc *r,\n+\t\t\t    bool raz)\n+{\n+\tif (p->is_write)\n+\t\treturn write_to_read_only(vcpu, p, r);\n+\n+\tp->regval = read_id_reg(r, raz);\n+\treturn true;\n+}\n+\n+static bool access_id_reg(struct kvm_vcpu *vcpu,\n+\t\t\t  struct sys_reg_params *p,\n+\t\t\t  const struct sys_reg_desc *r)\n+{\n+\treturn __access_id_reg(vcpu, p, r, false);\n+}\n+\n+static bool access_raz_id_reg(struct kvm_vcpu *vcpu,\n+\t\t\t      struct sys_reg_params *p,\n+\t\t\t      const struct sys_reg_desc *r)\n+{\n+\treturn __access_id_reg(vcpu, p, r, true);\n+}\n+\n+static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);\n+static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);\n+static u64 sys_reg_to_index(const struct sys_reg_desc *reg);\n+\n+/*\n+ * cpufeature ID register user accessors\n+ *\n+ * For now, these registers are immutable for userspace, so no values\n+ * are stored, and for set_id_reg() we don't allow the effective value\n+ * to be changed.\n+ */\n+static int __get_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,\n+\t\t\tbool raz)\n+{\n+\tconst u64 id = sys_reg_to_index(rd);\n+\tconst u64 val = read_id_reg(rd, raz);\n+\n+\treturn reg_to_user(uaddr, &val, id);\n+}\n+\n+static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,\n+\t\t\tbool raz)\n+{\n+\tconst u64 id = sys_reg_to_index(rd);\n+\tint err;\n+\tu64 val;\n+\n+\terr = reg_from_user(&val, uaddr, id);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* This is what we mean by invariant: you can't change it. */\n+\tif (val != read_id_reg(rd, raz))\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static int get_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,\n+\t\t      const struct kvm_one_reg *reg, void __user *uaddr)\n+{\n+\treturn __get_id_reg(rd, uaddr, false);\n+}\n+\n+static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,\n+\t\t      const struct kvm_one_reg *reg, void __user *uaddr)\n+{\n+\treturn __set_id_reg(rd, uaddr, false);\n+}\n+\n+static int get_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,\n+\t\t\t  const struct kvm_one_reg *reg, void __user *uaddr)\n+{\n+\treturn __get_id_reg(rd, uaddr, true);\n+}\n+\n+static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,\n+\t\t\t  const struct kvm_one_reg *reg, void __user *uaddr)\n+{\n+\treturn __set_id_reg(rd, uaddr, true);\n+}\n+\n+/* sys_reg_desc initialiser for known cpufeature ID registers */\n+#define ID_SANITISED(name) {\t\t\t\\\n+\tSYS_DESC(SYS_##name),\t\t\t\\\n+\t.access\t= access_id_reg,\t\t\\\n+\t.get_user = get_id_reg,\t\t\t\\\n+\t.set_user = set_id_reg,\t\t\t\\\n+}\n+\n+/*\n+ * sys_reg_desc initialiser for architecturally unallocated cpufeature ID\n+ * register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2\n+ * (1 <= crm < 8, 0 <= Op2 < 8).\n+ */\n+#define ID_UNALLOCATED(crm, op2) {\t\t\t\\\n+\tOp0(3), Op1(0), CRn(0), CRm(crm), Op2(op2),\t\\\n+\t.access = access_raz_id_reg,\t\t\t\\\n+\t.get_user = get_raz_id_reg,\t\t\t\\\n+\t.set_user = set_raz_id_reg,\t\t\t\\\n+}\n+\n+/*\n+ * sys_reg_desc initialiser for known ID registers that we hide from guests.\n+ * For now, these are exposed just like unallocated ID regs: they appear\n+ * RAZ for the guest.\n+ */\n+#define ID_HIDDEN(name) {\t\t\t\\\n+\tSYS_DESC(SYS_##name),\t\t\t\\\n+\t.access = access_raz_id_reg,\t\t\\\n+\t.get_user = get_raz_id_reg,\t\t\\\n+\t.set_user = set_raz_id_reg,\t\t\\\n+}\n+\n /*\n  * Architected system registers.\n  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2\n@@ -944,6 +1075,84 @@ static const struct sys_reg_desc sys_reg_descs[] = {\n \t{ SYS_DESC(SYS_DBGVCR32_EL2), NULL, reset_val, DBGVCR32_EL2, 0 },\n \n \t{ SYS_DESC(SYS_MPIDR_EL1), NULL, reset_mpidr, MPIDR_EL1 },\n+\n+\t/*\n+\t * ID regs: all ID_SANITISED() entries here must have corresponding\n+\t * entries in arm64_ftr_regs[].\n+\t */\n+\n+\t/* AArch64 mappings of the AArch32 ID registers */\n+\t/* CRm=1 */\n+\tID_SANITISED(ID_PFR0_EL1),\n+\tID_SANITISED(ID_PFR1_EL1),\n+\tID_SANITISED(ID_DFR0_EL1),\n+\tID_HIDDEN(ID_AFR0_EL1),\n+\tID_SANITISED(ID_MMFR0_EL1),\n+\tID_SANITISED(ID_MMFR1_EL1),\n+\tID_SANITISED(ID_MMFR2_EL1),\n+\tID_SANITISED(ID_MMFR3_EL1),\n+\n+\t/* CRm=2 */\n+\tID_SANITISED(ID_ISAR0_EL1),\n+\tID_SANITISED(ID_ISAR1_EL1),\n+\tID_SANITISED(ID_ISAR2_EL1),\n+\tID_SANITISED(ID_ISAR3_EL1),\n+\tID_SANITISED(ID_ISAR4_EL1),\n+\tID_SANITISED(ID_ISAR5_EL1),\n+\tID_SANITISED(ID_MMFR4_EL1),\n+\tID_UNALLOCATED(2,7),\n+\n+\t/* CRm=3 */\n+\tID_SANITISED(MVFR0_EL1),\n+\tID_SANITISED(MVFR1_EL1),\n+\tID_SANITISED(MVFR2_EL1),\n+\tID_UNALLOCATED(3,3),\n+\tID_UNALLOCATED(3,4),\n+\tID_UNALLOCATED(3,5),\n+\tID_UNALLOCATED(3,6),\n+\tID_UNALLOCATED(3,7),\n+\n+\t/* AArch64 ID registers */\n+\t/* CRm=4 */\n+\tID_SANITISED(ID_AA64PFR0_EL1),\n+\tID_SANITISED(ID_AA64PFR1_EL1),\n+\tID_UNALLOCATED(4,2),\n+\tID_UNALLOCATED(4,3),\n+\tID_UNALLOCATED(4,4),\n+\tID_UNALLOCATED(4,5),\n+\tID_UNALLOCATED(4,6),\n+\tID_UNALLOCATED(4,7),\n+\n+\t/* CRm=5 */\n+\tID_SANITISED(ID_AA64DFR0_EL1),\n+\tID_SANITISED(ID_AA64DFR1_EL1),\n+\tID_UNALLOCATED(5,2),\n+\tID_UNALLOCATED(5,3),\n+\tID_HIDDEN(ID_AA64AFR0_EL1),\n+\tID_HIDDEN(ID_AA64AFR1_EL1),\n+\tID_UNALLOCATED(5,6),\n+\tID_UNALLOCATED(5,7),\n+\n+\t/* CRm=6 */\n+\tID_SANITISED(ID_AA64ISAR0_EL1),\n+\tID_SANITISED(ID_AA64ISAR1_EL1),\n+\tID_UNALLOCATED(6,2),\n+\tID_UNALLOCATED(6,3),\n+\tID_UNALLOCATED(6,4),\n+\tID_UNALLOCATED(6,5),\n+\tID_UNALLOCATED(6,6),\n+\tID_UNALLOCATED(6,7),\n+\n+\t/* CRm=7 */\n+\tID_SANITISED(ID_AA64MMFR0_EL1),\n+\tID_SANITISED(ID_AA64MMFR1_EL1),\n+\tID_SANITISED(ID_AA64MMFR2_EL1),\n+\tID_UNALLOCATED(7,3),\n+\tID_UNALLOCATED(7,4),\n+\tID_UNALLOCATED(7,5),\n+\tID_UNALLOCATED(7,6),\n+\tID_UNALLOCATED(7,7),\n+\n \t{ SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },\n \t{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },\n \t{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },\n@@ -1790,8 +1999,8 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,\n \tif (!r)\n \t\tr = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));\n \n-\t/* Not saved in the sys_reg array? */\n-\tif (r && !r->reg)\n+\t/* Not saved in the sys_reg array and not otherwise accessible? */\n+\tif (r && !(r->reg || r->get_user))\n \t\tr = NULL;\n \n \treturn r;\n@@ -1815,20 +2024,6 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,\n FUNCTION_INVARIANT(midr_el1)\n FUNCTION_INVARIANT(ctr_el0)\n FUNCTION_INVARIANT(revidr_el1)\n-FUNCTION_INVARIANT(id_pfr0_el1)\n-FUNCTION_INVARIANT(id_pfr1_el1)\n-FUNCTION_INVARIANT(id_dfr0_el1)\n-FUNCTION_INVARIANT(id_afr0_el1)\n-FUNCTION_INVARIANT(id_mmfr0_el1)\n-FUNCTION_INVARIANT(id_mmfr1_el1)\n-FUNCTION_INVARIANT(id_mmfr2_el1)\n-FUNCTION_INVARIANT(id_mmfr3_el1)\n-FUNCTION_INVARIANT(id_isar0_el1)\n-FUNCTION_INVARIANT(id_isar1_el1)\n-FUNCTION_INVARIANT(id_isar2_el1)\n-FUNCTION_INVARIANT(id_isar3_el1)\n-FUNCTION_INVARIANT(id_isar4_el1)\n-FUNCTION_INVARIANT(id_isar5_el1)\n FUNCTION_INVARIANT(clidr_el1)\n FUNCTION_INVARIANT(aidr_el1)\n \n@@ -1836,20 +2031,6 @@ FUNCTION_INVARIANT(aidr_el1)\n static struct sys_reg_desc invariant_sys_regs[] = {\n \t{ SYS_DESC(SYS_MIDR_EL1), NULL, get_midr_el1 },\n \t{ SYS_DESC(SYS_REVIDR_EL1), NULL, get_revidr_el1 },\n-\t{ SYS_DESC(SYS_ID_PFR0_EL1), NULL, get_id_pfr0_el1 },\n-\t{ SYS_DESC(SYS_ID_PFR1_EL1), NULL, get_id_pfr1_el1 },\n-\t{ SYS_DESC(SYS_ID_DFR0_EL1), NULL, get_id_dfr0_el1 },\n-\t{ SYS_DESC(SYS_ID_AFR0_EL1), NULL, get_id_afr0_el1 },\n-\t{ SYS_DESC(SYS_ID_MMFR0_EL1), NULL, get_id_mmfr0_el1 },\n-\t{ SYS_DESC(SYS_ID_MMFR1_EL1), NULL, get_id_mmfr1_el1 },\n-\t{ SYS_DESC(SYS_ID_MMFR2_EL1), NULL, get_id_mmfr2_el1 },\n-\t{ SYS_DESC(SYS_ID_MMFR3_EL1), NULL, get_id_mmfr3_el1 },\n-\t{ SYS_DESC(SYS_ID_ISAR0_EL1), NULL, get_id_isar0_el1 },\n-\t{ SYS_DESC(SYS_ID_ISAR1_EL1), NULL, get_id_isar1_el1 },\n-\t{ SYS_DESC(SYS_ID_ISAR2_EL1), NULL, get_id_isar2_el1 },\n-\t{ SYS_DESC(SYS_ID_ISAR3_EL1), NULL, get_id_isar3_el1 },\n-\t{ SYS_DESC(SYS_ID_ISAR4_EL1), NULL, get_id_isar4_el1 },\n-\t{ SYS_DESC(SYS_ID_ISAR5_EL1), NULL, get_id_isar5_el1 },\n \t{ SYS_DESC(SYS_CLIDR_EL1), NULL, get_clidr_el1 },\n \t{ SYS_DESC(SYS_AIDR_EL1), NULL, get_aidr_el1 },\n \t{ SYS_DESC(SYS_CTR_EL0), NULL, get_ctr_el0 },\n@@ -2079,12 +2260,31 @@ static bool copy_reg_to_user(const struct sys_reg_desc *reg, u64 __user **uind)\n \treturn true;\n }\n \n+static int walk_one_sys_reg(const struct sys_reg_desc *rd,\n+\t\t\t    u64 __user **uind,\n+\t\t\t    unsigned int *total)\n+{\n+\t/*\n+\t * Ignore registers we trap but don't save,\n+\t * and for which no custom user accessor is provided.\n+\t */\n+\tif (!(rd->reg || rd->get_user))\n+\t\treturn 0;\n+\n+\tif (!copy_reg_to_user(rd, uind))\n+\t\treturn -EFAULT;\n+\n+\t(*total)++;\n+\treturn 0;\n+}\n+\n /* Assumed ordered tables, see kvm_sys_reg_table_init. */\n static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)\n {\n \tconst struct sys_reg_desc *i1, *i2, *end1, *end2;\n \tunsigned int total = 0;\n \tsize_t num;\n+\tint err;\n \n \t/* We check for duplicates here, to allow arch-specific overrides. */\n \ti1 = get_target_table(vcpu->arch.target, true, &num);\n@@ -2098,21 +2298,13 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)\n \twhile (i1 || i2) {\n \t\tint cmp = cmp_sys_reg(i1, i2);\n \t\t/* target-specific overrides generic entry. */\n-\t\tif (cmp <= 0) {\n-\t\t\t/* Ignore registers we trap but don't save. */\n-\t\t\tif (i1->reg) {\n-\t\t\t\tif (!copy_reg_to_user(i1, &uind))\n-\t\t\t\t\treturn -EFAULT;\n-\t\t\t\ttotal++;\n-\t\t\t}\n-\t\t} else {\n-\t\t\t/* Ignore registers we trap but don't save. */\n-\t\t\tif (i2->reg) {\n-\t\t\t\tif (!copy_reg_to_user(i2, &uind))\n-\t\t\t\t\treturn -EFAULT;\n-\t\t\t\ttotal++;\n-\t\t\t}\n-\t\t}\n+\t\tif (cmp <= 0)\n+\t\t\terr = walk_one_sys_reg(i1, &uind, &total);\n+\t\telse\n+\t\t\terr = walk_one_sys_reg(i2, &uind, &total);\n+\n+\t\tif (err)\n+\t\t\treturn err;\n \n \t\tif (cmp <= 0 && ++i1 == end1)\n \t\t\ti1 = NULL;\n",
    "prefixes": [
        "v2",
        "02/28"
    ]
}