[PATCH v2 RESEND] tcg/loongarch: strip flag bits in lddir/ldpte address calculation

SignKirigami posted 1 patch 6 days, 16 hours ago
target/loongarch/tcg/tlb_helper.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
[PATCH v2 RESEND] tcg/loongarch: strip flag bits in lddir/ldpte address calculation
Posted by SignKirigami 6 days, 16 hours ago
helper_lddir and helper_ldpte used TARGET_PHYS_MASK (bits 0-47) when
extracting the base address from a directory entry.  This retained flag
bits (V, D, PLV, MAT, etc.) at positions 0-11, which were then OR'd
with the next-level index, producing a wrong physical address whenever
the directory entry carried non-zero flags.

Fix both helpers to extract only the PPN field (bits 12-47) before
computing the address of the next-level page table entry.

Signed-off-by: numpy1314 <xzj13@mail.ustc.edu.cn>
Signed-off-by: SignKirigami <prcups@krgm.moe>
---
This patch is a resend of [1], Sorry for wrongly handling Signed-off-by.
 
[1]: https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg05581.html.
 
 target/loongarch/tcg/tlb_helper.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 40cc076424..529b22347d 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -750,7 +750,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
     }
 
     badvaddr = sys->CSR_TLBRBADV;
-    base = base & palen_mask;
+    base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
     get_dir_base_width(env, &dir_base, &dir_width, level);
     index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
     phys = base | index << 3;
@@ -773,7 +773,6 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
     uint64_t dir_base, dir_width;
     uint8_t  ps;
 
-
     /*
      * The parameter "base" has only two types,
      * one is the page table base address,
@@ -815,9 +814,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
         }
     } else {
         badv = sys->CSR_TLBRBADV;
-
-        base = base & palen_mask;
-
+        base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
         ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
         ptindex = ptindex & ~0x1;   /* clear bit 0 */
         ptoffset0 = ptindex << 3;
-- 
2.55.0
Re: [PATCH v2 RESEND] tcg/loongarch: strip flag bits in lddir/ldpte address calculation
Posted by Bibo Mao 6 days, 15 hours ago

On 2026/9/20 上午10:42, SignKirigami wrote:
> helper_lddir and helper_ldpte used TARGET_PHYS_MASK (bits 0-47) when
> extracting the base address from a directory entry.  This retained flag
> bits (V, D, PLV, MAT, etc.) at positions 0-11, which were then OR'd
For LoongArch, what is scenery with DIR/PTE entry where bit0-bit11 such 
as (V, D, PLV, MAT, etc.) is used, except Huge bit?

Regards
Bibo Mao
> with the next-level index, producing a wrong physical address whenever
> the directory entry carried non-zero flags.
> 
> Fix both helpers to extract only the PPN field (bits 12-47) before
> computing the address of the next-level page table entry.
> 
> Signed-off-by: numpy1314 <xzj13@mail.ustc.edu.cn>
> Signed-off-by: SignKirigami <prcups@krgm.moe>
> ---
> This patch is a resend of [1], Sorry for wrongly handling Signed-off-by.
>   
> [1]: https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg05581.html.
>   
>   target/loongarch/tcg/tlb_helper.c | 7 ++-----
>   1 file changed, 2 insertions(+), 5 deletions(-)
> 
> diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
> index 40cc076424..529b22347d 100644
> --- a/target/loongarch/tcg/tlb_helper.c
> +++ b/target/loongarch/tcg/tlb_helper.c
> @@ -750,7 +750,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
>       }
>   
>       badvaddr = sys->CSR_TLBRBADV;
> -    base = base & palen_mask;
> +    base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
>       get_dir_base_width(env, &dir_base, &dir_width, level);
>       index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
>       phys = base | index << 3;
> @@ -773,7 +773,6 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
>       uint64_t dir_base, dir_width;
>       uint8_t  ps;
>   
> -
>       /*
>        * The parameter "base" has only two types,
>        * one is the page table base address,
> @@ -815,9 +814,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
>           }
>       } else {
>           badv = sys->CSR_TLBRBADV;
> -
> -        base = base & palen_mask;
> -
> +        base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
>           ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
>           ptindex = ptindex & ~0x1;   /* clear bit 0 */
>           ptoffset0 = ptindex << 3;
> 


