[PATCH v2 0/2] target/loongarch: Fix NX enforcement for PTW helpers

Andrew S. Rightenburg via qemu development posted 2 patches 1 month ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260306073355.899858-1-andrew@rail5.org
Maintainers: Song Gao <gaosong@loongson.cn>
target/loongarch/cpu.c            | 11 +++++++++++
target/loongarch/cpu.h            |  1 +
target/loongarch/tcg/tcg_cpu.c    |  2 +-
target/loongarch/tcg/tlb_helper.c | 25 ++++++++++++++++++++++---
4 files changed, 35 insertions(+), 4 deletions(-)
[PATCH v2 0/2] target/loongarch: Fix NX enforcement for PTW helpers
Posted by Andrew S. Rightenburg via qemu development 1 month ago
From: rail5 <andrew@rail5.org>

Thanks to Bibo Mao <maobibo@loongson.cn> for the quick review and feedback
on the original patch.

The LoongArch ISA defines NX at bit 62 in the page table entry. Under TCG,
NX is checked during translation, but the software page-walk helper (LDPTE)
was masking the whole PTE value with the PALEN mask. This clears upper
permission bits (including NX), allowing execution from NX mappings.

Fix this by masking only the PPN/address field and preserving permission bits,
while also clearing any non-architectural (software) bits via a hardware PTE
mask.

Once NX is enforced, instruction fetches from NX pages correctly raise PNX,
but taking PNX could end up looping because loongarch_cpu_do_interrupt() tried
to fetch the faulting instruction to populate CSR_BADI, which faults with PNX
again. Treat PNX like other instruction-fetch exceptions and skip the CSR_BADI
fetch.

Reported at: https://gitlab.com/qemu-project/qemu/-/issues/3319

Tested with a Linux guest by mapping a page RW, writing a single instruction,
mprotect(PROT_READ) (no exec) and then calling through a function pointer.
With this series applied the guest receives SIGSEGV instead of executing or
hanging.

Changes in v2:
- Patch 1: Touch only helper_ldpte() (leave LDDIR returning a PALEN-masked base addr)
- Patch 1: Drop hard-coded PPN width (use R_TLBENTRY_{32,64}_PPN_MASK)
- Patch 1: Clear software/non-architectural PTE bits via env->hw_pte_mask
- Patch 2: Carry Reviewed-by: Bibo Mao <maobibo@loongson.cn>

rail5 (2):
  target/loongarch: Preserve PTE permission bits in LDPTE
  target/loongarch: Avoid recursive PNX exception on CSR_BADI fetch

 target/loongarch/cpu.c            | 11 +++++++++++
 target/loongarch/cpu.h            |  1 +
 target/loongarch/tcg/tcg_cpu.c    |  2 +-
 target/loongarch/tcg/tlb_helper.c | 25 ++++++++++++++++++++++---
 4 files changed, 35 insertions(+), 4 deletions(-)

-- 
2.47.3
Re: [PATCH v2 0/2] target/loongarch: Fix NX enforcement for PTW helpers
Posted by gaosong 1 month ago
在 2026/3/6 下午3:33, Andrew S. Rightenburg 写道:
> From: rail5 <andrew@rail5.org>
>
> Thanks to Bibo Mao <maobibo@loongson.cn> for the quick review and feedback
> on the original patch.
>
> The LoongArch ISA defines NX at bit 62 in the page table entry. Under TCG,
> NX is checked during translation, but the software page-walk helper (LDPTE)
> was masking the whole PTE value with the PALEN mask. This clears upper
> permission bits (including NX), allowing execution from NX mappings.
>
> Fix this by masking only the PPN/address field and preserving permission bits,
> while also clearing any non-architectural (software) bits via a hardware PTE
> mask.
>
> Once NX is enforced, instruction fetches from NX pages correctly raise PNX,
> but taking PNX could end up looping because loongarch_cpu_do_interrupt() tried
> to fetch the faulting instruction to populate CSR_BADI, which faults with PNX
> again. Treat PNX like other instruction-fetch exceptions and skip the CSR_BADI
> fetch.
>
> Reported at: https://gitlab.com/qemu-project/qemu/-/issues/3319
>
> Tested with a Linux guest by mapping a page RW, writing a single instruction,
> mprotect(PROT_READ) (no exec) and then calling through a function pointer.
> With this series applied the guest receives SIGSEGV instead of executing or
> hanging.
>
> Changes in v2:
> - Patch 1: Touch only helper_ldpte() (leave LDDIR returning a PALEN-masked base addr)
> - Patch 1: Drop hard-coded PPN width (use R_TLBENTRY_{32,64}_PPN_MASK)
> - Patch 1: Clear software/non-architectural PTE bits via env->hw_pte_mask
> - Patch 2: Carry Reviewed-by: Bibo Mao <maobibo@loongson.cn>
>
> rail5 (2):
>    target/loongarch: Preserve PTE permission bits in LDPTE
>    target/loongarch: Avoid recursive PNX exception on CSR_BADI fetch
>
>   target/loongarch/cpu.c            | 11 +++++++++++
>   target/loongarch/cpu.h            |  1 +
>   target/loongarch/tcg/tcg_cpu.c    |  2 +-
>   target/loongarch/tcg/tlb_helper.c | 25 ++++++++++++++++++++++---
>   4 files changed, 35 insertions(+), 4 deletions(-)
>
Reviewed-by: Song Gao <gaosong@loongson.cn>

Thanks.
Song Gao