From: Oleksii Kurochko <oleksii.kurochko@gmail.com>
To: Baptiste Le Duc <baptiste.le-duc@vates.tech>,
xen-devel@lists.xenproject.org
Cc: zhangzheng@iscas.ac.cn,
"Alistair Francis" <alistair.francis@wdc.com>,
"Connor Davis" <connojdavis@gmail.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Anthony PERARD" <anthony.perard@vates.tech>,
"Michal Orzel" <michal.orzel@amd.com>,
"Jan Beulich" <jbeulich@suse.com>,
"Julien Grall" <julien@xen.org>,
"Roger Pau Monné" <roger@xenproject.org>,
"Stefano Stabellini" <sstabellini@kernel.org>
Subject: Re: [PATCH 2/5] xen/riscv: preset A/D bits in Xen's own page-table mappings
Date: Fri, 28 Aug 2026 15:34:46 +0200 [thread overview]
Message-ID: <ec69b941-2648-4c3f-bbee-95d4d56fb543@gmail.com> (raw)
In-Reply-To: <1787844809.8631fc262581453bbf619ec5b2062170.1a043dad225000c4f3@vates.tech>
On 8/27/26 5:33 PM, Baptiste Le Duc wrote:
> The previous patch made p2m_set_permission() always set the PTE A/D bits to
> map pages in G-stage, to avoid a page fault on platforms that implement
> neither Svade nor Svadu, or that declare both in the device tree. Xen's own
> page tables, built by setup_initial_mapping(), never go through
> p2m_set_permission() and need the same fix.
>
> Add PTE_ACCESSED to PTE_LEAF_DEFAULT and make it the minimal common leaf
> permission set by dropping PTE_WRITABLE. Rebuild PAGE_HYPERVISOR_RO,
> PAGE_HYPERVISOR_RW and PAGE_HYPERVISOR_RX from that common base, with
> PAGE_HYPERVISOR_RW also adding PTE_DIRTY. Switch setup_initial_mapping() to
> use these macros for its default, text, and rodata permissions instead of
> the equivalent raw bit lists.
>
> A PTE is a table entry iff PTE_VALID is set and R/W/X are all clear, so
> update pte_is_table() accordingly.
>
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
> ---
> xen/arch/riscv/include/asm/page.h | 14 ++++++++------
> xen/arch/riscv/mm.c | 7 +++----
> 2 files changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/xen/arch/riscv/include/asm/page.h b/xen/arch/riscv/include/asm/page.h
> index b465a90325..5c02f64a17 100644
> --- a/xen/arch/riscv/include/asm/page.h
> +++ b/xen/arch/riscv/include/asm/page.h
> @@ -46,12 +46,12 @@
> #define PTE_PBMT_NOCACHE BIT(61, UL)
> #define PTE_PBMT_IO BIT(62, UL)
>
> -#define PTE_LEAF_DEFAULT (PTE_VALID | PTE_READABLE | PTE_WRITABLE)
> +#define PTE_LEAF_DEFAULT (PTE_VALID | PTE_READABLE | PTE_ACCESSED)
Dropping PTE_WRITABLE here silently changes the permissions of an
existing user of this macro that the patch doesn't touch.
check_pgtbl_mode_support() in mm.c still builds its temporary root entry as:
index = pt_index(page_table_level, aligned_load_start);
stage1_pgtbl_root[index] = paddr_to_pte(aligned_load_start,
PTE_LEAF_DEFAULT | PTE_EXECUTABLE);
Before this patch that evaluated to V|R|W|X (RWX); afterwards it is
V|R|A|X (RX). So the mapping loses write permission.
I believe that is harmless in practice: the entry is only alive between
the csr_write(CSR_SATP, ...) that turns the MMU on and the
csr_write(CSR_SATP, 0) a few lines below, it only has to make the
current instruction stream fetchable so that the SATP mode probe can
complete, and nothing writes through it. Arguably RX is the better
permission set for it anyway. But it is still a behavioural change
rather than a cosmetic one, and the commit message doesn't mention it(it
only talks about setup_initial_mapping()).
Please call it out explicitly there.
While at it, this site should be converted too:
stage1_pgtbl_root[index] = paddr_to_pte(aligned_load_start,
PAGE_HYPERVISOR_RX);
Otherwise the patch converts three sites in setup_initial_mapping() to
the new PAGE_HYPERVISOR_* macros while leaving a fourth one open-coding
the redefined PTE_LEAF_DEFAULT, which is exactly the kind of asymmetry
that makes the redefinition easy to miss on the next change.
After that conversion PTE_LEAF_DEFAULT has no users left
outside page.h itself, so it could either be dropped entirely in favour
of PAGE_HYPERVISOR_{RO,RW,RX}, or renamed to something that reflects its
new meaning (PTE_LEAF_COMMON or similar). "DEFAULT" now names a set that
is not a usable permission on its own, which is misleading.
> #define PTE_TABLE (PTE_VALID)
>
> -#define PAGE_HYPERVISOR_RO (PTE_VALID | PTE_READABLE)
> -#define PAGE_HYPERVISOR_RW (PTE_VALID | PTE_READABLE | PTE_WRITABLE)
> -#define PAGE_HYPERVISOR_RX (PTE_VALID | PTE_READABLE | PTE_EXECUTABLE)
> +#define PAGE_HYPERVISOR_RO (PTE_LEAF_DEFAULT)
> +#define PAGE_HYPERVISOR_RW (PTE_LEAF_DEFAULT | PTE_WRITABLE | PTE_DIRTY)
> +#define PAGE_HYPERVISOR_RX (PTE_LEAF_DEFAULT | PTE_EXECUTABLE)
Adding A/D to PAGE_HYPERVISOR_RW fixes a second site beyond the ones the
commit message mentions, and I think it deserves to be spelled out.
arch_pmap_map() in asm/pmap.h writes the fixmap leaf entry directly:
pte = pte_from_mfn(mfn, PAGE_HYPERVISOR_RW);
write_pte(entry, pte);
i.e. it bypasses pt_update_entry(), which is the place that ORs in
PTE_ACCESSED | PTE_DIRTY for everything going through map_pages_to_xen().
So before this patch every pmap mapping was installed with A=D=0 and
would fault on first access under Svade, in exactly the same way the
boot page tables did.
The commit message currently frames the problem as "Xen's own page
tables, built by setup_initial_mapping()", which undersells the fix.
Please extend it to say that arch_pmap_map() is affected as well, and
that it is fixed by the PAGE_HYPERVISOR_RW change rather than by the
mm.c conversion.
FWIW I checked the remaining leaf-PTE construction sites (paddr_to_pte()
/pte_from_mfn() callers) and with these two the series covers all of
them: everything else either builds table entries (PTE_TABLE) or goes
through pt_update_entry() / p2m_set_permission(), both of which set A/D
themselves.
>
> #define PAGE_HYPERVISOR PAGE_HYPERVISOR_RW
> /*
> @@ -177,7 +177,8 @@ static inline bool pte_is_table(pte_t p)
> *
> * PAGE_HYPERVISOR_RW contains PTE_VALID too.
> */
> - ASSERT(((p.pte & PAGE_HYPERVISOR_RW) != (PTE_VALID | PTE_WRITABLE)));
> + ASSERT((p.pte & (PTE_VALID | PTE_READABLE | PTE_WRITABLE)) !=
> + (PTE_VALID | PTE_WRITABLE));
Please drop the last line of the comment above it:
* PAGE_HYPERVISOR_RW contains PTE_VALID too.
That sentence existed only to explain why the old mask was written as
PAGE_HYPERVISOR_RW, i.e. that the macro is not just R|W but carries
PTE_VALID as well, which is what made the comparison against V|W work.
With the mask now written out literally, the macro is no longer
referenced anywhere in the function, so the line dangles. It is also
inaccurate now, since PAGE_HYPERVISOR_RW carries A and D in addition to V.
~ Oleksii
next prev parent reply other threads:[~2026-08-28 13:35 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 15:27 [PATCH 0/5] xen/riscv: fix boot on missing extensions and MMU setup bugs Baptiste Le Duc
2026-08-27 15:33 ` [PATCH 1/5] xen/riscv: always set A/D bits at boot time Baptiste Le Duc
2026-08-28 10:59 ` Oleksii Kurochko
2026-08-28 13:58 ` Baptiste Le Duc
2026-08-28 16:12 ` Oleksii Kurochko
2026-08-27 15:33 ` [PATCH 2/5] xen/riscv: preset A/D bits in Xen's own page-table mappings Baptiste Le Duc
2026-08-28 13:34 ` Oleksii Kurochko [this message]
2026-08-27 15:33 ` [PATCH 3/5] xen/riscv: make Svpbmt no longer a required extension Baptiste Le Duc
2026-08-28 15:58 ` Oleksii Kurochko
2026-08-27 15:33 ` [PATCH 4/5] xen/riscv: make Zihintpause " Baptiste Le Duc
2026-08-28 8:59 ` Oleksii Kurochko
2026-08-28 9:16 ` Baptiste Le Duc
2026-08-27 15:33 ` [PATCH 5/5] xen/riscv: add SFENCE.VMA after enabling paging Baptiste Le Duc
2026-08-27 16:53 ` Oleksii Kurochko
2026-08-27 16:58 ` Oleksii Kurochko
2026-08-28 7:13 ` Jan Beulich
2026-08-28 8:03 ` Oleksii Kurochko
2026-08-28 8:11 ` Oleksii Kurochko
2026-08-28 8:29 ` Baptiste Le Duc
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ec69b941-2648-4c3f-bbee-95d4d56fb543@gmail.com \
--to=oleksii.kurochko@gmail.com \
--cc=alistair.francis@wdc.com \
--cc=andrew.cooper3@citrix.com \
--cc=anthony.perard@vates.tech \
--cc=baptiste.le-duc@vates.tech \
--cc=connojdavis@gmail.com \
--cc=jbeulich@suse.com \
--cc=julien@xen.org \
--cc=michal.orzel@amd.com \
--cc=roger@xenproject.org \
--cc=sstabellini@kernel.org \
--cc=xen-devel@lists.xenproject.org \
--cc=zhangzheng@iscas.ac.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.