Re: [PATCH v2 RESEND] tcg/loongarch: strip flag bits in lddir/ldpte address calculation
Posted by SignKirigami 5 days, 15 hours ago
On 2026年9月20日星期日 中国标准时间 11:48:53,Bibo Mao wrote:
> 
> On 2026/9/20 上午10:42, SignKirigami wrote:
> > helper_lddir and helper_ldpte used TARGET_PHYS_MASK (bits 0-47) when
> > extracting the base address from a directory entry.  This retained flag
> > bits (V, D, PLV, MAT, etc.) at positions 0-11, which were then OR'd
> For LoongArch, what is scenery with DIR/PTE entry where bit0-bit11 such 
> as (V, D, PLV, MAT, etc.) is used, except Huge bit?
> 
> Regards
> Bibo Mao
This patch is originally from rcore developers, and it seems to be hardware's 
responsibility to clear 0-11 bits.
Regards
SignKirigami
> > with the next-level index, producing a wrong physical address whenever
> > the directory entry carried non-zero flags.
> > 
> > Fix both helpers to extract only the PPN field (bits 12-47) before
> > computing the address of the next-level page table entry.
> > 
> > Signed-off-by: numpy1314 <xzj13@mail.ustc.edu.cn>
> > Signed-off-by: SignKirigami <prcups@krgm.moe>
> > ---
> > This patch is a resend of [1], Sorry for wrongly handling Signed-off-by.
> >   
> > [1]: https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg05581.html.
> >   
> >   target/loongarch/tcg/tlb_helper.c | 7 ++-----
> >   1 file changed, 2 insertions(+), 5 deletions(-)
> > 
> > diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
> > index 40cc076424..529b22347d 100644
> > --- a/target/loongarch/tcg/tlb_helper.c
> > +++ b/target/loongarch/tcg/tlb_helper.c
> > @@ -750,7 +750,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
> >       }
> >   
> >       badvaddr = sys->CSR_TLBRBADV;
> > -    base = base & palen_mask;
> > +    base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
> >       get_dir_base_width(env, &dir_base, &dir_width, level);
> >       index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
> >       phys = base | index << 3;
> > @@ -773,7 +773,6 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
> >       uint64_t dir_base, dir_width;
> >       uint8_t  ps;
> >   
> > -
> >       /*
> >        * The parameter "base" has only two types,
> >        * one is the page table base address,
> > @@ -815,9 +814,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
> >           }
> >       } else {
> >           badv = sys->CSR_TLBRBADV;
> > -
> > -        base = base & palen_mask;
> > -
> > +        base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
> >           ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
> >           ptindex = ptindex & ~0x1;   /* clear bit 0 */
> >           ptoffset0 = ptindex << 3;
> > 
> 
> 
Re: [PATCH v2 RESEND] tcg/loongarch: strip flag bits in lddir/ldpte address calculation
Posted by Bibo Mao 4 days, 17 hours ago

On 2026/9/21 下午12:17, SignKirigami wrote:
> On 2026年9月20日星期日 中国标准时间 11:48:53,Bibo Mao wrote:
>>
>> On 2026/9/20 上午10:42, SignKirigami wrote:
>>> helper_lddir and helper_ldpte used TARGET_PHYS_MASK (bits 0-47) when
>>> extracting the base address from a directory entry.  This retained flag
>>> bits (V, D, PLV, MAT, etc.) at positions 0-11, which were then OR'd
>> For LoongArch, what is scenery with DIR/PTE entry where bit0-bit11 such
>> as (V, D, PLV, MAT, etc.) is used, except Huge bit?
>>
>> Regards
>> Bibo Mao
> This patch is originally from rcore developers, and it seems to be hardware's
> responsibility to clear 0-11 bits.
Could you show me the web link how hardware clears 0-11 bits with 
LDDIR/LDPTE instruction?

Regards
Bibo Mao

> Regards
> SignKirigami
>>> with the next-level index, producing a wrong physical address whenever
>>> the directory entry carried non-zero flags.
>>>
>>> Fix both helpers to extract only the PPN field (bits 12-47) before
>>> computing the address of the next-level page table entry.
>>>
>>> Signed-off-by: numpy1314 <xzj13@mail.ustc.edu.cn>
>>> Signed-off-by: SignKirigami <prcups@krgm.moe>
>>> ---
>>> This patch is a resend of [1], Sorry for wrongly handling Signed-off-by.
>>>    
>>> [1]: https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg05581.html.
>>>    
>>>    target/loongarch/tcg/tlb_helper.c | 7 ++-----
>>>    1 file changed, 2 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
>>> index 40cc076424..529b22347d 100644
>>> --- a/target/loongarch/tcg/tlb_helper.c
>>> +++ b/target/loongarch/tcg/tlb_helper.c
>>> @@ -750,7 +750,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
>>>        }
>>>    
>>>        badvaddr = sys->CSR_TLBRBADV;
>>> -    base = base & palen_mask;
>>> +    base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
>>>        get_dir_base_width(env, &dir_base, &dir_width, level);
>>>        index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
>>>        phys = base | index << 3;
>>> @@ -773,7 +773,6 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
>>>        uint64_t dir_base, dir_width;
>>>        uint8_t  ps;
>>>    
>>> -
>>>        /*
>>>         * The parameter "base" has only two types,
>>>         * one is the page table base address,
>>> @@ -815,9 +814,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
>>>            }
>>>        } else {
>>>            badv = sys->CSR_TLBRBADV;
>>> -
>>> -        base = base & palen_mask;
>>> -
>>> +        base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
>>>            ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
>>>            ptindex = ptindex & ~0x1;   /* clear bit 0 */
>>>            ptoffset0 = ptindex << 3;
>>>
>>
>>
> 
> 
> 


