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 5/5] xen/riscv: add SFENCE.VMA after enabling paging
Date: Fri, 28 Aug 2026 10:11:22 +0200 [thread overview]
Message-ID: <f22db381-40c1-4928-85a4-5019da6a9c07@gmail.com> (raw)
In-Reply-To: <9e4778fa-3164-49bc-a921-ce6b251b5db5@gmail.com>
On 8/27/26 6:53 PM, Oleksii Kurochko wrote:
>
>
> On 8/27/26 5:33 PM, Baptiste Le Duc wrote:
>> turn_on_mmu() writes satp to switch on Sv39 paging but never fences
>> afterwards.
>>
>> Xen never allocates a non-zero ASID, so per the Privileged spec, sec.
>> 12.2.1 "Supervisor Memory-Management Fence Instruction":
>>
>> "If the implementation does not provide ASIDs, or software chooses
>> to always use ASID 0, then after every satp write, software should
>> execute SFENCE.VMA with rs1=x0."
>>
>> The spec text around this rule hedges with "may be necessary", but
>> RISC-V spec co-author Andrew Waterman confirmed on the ISA manual
>> issue tracker that the fence after a satp write is not optional in
>> this case: "The SFENCE after the SATP write is definitely necessary
>> ... In general, you need to SFENCE after you've recycled an ASID.
>> Since we don't use ASIDs in the Linux kernel yet, every context
>> switch is effectively an ASID reuse, hence the full TLB flush." [1]
>> The same reasoning applies to Xen: with ASID always 0, this satp
>> write is indistinguishable from an ASID reuse to the hart, so the
>> fence is required for correctness.
>
> But at the moment of execution of turn_on_mmu() we don't use any ASID,
> do we? It was used in check_pgtbl_mode_support() but at the end it is done:
>
> csr_write(CSR_SATP, 0);
>
> sfence_vma();
>
> So basically Bare mode + flush all TLBs presented before and then up to
>
> ...
>
>>
>> Add the missing SFENCE.VMA to order those page-table stores before
>> the hart's first translation under the new mapping.
>>
>> [1] https://github.com/riscv/riscv-isa-manual/issues/226
>>
>> Fixes: f5035d480f7a ("xen: add files needed for minimal riscv build")
>> Assisted-by: Claude:claude-opus-5
>> Signed-off-by: Baptiste Le Duc <baptiste.le-duc@vates.tech>
>> ---
>> xen/arch/riscv/riscv64/head.S | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/xen/arch/riscv/riscv64/head.S b/xen/arch/riscv/riscv64/
>> head.S
>> index 9c40512e61..7f6edc972f 100644
>> --- a/xen/arch/riscv/riscv64/head.S
>> +++ b/xen/arch/riscv/riscv64/head.S
>> @@ -98,6 +98,7 @@ FUNC(turn_on_mmu)
>> srli t1, t1, PAGE_SHIFT
>> or t1, t1, t0
>> csrw CSR_SATP, t1
>
> ... ASID isn't used as we are in Bare mode.
>
> What am I missing?
After the conversation with Jan B. in the separate thread I re-read
documentaion and found that ASID=0 will be used here too as after
check_pgtbl_mode_support() we set Bare mode and ASID 0 will be really
used even in Bare mode as to select MODE=Bare as software must write
zero to the remaining fields of satp (bits 30–0 when SXLEN=32, or bits
59–0 when SXLEN=64) what automatically includes field ASID (so it will
be zero).
But still the full reason why we need sfence.vma here is that TLB could
be polluted with identity mapping (even in Bare mode) and which will be
tagged by ASID=0.
So what about to update commit message with:
```
xen/riscv: flush speculatively cached Bare-mode TLB entries in turn_on_mmu()
The existing SFENCE.VMA before the satp write only orders the page table
stores from setup_initial_pagetables() against subsequent implicit reads.
It does not prevent the CPU from speculatively caching translations
after the fence retires.
According to the RISC-V Privileged specification, implementations are
permitted to speculatively cache Bare-mode identity mappings. Furthermore,
selecting MODE=Bare (which happens during check_pgtbl_mode_support())
requires zeroing the remaining fields of satp, causing ASID=0 to be
actively used in Bare mode. Consequently, the TLB can be polluted with Bare
identity mappings tagged with ASID=0.
Once satp is written to enable Sv39 translation, these cached identity
mappings (tagged with ASID=0) can shadow the true Sv39 translations.
This would lead to translation failures since turn_on_mmu() jumps to
a non-identity-mapped linker address.
Fix this by adding a post-satp-write SFENCE.VMA to invalidate any stale
translations (including Bare-mode identity mappings under ASID=0) before
jumping to the virtual address space.
```
~ Oleksii
next prev parent reply other threads:[~2026-08-28 8:11 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
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 [this message]
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=f22db381-40c1-4928-85a4-5019da6a9c07@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.