get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2217725,
    "url": "http://patchwork.ozlabs.org/api/patches/2217725/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/kvm-riscv/patch/20260330122601.22140-2-fangyu.yu@linux.alibaba.com/",
    "project": {
        "id": 70,
        "url": "http://patchwork.ozlabs.org/api/projects/70/?format=api",
        "name": "Linux KVM RISC-V",
        "link_name": "kvm-riscv",
        "list_id": "kvm-riscv.lists.infradead.org",
        "list_email": "kvm-riscv@lists.infradead.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "http://lists.infradead.org/pipermail/kvm-riscv/",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260330122601.22140-2-fangyu.yu@linux.alibaba.com>",
    "list_archive_url": null,
    "date": "2026-03-30T12:25:58",
    "name": "[v6,1/4] RISC-V: KVM: Support runtime configuration for per-VM's HGATP mode",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "237f260d94357e73b51da32a07c6a329d291b3bd",
    "submitter": {
        "id": 91416,
        "url": "http://patchwork.ozlabs.org/api/people/91416/?format=api",
        "name": null,
        "email": "fangyu.yu@linux.alibaba.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/kvm-riscv/patch/20260330122601.22140-2-fangyu.yu@linux.alibaba.com/mbox/",
    "series": [
        {
            "id": 498017,
            "url": "http://patchwork.ozlabs.org/api/series/498017/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/kvm-riscv/list/?series=498017",
            "date": "2026-03-30T12:25:57",
            "name": "Support runtime configuration for per-VM's HGATP mode",
            "version": 6,
            "mbox": "http://patchwork.ozlabs.org/series/498017/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2217725/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2217725/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.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 secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=UKS/PxrE;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=linux.alibaba.com header.i=@linux.alibaba.com\n header.a=rsa-sha256 header.s=default header.b=DYI3zrVz;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fkr8n0Bygz1yG8\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 30 Mar 2026 23:26:49 +1100 (AEDT)",
            "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1w7Bhf-0000000BFol-1RHP;\n\tMon, 30 Mar 2026 12:26:47 +0000",
            "from out30-99.freemail.mail.aliyun.com ([115.124.30.99])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1w7BhZ-0000000BFjl-2Q04;\n\tMon, 30 Mar 2026 12:26:43 +0000",
            "from localhost.localdomain(mailfrom:fangyu.yu@linux.alibaba.com\n fp:SMTPD_---0X.zfcHu_1774873588 cluster:ay36)\n          by smtp.aliyun-inc.com;\n          Mon, 30 Mar 2026 20:26:29 +0800"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=A2WURd8dgrytGuvs9KvVWMc/vwFG+oIJNDTw6ZddC34=; b=UKS/PxrENtB+pI\n\tzh6VQHUBgQqptalNrkaOE8kFuD2SorKXg+1LevKkmxEJtGhP1zUa9lMfTw73gCxSvBv4/9t70fQ7o\n\t3fL+XaDWENB8boVAqX0BWRh5gd7Cj5285jYgeHeQNjRcZgawu3lkLvKGA0iFFfTsS8aojbgTg2bcq\n\tiK/7iC5DVO+/BsY3mB5sSpC2Cfyy6TvJLi2ww0n9oJmWndLVKxGoANigd+uUsdiaJJXPIBspXHMnD\n\tlJdXw77+g4B6Zo1HMszDewsSVeZNn7XRAWMmMUdcnSPCTA6opgJ+bqyf+t6sei9O2ltQMv61GuwHs\n\tR0Jix2/uAYUghWGICMJA==;",
            "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=linux.alibaba.com; s=default;\n\tt=1774873594; h=From:To:Subject:Date:Message-Id:MIME-Version;\n\tbh=IP4OR0IOXc3EH919Yujr0f/z3szQm2ZfCPxkDR27Nqw=;\n\tb=DYI3zrVzBf/L71TqdPEKIoJzofcJT0EvU40utzMlrUp6NDDjYByWv5HEE7GMp7cGvz4hb6o97GADLaHK7KbrxX5HoeK7zUZSU6RQ8gU88evEAGceMwJOPu+JZcoP2lFArqOCrkRyowTlGiCCdDKH26lxcrGQXGjKukKC1OGsRbU="
        ],
        "X-Alimail-AntiSpam": "\n AC=PASS;BC=-1|-1;BR=01201311R131e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033037033178;MF=fangyu.yu@linux.alibaba.com;NM=1;PH=DS;RN=18;SR=0;TI=SMTPD_---0X.zfcHu_1774873588;",
        "From": "fangyu.yu@linux.alibaba.com",
        "To": "pbonzini@redhat.com,\n\tcorbet@lwn.net,\n\tanup@brainfault.org,\n\tatish.patra@linux.dev,\n\tpjw@kernel.org,\n\tpalmer@dabbelt.com,\n\taou@eecs.berkeley.edu,\n\talex@ghiti.fr,\n\tskhan@linuxfoundation.org",
        "Cc": "guoren@kernel.org,\n\tradim.krcmar@oss.qualcomm.com,\n\tandrew.jones@oss.qualcomm.com,\n\tlinux-doc@vger.kernel.org,\n\tkvm@vger.kernel.org,\n\tkvm-riscv@lists.infradead.org,\n\tlinux-riscv@lists.infradead.org,\n\tlinux-kernel@vger.kernel.org,\n\tFangyu Yu <fangyu.yu@linux.alibaba.com>",
        "Subject": "[PATCH v6 1/4] RISC-V: KVM: Support runtime configuration for\n per-VM's HGATP mode",
        "Date": "Mon, 30 Mar 2026 20:25:58 +0800",
        "Message-Id": "<20260330122601.22140-2-fangyu.yu@linux.alibaba.com>",
        "X-Mailer": "git-send-email 2.39.3 (Apple Git-146)",
        "In-Reply-To": "<20260330122601.22140-1-fangyu.yu@linux.alibaba.com>",
        "References": "<20260330122601.22140-1-fangyu.yu@linux.alibaba.com>",
        "MIME-Version": "1.0",
        "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ",
        "X-CRM114-CacheID": "sfid-20260330_052641_938096_166C3992 ",
        "X-CRM114-Status": "GOOD (  18.81  )",
        "X-Spam-Score": "-14.6 (--------------)",
        "X-Spam-Report": "Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam.  The original\n message has been attached to this so you can view it or label\n similar future email.  If you have any questions, see\n the administrator of that system for details.\n Content preview:  From: Fangyu Yu <fangyu.yu@linux.alibaba.com> Introduces\n one\n    per-VM architecture-specific fields to support runtime configuration of\n the\n    G-stage page table format: - kvm->arch.pgd_levels: the corresponding\n number\n    of page table levels for the selected mode.\n Content analysis details:   (-14.6 points, 5.0 required)\n  pts rule name              description\n ---- ----------------------\n --------------------------------------------------\n -7.5 USER_IN_DEF_DKIM_WL    From: address is in the default DKIM welcome-list\n -7.5 USER_IN_DEF_SPF_WL     From: address is in the default SPF welcome-list\n  0.0 SPF_HELO_NONE          SPF: HELO does not publish an SPF Record\n -0.0 SPF_PASS               SPF: sender matches SPF record\n  0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from\n                             envelope-from domain\n -0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from\n author's\n                             domain\n -0.1 DKIM_VALID             Message has at least one valid DKIM or DK\n signature\n -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n                             [score: 0.0000]\n  1.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The\n                             query to Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                          [115.124.30.99 listed in\n sa-trusted.bondedsender.org]\n  1.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n                              Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                             [115.124.30.99 listed in sa-accredit.habeas.com]\n -0.0 RCVD_IN_DNSWL_NONE     RBL: Sender listed at https://www.dnswl.org/, no\n                             trust\n                             [115.124.30.99 listed in list.dnswl.org]\n  1.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n                              Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                             [115.124.30.99 listed in\n bl.score.senderscore.com]\n  0.0 UNPARSEABLE_RELAY      Informational: message has unparseable relay\n lines\n -0.5 ENV_AND_HDR_SPF_MATCH  Env and Hdr From used in default SPF WL Match",
        "X-BeenThere": "kvm-riscv@lists.infradead.org",
        "X-Mailman-Version": "2.1.34",
        "Precedence": "list",
        "List-Id": "<kvm-riscv.lists.infradead.org>",
        "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/kvm-riscv>,\n <mailto:kvm-riscv-request@lists.infradead.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.infradead.org/pipermail/kvm-riscv/>",
        "List-Post": "<mailto:kvm-riscv@lists.infradead.org>",
        "List-Help": "<mailto:kvm-riscv-request@lists.infradead.org?subject=help>",
        "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/kvm-riscv>,\n <mailto:kvm-riscv-request@lists.infradead.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Sender": "\"kvm-riscv\" <kvm-riscv-bounces@lists.infradead.org>",
        "Errors-To": "kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org"
    },
    "content": "From: Fangyu Yu <fangyu.yu@linux.alibaba.com>\n\nIntroduces one per-VM architecture-specific fields to support runtime\nconfiguration of the G-stage page table format:\n\n- kvm->arch.pgd_levels: the corresponding number of page table levels\n  for the selected mode.\n\nThese fields replace the previous global variables\nkvm_riscv_gstage_mode and kvm_riscv_gstage_pgd_levels, enabling different\nvirtual machines to independently select their G-stage page table format\ninstead of being forced to share the maximum mode detected by the kernel\nat boot time.\n\nSigned-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>\nReviewed-by: Andrew Jones <andrew.jones@oss.qualcomm.com>\n---\n arch/riscv/include/asm/kvm_gstage.h | 37 ++++++++++++----\n arch/riscv/include/asm/kvm_host.h   |  1 +\n arch/riscv/kvm/gstage.c             | 65 ++++++++++++++---------------\n arch/riscv/kvm/main.c               | 12 +++---\n arch/riscv/kvm/mmu.c                | 20 +++++----\n arch/riscv/kvm/vm.c                 |  2 +-\n arch/riscv/kvm/vmid.c               |  3 +-\n 7 files changed, 83 insertions(+), 57 deletions(-)",
    "diff": "diff --git a/arch/riscv/include/asm/kvm_gstage.h b/arch/riscv/include/asm/kvm_gstage.h\nindex 595e2183173e..5aa58d1f692a 100644\n--- a/arch/riscv/include/asm/kvm_gstage.h\n+++ b/arch/riscv/include/asm/kvm_gstage.h\n@@ -29,16 +29,22 @@ struct kvm_gstage_mapping {\n #define kvm_riscv_gstage_index_bits\t10\n #endif\n \n-extern unsigned long kvm_riscv_gstage_mode;\n-extern unsigned long kvm_riscv_gstage_pgd_levels;\n+extern unsigned long kvm_riscv_gstage_max_pgd_levels;\n \n #define kvm_riscv_gstage_pgd_xbits\t2\n #define kvm_riscv_gstage_pgd_size\t(1UL << (HGATP_PAGE_SHIFT + kvm_riscv_gstage_pgd_xbits))\n-#define kvm_riscv_gstage_gpa_bits\t(HGATP_PAGE_SHIFT + \\\n-\t\t\t\t\t (kvm_riscv_gstage_pgd_levels * \\\n-\t\t\t\t\t  kvm_riscv_gstage_index_bits) + \\\n-\t\t\t\t\t kvm_riscv_gstage_pgd_xbits)\n-#define kvm_riscv_gstage_gpa_size\t((gpa_t)(1ULL << kvm_riscv_gstage_gpa_bits))\n+\n+static inline unsigned long kvm_riscv_gstage_gpa_bits(unsigned long pgd_levels)\n+{\n+\treturn (HGATP_PAGE_SHIFT +\n+\t\tpgd_levels * kvm_riscv_gstage_index_bits +\n+\t\tkvm_riscv_gstage_pgd_xbits);\n+}\n+\n+static inline gpa_t kvm_riscv_gstage_gpa_size(unsigned long pgd_levels)\n+{\n+\treturn BIT_ULL(kvm_riscv_gstage_gpa_bits(pgd_levels));\n+}\n \n bool kvm_riscv_gstage_get_leaf(struct kvm_gstage *gstage, gpa_t addr,\n \t\t\t       pte_t **ptepp, u32 *ptep_level);\n@@ -69,4 +75,21 @@ void kvm_riscv_gstage_wp_range(struct kvm_gstage *gstage, gpa_t start, gpa_t end\n \n void kvm_riscv_gstage_mode_detect(void);\n \n+static inline unsigned long kvm_riscv_gstage_mode(unsigned long pgd_levels)\n+{\n+\tswitch (pgd_levels) {\n+\tcase 2:\n+\t\treturn HGATP_MODE_SV32X4;\n+\tcase 3:\n+\t\treturn HGATP_MODE_SV39X4;\n+\tcase 4:\n+\t\treturn HGATP_MODE_SV48X4;\n+\tcase 5:\n+\t\treturn HGATP_MODE_SV57X4;\n+\tdefault:\n+\t\tWARN_ON_ONCE(1);\n+\t\treturn HGATP_MODE_OFF;\n+\t}\n+}\n+\n #endif\ndiff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h\nindex 24585304c02b..478f699e9dec 100644\n--- a/arch/riscv/include/asm/kvm_host.h\n+++ b/arch/riscv/include/asm/kvm_host.h\n@@ -94,6 +94,7 @@ struct kvm_arch {\n \t/* G-stage page table */\n \tpgd_t *pgd;\n \tphys_addr_t pgd_phys;\n+\tunsigned long pgd_levels;\n \n \t/* Guest Timer */\n \tstruct kvm_guest_timer timer;\ndiff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c\nindex b67d60d722c2..4beb9322fe76 100644\n--- a/arch/riscv/kvm/gstage.c\n+++ b/arch/riscv/kvm/gstage.c\n@@ -12,22 +12,21 @@\n #include <asm/kvm_gstage.h>\n \n #ifdef CONFIG_64BIT\n-unsigned long kvm_riscv_gstage_mode __ro_after_init = HGATP_MODE_SV39X4;\n-unsigned long kvm_riscv_gstage_pgd_levels __ro_after_init = 3;\n+unsigned long kvm_riscv_gstage_max_pgd_levels __ro_after_init = 3;\n #else\n-unsigned long kvm_riscv_gstage_mode __ro_after_init = HGATP_MODE_SV32X4;\n-unsigned long kvm_riscv_gstage_pgd_levels __ro_after_init = 2;\n+unsigned long kvm_riscv_gstage_max_pgd_levels __ro_after_init = 2;\n #endif\n \n #define gstage_pte_leaf(__ptep)\t\\\n \t(pte_val(*(__ptep)) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC))\n \n-static inline unsigned long gstage_pte_index(gpa_t addr, u32 level)\n+static inline unsigned long gstage_pte_index(struct kvm_gstage *gstage,\n+\t\t\t\t\t     gpa_t addr, u32 level)\n {\n \tunsigned long mask;\n \tunsigned long shift = HGATP_PAGE_SHIFT + (kvm_riscv_gstage_index_bits * level);\n \n-\tif (level == (kvm_riscv_gstage_pgd_levels - 1))\n+\tif (level == gstage->kvm->arch.pgd_levels - 1)\n \t\tmask = (PTRS_PER_PTE * (1UL << kvm_riscv_gstage_pgd_xbits)) - 1;\n \telse\n \t\tmask = PTRS_PER_PTE - 1;\n@@ -40,12 +39,13 @@ static inline unsigned long gstage_pte_page_vaddr(pte_t pte)\n \treturn (unsigned long)pfn_to_virt(__page_val_to_pfn(pte_val(pte)));\n }\n \n-static int gstage_page_size_to_level(unsigned long page_size, u32 *out_level)\n+static int gstage_page_size_to_level(struct kvm_gstage *gstage, unsigned long page_size,\n+\t\t\t\t     u32 *out_level)\n {\n \tu32 i;\n \tunsigned long psz = 1UL << 12;\n \n-\tfor (i = 0; i < kvm_riscv_gstage_pgd_levels; i++) {\n+\tfor (i = 0; i < gstage->kvm->arch.pgd_levels; i++) {\n \t\tif (page_size == (psz << (i * kvm_riscv_gstage_index_bits))) {\n \t\t\t*out_level = i;\n \t\t\treturn 0;\n@@ -55,21 +55,23 @@ static int gstage_page_size_to_level(unsigned long page_size, u32 *out_level)\n \treturn -EINVAL;\n }\n \n-static int gstage_level_to_page_order(u32 level, unsigned long *out_pgorder)\n+static int gstage_level_to_page_order(struct kvm_gstage *gstage, u32 level,\n+\t\t\t\t      unsigned long *out_pgorder)\n {\n-\tif (kvm_riscv_gstage_pgd_levels < level)\n+\tif (gstage->kvm->arch.pgd_levels < level)\n \t\treturn -EINVAL;\n \n \t*out_pgorder = 12 + (level * kvm_riscv_gstage_index_bits);\n \treturn 0;\n }\n \n-static int gstage_level_to_page_size(u32 level, unsigned long *out_pgsize)\n+static int gstage_level_to_page_size(struct kvm_gstage *gstage, u32 level,\n+\t\t\t\t     unsigned long *out_pgsize)\n {\n \tint rc;\n \tunsigned long page_order = PAGE_SHIFT;\n \n-\trc = gstage_level_to_page_order(level, &page_order);\n+\trc = gstage_level_to_page_order(gstage, level, &page_order);\n \tif (rc)\n \t\treturn rc;\n \n@@ -81,11 +83,11 @@ bool kvm_riscv_gstage_get_leaf(struct kvm_gstage *gstage, gpa_t addr,\n \t\t\t       pte_t **ptepp, u32 *ptep_level)\n {\n \tpte_t *ptep;\n-\tu32 current_level = kvm_riscv_gstage_pgd_levels - 1;\n+\tu32 current_level = gstage->kvm->arch.pgd_levels - 1;\n \n \t*ptep_level = current_level;\n \tptep = (pte_t *)gstage->pgd;\n-\tptep = &ptep[gstage_pte_index(addr, current_level)];\n+\tptep = &ptep[gstage_pte_index(gstage, addr, current_level)];\n \twhile (ptep && pte_val(ptep_get(ptep))) {\n \t\tif (gstage_pte_leaf(ptep)) {\n \t\t\t*ptep_level = current_level;\n@@ -97,7 +99,7 @@ bool kvm_riscv_gstage_get_leaf(struct kvm_gstage *gstage, gpa_t addr,\n \t\t\tcurrent_level--;\n \t\t\t*ptep_level = current_level;\n \t\t\tptep = (pte_t *)gstage_pte_page_vaddr(ptep_get(ptep));\n-\t\t\tptep = &ptep[gstage_pte_index(addr, current_level)];\n+\t\t\tptep = &ptep[gstage_pte_index(gstage, addr, current_level)];\n \t\t} else {\n \t\t\tptep = NULL;\n \t\t}\n@@ -110,7 +112,7 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)\n {\n \tunsigned long order = PAGE_SHIFT;\n \n-\tif (gstage_level_to_page_order(level, &order))\n+\tif (gstage_level_to_page_order(gstage, level, &order))\n \t\treturn;\n \taddr &= ~(BIT(order) - 1);\n \n@@ -125,9 +127,9 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,\n \t\t\t     struct kvm_mmu_memory_cache *pcache,\n \t\t\t     const struct kvm_gstage_mapping *map)\n {\n-\tu32 current_level = kvm_riscv_gstage_pgd_levels - 1;\n+\tu32 current_level = gstage->kvm->arch.pgd_levels - 1;\n \tpte_t *next_ptep = (pte_t *)gstage->pgd;\n-\tpte_t *ptep = &next_ptep[gstage_pte_index(map->addr, current_level)];\n+\tpte_t *ptep = &next_ptep[gstage_pte_index(gstage, map->addr, current_level)];\n \n \tif (current_level < map->level)\n \t\treturn -EINVAL;\n@@ -151,7 +153,7 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,\n \t\t}\n \n \t\tcurrent_level--;\n-\t\tptep = &next_ptep[gstage_pte_index(map->addr, current_level)];\n+\t\tptep = &next_ptep[gstage_pte_index(gstage, map->addr, current_level)];\n \t}\n \n \tif (pte_val(*ptep) != pte_val(map->pte)) {\n@@ -175,7 +177,7 @@ int kvm_riscv_gstage_map_page(struct kvm_gstage *gstage,\n \tout_map->addr = gpa;\n \tout_map->level = 0;\n \n-\tret = gstage_page_size_to_level(page_size, &out_map->level);\n+\tret = gstage_page_size_to_level(gstage, page_size, &out_map->level);\n \tif (ret)\n \t\treturn ret;\n \n@@ -217,7 +219,7 @@ void kvm_riscv_gstage_op_pte(struct kvm_gstage *gstage, gpa_t addr,\n \tu32 next_ptep_level;\n \tunsigned long next_page_size, page_size;\n \n-\tret = gstage_level_to_page_size(ptep_level, &page_size);\n+\tret = gstage_level_to_page_size(gstage, ptep_level, &page_size);\n \tif (ret)\n \t\treturn;\n \n@@ -229,7 +231,7 @@ void kvm_riscv_gstage_op_pte(struct kvm_gstage *gstage, gpa_t addr,\n \tif (ptep_level && !gstage_pte_leaf(ptep)) {\n \t\tnext_ptep = (pte_t *)gstage_pte_page_vaddr(ptep_get(ptep));\n \t\tnext_ptep_level = ptep_level - 1;\n-\t\tret = gstage_level_to_page_size(next_ptep_level, &next_page_size);\n+\t\tret = gstage_level_to_page_size(gstage, next_ptep_level, &next_page_size);\n \t\tif (ret)\n \t\t\treturn;\n \n@@ -263,7 +265,7 @@ void kvm_riscv_gstage_unmap_range(struct kvm_gstage *gstage,\n \n \twhile (addr < end) {\n \t\tfound_leaf = kvm_riscv_gstage_get_leaf(gstage, addr, &ptep, &ptep_level);\n-\t\tret = gstage_level_to_page_size(ptep_level, &page_size);\n+\t\tret = gstage_level_to_page_size(gstage, ptep_level, &page_size);\n \t\tif (ret)\n \t\t\tbreak;\n \n@@ -297,7 +299,7 @@ void kvm_riscv_gstage_wp_range(struct kvm_gstage *gstage, gpa_t start, gpa_t end\n \n \twhile (addr < end) {\n \t\tfound_leaf = kvm_riscv_gstage_get_leaf(gstage, addr, &ptep, &ptep_level);\n-\t\tret = gstage_level_to_page_size(ptep_level, &page_size);\n+\t\tret = gstage_level_to_page_size(gstage, ptep_level, &page_size);\n \t\tif (ret)\n \t\t\tbreak;\n \n@@ -319,39 +321,34 @@ void __init kvm_riscv_gstage_mode_detect(void)\n \t/* Try Sv57x4 G-stage mode */\n \tcsr_write(CSR_HGATP, HGATP_MODE_SV57X4 << HGATP_MODE_SHIFT);\n \tif ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV57X4) {\n-\t\tkvm_riscv_gstage_mode = HGATP_MODE_SV57X4;\n-\t\tkvm_riscv_gstage_pgd_levels = 5;\n+\t\tkvm_riscv_gstage_max_pgd_levels = 5;\n \t\tgoto done;\n \t}\n \n \t/* Try Sv48x4 G-stage mode */\n \tcsr_write(CSR_HGATP, HGATP_MODE_SV48X4 << HGATP_MODE_SHIFT);\n \tif ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV48X4) {\n-\t\tkvm_riscv_gstage_mode = HGATP_MODE_SV48X4;\n-\t\tkvm_riscv_gstage_pgd_levels = 4;\n+\t\tkvm_riscv_gstage_max_pgd_levels = 4;\n \t\tgoto done;\n \t}\n \n \t/* Try Sv39x4 G-stage mode */\n \tcsr_write(CSR_HGATP, HGATP_MODE_SV39X4 << HGATP_MODE_SHIFT);\n \tif ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV39X4) {\n-\t\tkvm_riscv_gstage_mode = HGATP_MODE_SV39X4;\n-\t\tkvm_riscv_gstage_pgd_levels = 3;\n+\t\tkvm_riscv_gstage_max_pgd_levels = 3;\n \t\tgoto done;\n \t}\n #else /* CONFIG_32BIT */\n \t/* Try Sv32x4 G-stage mode */\n \tcsr_write(CSR_HGATP, HGATP_MODE_SV32X4 << HGATP_MODE_SHIFT);\n \tif ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV32X4) {\n-\t\tkvm_riscv_gstage_mode = HGATP_MODE_SV32X4;\n-\t\tkvm_riscv_gstage_pgd_levels = 2;\n+\t\tkvm_riscv_gstage_max_pgd_levels = 2;\n \t\tgoto done;\n \t}\n #endif\n \n \t/* KVM depends on !HGATP_MODE_OFF */\n-\tkvm_riscv_gstage_mode = HGATP_MODE_OFF;\n-\tkvm_riscv_gstage_pgd_levels = 0;\n+\tkvm_riscv_gstage_max_pgd_levels = 0;\n \n done:\n \tcsr_write(CSR_HGATP, 0);\ndiff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c\nindex 0f3fe3986fc0..90ee0a032b9a 100644\n--- a/arch/riscv/kvm/main.c\n+++ b/arch/riscv/kvm/main.c\n@@ -105,17 +105,17 @@ static int __init riscv_kvm_init(void)\n \t\treturn rc;\n \n \tkvm_riscv_gstage_mode_detect();\n-\tswitch (kvm_riscv_gstage_mode) {\n-\tcase HGATP_MODE_SV32X4:\n+\tswitch (kvm_riscv_gstage_max_pgd_levels) {\n+\tcase 2:\n \t\tstr = \"Sv32x4\";\n \t\tbreak;\n-\tcase HGATP_MODE_SV39X4:\n+\tcase 3:\n \t\tstr = \"Sv39x4\";\n \t\tbreak;\n-\tcase HGATP_MODE_SV48X4:\n+\tcase 4:\n \t\tstr = \"Sv48x4\";\n \t\tbreak;\n-\tcase HGATP_MODE_SV57X4:\n+\tcase 5:\n \t\tstr = \"Sv57x4\";\n \t\tbreak;\n \tdefault:\n@@ -164,7 +164,7 @@ static int __init riscv_kvm_init(void)\n \t\t\t (rc) ? slist : \"no features\");\n \t}\n \n-\tkvm_info(\"using %s G-stage page table format\\n\", str);\n+\tkvm_info(\"highest G-stage page table mode is %s\\n\", str);\n \n \tkvm_info(\"VMID %ld bits available\\n\", kvm_riscv_gstage_vmid_bits());\n \ndiff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c\nindex 088d33ba90ed..fbcdd75cb9af 100644\n--- a/arch/riscv/kvm/mmu.c\n+++ b/arch/riscv/kvm/mmu.c\n@@ -67,7 +67,7 @@ int kvm_riscv_mmu_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa,\n \t\tif (!writable)\n \t\t\tmap.pte = pte_wrprotect(map.pte);\n \n-\t\tret = kvm_mmu_topup_memory_cache(&pcache, kvm_riscv_gstage_pgd_levels);\n+\t\tret = kvm_mmu_topup_memory_cache(&pcache, kvm->arch.pgd_levels);\n \t\tif (ret)\n \t\t\tgoto out;\n \n@@ -186,7 +186,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,\n \t * space addressable by the KVM guest GPA space.\n \t */\n \tif ((new->base_gfn + new->npages) >=\n-\t    (kvm_riscv_gstage_gpa_size >> PAGE_SHIFT))\n+\t     kvm_riscv_gstage_gpa_size(kvm->arch.pgd_levels) >> PAGE_SHIFT)\n \t\treturn -EFAULT;\n \n \thva = new->userspace_addr;\n@@ -472,7 +472,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,\n \tmemset(out_map, 0, sizeof(*out_map));\n \n \t/* We need minimum second+third level pages */\n-\tret = kvm_mmu_topup_memory_cache(pcache, kvm_riscv_gstage_pgd_levels);\n+\tret = kvm_mmu_topup_memory_cache(pcache, kvm->arch.pgd_levels);\n \tif (ret) {\n \t\tkvm_err(\"Failed to topup G-stage cache\\n\");\n \t\treturn ret;\n@@ -575,6 +575,7 @@ int kvm_riscv_mmu_alloc_pgd(struct kvm *kvm)\n \t\treturn -ENOMEM;\n \tkvm->arch.pgd = page_to_virt(pgd_page);\n \tkvm->arch.pgd_phys = page_to_phys(pgd_page);\n+\tkvm->arch.pgd_levels = kvm_riscv_gstage_max_pgd_levels;\n \n \treturn 0;\n }\n@@ -590,10 +591,12 @@ void kvm_riscv_mmu_free_pgd(struct kvm *kvm)\n \t\tgstage.flags = 0;\n \t\tgstage.vmid = READ_ONCE(kvm->arch.vmid.vmid);\n \t\tgstage.pgd = kvm->arch.pgd;\n-\t\tkvm_riscv_gstage_unmap_range(&gstage, 0UL, kvm_riscv_gstage_gpa_size, false);\n+\t\tkvm_riscv_gstage_unmap_range(&gstage, 0UL,\n+\t\t\tkvm_riscv_gstage_gpa_size(kvm->arch.pgd_levels), false);\n \t\tpgd = READ_ONCE(kvm->arch.pgd);\n \t\tkvm->arch.pgd = NULL;\n \t\tkvm->arch.pgd_phys = 0;\n+\t\tkvm->arch.pgd_levels = 0;\n \t}\n \tspin_unlock(&kvm->mmu_lock);\n \n@@ -603,11 +606,12 @@ void kvm_riscv_mmu_free_pgd(struct kvm *kvm)\n \n void kvm_riscv_mmu_update_hgatp(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long hgatp = kvm_riscv_gstage_mode << HGATP_MODE_SHIFT;\n-\tstruct kvm_arch *k = &vcpu->kvm->arch;\n+\tstruct kvm_arch *ka = &vcpu->kvm->arch;\n+\tunsigned long hgatp = kvm_riscv_gstage_mode(ka->pgd_levels)\n+\t\t\t      << HGATP_MODE_SHIFT;\n \n-\thgatp |= (READ_ONCE(k->vmid.vmid) << HGATP_VMID_SHIFT) & HGATP_VMID;\n-\thgatp |= (k->pgd_phys >> PAGE_SHIFT) & HGATP_PPN;\n+\thgatp |= (READ_ONCE(ka->vmid.vmid) << HGATP_VMID_SHIFT) & HGATP_VMID;\n+\thgatp |= (ka->pgd_phys >> PAGE_SHIFT) & HGATP_PPN;\n \n \tncsr_write(CSR_HGATP, hgatp);\n \ndiff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c\nindex 13c63ae1a78b..4d82a886102c 100644\n--- a/arch/riscv/kvm/vm.c\n+++ b/arch/riscv/kvm/vm.c\n@@ -199,7 +199,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)\n \t\tr = KVM_USER_MEM_SLOTS;\n \t\tbreak;\n \tcase KVM_CAP_VM_GPA_BITS:\n-\t\tr = kvm_riscv_gstage_gpa_bits;\n+\t\tr = kvm_riscv_gstage_gpa_bits(kvm->arch.pgd_levels);\n \t\tbreak;\n \tdefault:\n \t\tr = 0;\ndiff --git a/arch/riscv/kvm/vmid.c b/arch/riscv/kvm/vmid.c\nindex cf34d448289d..c15bdb1dd8be 100644\n--- a/arch/riscv/kvm/vmid.c\n+++ b/arch/riscv/kvm/vmid.c\n@@ -26,7 +26,8 @@ static DEFINE_SPINLOCK(vmid_lock);\n void __init kvm_riscv_gstage_vmid_detect(void)\n {\n \t/* Figure-out number of VMID bits in HW */\n-\tcsr_write(CSR_HGATP, (kvm_riscv_gstage_mode << HGATP_MODE_SHIFT) | HGATP_VMID);\n+\tcsr_write(CSR_HGATP, (kvm_riscv_gstage_mode(kvm_riscv_gstage_max_pgd_levels) <<\n+\t\t\t      HGATP_MODE_SHIFT) | HGATP_VMID);\n \tvmid_bits = csr_read(CSR_HGATP);\n \tvmid_bits = (vmid_bits & HGATP_VMID) >> HGATP_VMID_SHIFT;\n \tvmid_bits = fls_long(vmid_bits);\n",
    "prefixes": [
        "v6",
        "1/4"
    ]
}