Re: [PATCH v2 RESEND] tcg/loongarch: strip flag bits in lddir/ldpte address calculation
Posted by SignKirigami 4 days, 16 hours ago
On 2026年9月22日星期二 中国标准时间 09:35:30,Bibo Mao wrote:
> 
> On 2026/9/21 下午12:17, SignKirigami wrote:
> > On 2026年9月20日星期日 中国标准时间 11:48:53,Bibo Mao wrote:
> >>
> >> On 2026/9/20 上午10:42, SignKirigami wrote:
> >>> helper_lddir and helper_ldpte used TARGET_PHYS_MASK (bits 0-47) when
> >>> extracting the base address from a directory entry.  This retained flag
> >>> bits (V, D, PLV, MAT, etc.) at positions 0-11, which were then OR'd
> >> For LoongArch, what is scenery with DIR/PTE entry where bit0-bit11 such
> >> as (V, D, PLV, MAT, etc.) is used, except Huge bit?
> >>
> >> Regards
> >> Bibo Mao
> > This patch is originally from rcore developers, and it seems to be hardware's
> > responsibility to clear 0-11 bits.
> Could you show me the web link how hardware clears 0-11 bits with 
> LDDIR/LDPTE instruction?
> 
> Regards
> Bibo Mao
Sorry I just read the documentation and find no such definition. I will withdraw
this patch.
Regards
SignKirigami
> 
> > Regards
> > SignKirigami
> >>> with the next-level index, producing a wrong physical address whenever
> >>> the directory entry carried non-zero flags.
> >>>
> >>> Fix both helpers to extract only the PPN field (bits 12-47) before
> >>> computing the address of the next-level page table entry.
> >>>
> >>> Signed-off-by: numpy1314 <xzj13@mail.ustc.edu.cn>
> >>> Signed-off-by: SignKirigami <prcups@krgm.moe>
> >>> ---
> >>> This patch is a resend of [1], Sorry for wrongly handling Signed-off-by.
> >>>    
> >>> [1]: https://lists.gnu.org/archive/html/qemu-devel/2026-09/msg05581.html.
> >>>    
> >>>    target/loongarch/tcg/tlb_helper.c | 7 ++-----
> >>>    1 file changed, 2 insertions(+), 5 deletions(-)
> >>>
> >>> diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
> >>> index 40cc076424..529b22347d 100644
> >>> --- a/target/loongarch/tcg/tlb_helper.c
> >>> +++ b/target/loongarch/tcg/tlb_helper.c
> >>> @@ -750,7 +750,7 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
> >>>        }
> >>>    
> >>>        badvaddr = sys->CSR_TLBRBADV;
> >>> -    base = base & palen_mask;
> >>> +    base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
> >>>        get_dir_base_width(env, &dir_base, &dir_width, level);
> >>>        index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
> >>>        phys = base | index << 3;
> >>> @@ -773,7 +773,6 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
> >>>        uint64_t dir_base, dir_width;
> >>>        uint8_t  ps;
> >>>    
> >>> -
> >>>        /*
> >>>         * The parameter "base" has only two types,
> >>>         * one is the page table base address,
> >>> @@ -815,9 +814,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
> >>>            }
> >>>        } else {
> >>>            badv = sys->CSR_TLBRBADV;
> >>> -
> >>> -        base = base & palen_mask;
> >>> -
> >>> +        base = base & palen_mask & ~MAKE_64BIT_MASK(0, 12);
> >>>            ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
> >>>            ptindex = ptindex & ~0x1;   /* clear bit 0 */
> >>>            ptoffset0 = ptindex << 3;
> >>>
> >>
> >>
> > 
> > 
> > 
> 
>