diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index 4ba82a7f81..aa43e57128 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -25,6 +25,7 @@ typedef struct MMUContext { hwaddr physical; int ps; /* page size shift */ int prot; + uint64_t pte_buddy[2]; } MMUContext; static inline bool cpu_has_ptw(CPULoongArchState *env) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index bc89a4d5ee..f42bbcde67 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -159,10 +159,10 @@ static void invalidate_tlb(CPULoongArchState *env, int index) invalidate_tlb_entry(env, index); } -static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb) +/* Prepare tlb entry information in software PTW mode */ +static void sptw_prepare_context(CPULoongArchState *env, MMUContext *context) { uint64_t lo0, lo1, csr_vppn; - uint16_t csr_asid; uint8_t csr_ps; if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { @@ -185,6 +185,25 @@ static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb) lo1 = env->CSR_TLBELO1; } + context->ps = csr_ps; + context->addr = csr_vppn << R_TLB_MISC_VPPN_SHIFT; + context->pte_buddy[0] = lo0; + context->pte_buddy[1] = lo1; +} + +static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb) +{ + uint64_t lo0, lo1, csr_vppn; + uint16_t csr_asid; + uint8_t csr_ps; + MMUContext context; + + sptw_prepare_context(env, &context); + csr_vppn = context.addr >> R_TLB_MISC_VPPN_SHIFT; + csr_ps = context.ps; + lo0 = context.pte_buddy[0]; + lo1 = context.pte_buddy[1]; + /* Store page size in field PS */ tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, PS, csr_ps); tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, VPPN, csr_vppn);