:p
atchew
Login
The following changes since commit c0e80879c876cbe4cbde43a92403329bcedf2ba0: Merge tag 'pull-vfio-20251022' of https://github.com/legoater/qemu into staging (2025-10-22 08:01:21 -0500) are available in the Git repository at: https://github.com/bibo-mao/qemu.git tags/pull-loongarch-20251023 for you to fetch changes up to 79ff2eee9a377f654ed0c3533a0874a0e7d6226d: target/loongarch: Add bit A/D checking in TLB entry with PTW supported (2025-10-23 19:43:48 +0800) ---------------------------------------------------------------- pull-loongarch-20251023 queue ---------------------------------------------------------------- Bibo Mao (14): target/loongarch: Use auto method with PTW feature target/loongarch: Add CSR_PWCH write helper function target/loongarch: Add present and write bit with pte entry target/loongarch: Add function sptw_prepare_tlb before adding tlb entry target/loongarch: target/loongarch: Add common function get_tlb_random_index() target/loongarch: Add MMUContext parameter in fill_tlb_entry() target/loongarch: Add debug parameter with loongarch_page_table_walker() target/loongarch: Reserve higher 48 bit PTE attribute with huge page target/loongarch: Move last PTE lookup into page table walker loop target/loongarch: Add field tlb_index to record TLB search info target/loongarch: Add common interface update_tlb_index() target/loongarch: Add basic hardware PTW support target/loongarch: Update matched ptw bit A/D with PTW supported target/loongarch: Add bit A/D checking in TLB entry with PTW supported target/loongarch/cpu-csr.h | 4 + target/loongarch/cpu-mmu.h | 62 ++++++++ target/loongarch/cpu.c | 26 ++++ target/loongarch/cpu.h | 2 + target/loongarch/cpu_helper.c | 146 ++++++++++++++++--- target/loongarch/tcg/csr_helper.c | 15 ++ target/loongarch/tcg/helper.h | 1 + .../tcg/insn_trans/trans_privileged.c.inc | 1 + target/loongarch/tcg/tlb_helper.c | 157 ++++++++++++++++----- 9 files changed, 358 insertions(+), 56 deletions(-)
PTW is short for page table walker, it is hardware page table walker function. With PTW supported, hardware MMU will parse page table table and update TLB entries automatically. This patch adds type OnOffAuto for PTW feature setting. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu.c | 26 ++++++++++++++++++++++++++ target/loongarch/cpu.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -XXX,XX +XXX,XX @@ static void loongarch_set_msgint(Object *obj, bool value, Error **errp) cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, value); } +static bool loongarch_get_ptw(Object *obj, Error **errp) +{ + return LOONGARCH_CPU(obj)->ptw != ON_OFF_AUTO_OFF; +} + +static void loongarch_set_ptw(Object *obj, bool value, Error **errp) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(obj); + + cpu->ptw = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + + if (kvm_enabled()) { + /* PTW feature is only support in TCG mode now */ + return; + } + + cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, HPTW, value); +} + static void loongarch_cpu_post_init(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_post_init(Object *obj) loongarch_set_lasx); object_property_add_bool(obj, "msgint", loongarch_get_msgint, loongarch_set_msgint); + object_property_add_bool(obj, "ptw", loongarch_get_ptw, + loongarch_set_ptw); /* lbt is enabled only in kvm mode, not supported in tcg mode */ + if (kvm_enabled()) { kvm_loongarch_cpu_post_init(cpu); } @@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj) env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); cpu->msgint = ON_OFF_AUTO_OFF; + cpu->ptw = ON_OFF_AUTO_OFF; loongarch_la464_init_csr(obj); loongarch_cpu_post_init(obj); } @@ -XXX,XX +XXX,XX @@ static void loongarch_la132_initfn(Object *obj) data = FIELD_DP32(data, CPUCFG1, CRC, 1); env->cpucfg[1] = data; cpu->msgint = ON_OFF_AUTO_OFF; + cpu->ptw = ON_OFF_AUTO_OFF; } static void loongarch_max_initfn(Object *obj) @@ -XXX,XX +XXX,XX @@ static void loongarch_max_initfn(Object *obj) if (tcg_enabled()) { cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1); cpu->msgint = ON_OFF_AUTO_AUTO; + cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, HPTW, 1); + cpu->ptw = ON_OFF_AUTO_AUTO; } } diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -XXX,XX +XXX,XX @@ FIELD(CPUCFG2, LBT_MIPS, 20, 1) FIELD(CPUCFG2, LBT_ALL, 18, 3) FIELD(CPUCFG2, LSPW, 21, 1) FIELD(CPUCFG2, LAM, 22, 1) +FIELD(CPUCFG2, HPTW, 24, 1) /* cpucfg[3] bits */ FIELD(CPUCFG3, CCDMA, 0, 1) @@ -XXX,XX +XXX,XX @@ struct ArchCPU { uint32_t phy_id; OnOffAuto lbt; OnOffAuto pmu; + OnOffAuto ptw; OnOffAuto lsx; OnOffAuto lasx; OnOffAuto msgint; -- 2.43.5
Bit HPTW_EN in register CSR_PWCH controls enabling hardware page table walker feature when PTW feature is enabled. Otherwise it is reserved bit. Here add register CSR_PWCH write helper function. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-csr.h | 2 ++ target/loongarch/tcg/csr_helper.c | 15 +++++++++++++++ target/loongarch/tcg/helper.h | 1 + .../tcg/insn_trans/trans_privileged.c.inc | 1 + 4 files changed, 19 insertions(+) diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-csr.h +++ b/target/loongarch/cpu-csr.h @@ -XXX,XX +XXX,XX @@ FIELD(CSR_PWCH, DIR3_BASE, 0, 6) FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6) FIELD(CSR_PWCH, DIR4_BASE, 12, 6) FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6) +FIELD(CSR_PWCH, HPTW_EN, 24, 1) +FIELD(CSR_PWCH, RESERVE, 25, 7) #define LOONGARCH_CSR_STLBPS 0x1e /* Stlb page size */ FIELD(CSR_STLBPS, PS, 0, 5) diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/csr_helper.c +++ b/target/loongarch/tcg/csr_helper.c @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) env->CSR_PWCL = val; return old_v; } + +target_ulong helper_csrwr_pwch(CPULoongArchState *env, target_ulong val) +{ + uint8_t has_ptw; + int64_t old_v = env->CSR_PWCH; + + val = FIELD_DP64(val, CSR_PWCH, RESERVE, 0); + has_ptw = FIELD_EX32(env->cpucfg[2], CPUCFG2, HPTW); + if (!has_ptw) { + val = FIELD_DP64(val, CSR_PWCH, HPTW_EN, 0); + } + + env->CSR_PWCH = val; + return old_v; + } diff --git a/target/loongarch/tcg/helper.h b/target/loongarch/tcg/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/helper.h +++ b/target/loongarch/tcg/helper.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(csrwr_asid, i64, env, tl) DEF_HELPER_2(csrwr_tcfg, i64, env, tl) DEF_HELPER_2(csrwr_ticlr, i64, env, tl) DEF_HELPER_2(csrwr_pwcl, i64, env, tl) +DEF_HELPER_2(csrwr_pwch, i64, env, tl) DEF_HELPER_2(iocsrrd_b, i64, env, tl) DEF_HELPER_2(iocsrrd_h, i64, env, tl) DEF_HELPER_2(iocsrrd_w, i64, env, tl) diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc @@ -XXX,XX +XXX,XX @@ void loongarch_csr_translate_init(void) SET_CSR_FUNC(ASID, NULL, gen_helper_csrwr_asid); SET_CSR_FUNC(PGD, gen_helper_csrrd_pgd, NULL); SET_CSR_FUNC(PWCL, NULL, gen_helper_csrwr_pwcl); + SET_CSR_FUNC(PWCH, NULL, gen_helper_csrwr_pwch); SET_CSR_FUNC(CPUID, gen_helper_csrrd_cpuid, NULL); SET_CSR_FUNC(TCFG, NULL, gen_helper_csrwr_tcfg); SET_CSR_FUNC(TVAL, gen_helper_csrrd_tval, NULL); -- 2.43.5
With hardware PTW feature enabled, Present bit and Write bit is checked by hardware, rather Valid bit and Dirty bit. Bit P means that the page is valid and present, and bit W means that the page is writable. The original V bit is treated as access bit, hardware sets this bit if there is a read or write access. Bit D bit is updated by hardware if there is a write access. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-csr.h | 2 ++ target/loongarch/cpu-mmu.h | 31 +++++++++++++++++++++++++++++++ target/loongarch/cpu_helper.c | 7 ++++--- target/loongarch/tcg/tlb_helper.c | 16 ++++++++-------- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-csr.h +++ b/target/loongarch/cpu-csr.h @@ -XXX,XX +XXX,XX @@ FIELD(TLBENTRY, PLV, 2, 2) FIELD(TLBENTRY, MAT, 4, 2) FIELD(TLBENTRY, G, 6, 1) FIELD(TLBENTRY, HUGE, 6, 1) +FIELD(TLBENTRY, P, 7, 1) +FIELD(TLBENTRY, W, 8, 1) FIELD(TLBENTRY, HGLOBAL, 12, 1) FIELD(TLBENTRY, LEVEL, 13, 2) FIELD(TLBENTRY_32, PPN, 8, 24) diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -XXX,XX +XXX,XX @@ typedef struct MMUContext { int prot; } MMUContext; +static inline bool cpu_has_ptw(CPULoongArchState *env) +{ + return !!FIELD_EX64(env->CSR_PWCH, CSR_PWCH, HPTW_EN); +} + +static inline bool pte_present(CPULoongArchState *env, uint64_t entry) +{ + uint8_t present; + + if (cpu_has_ptw(env)) { + present = FIELD_EX64(entry, TLBENTRY, P); + } else { + present = FIELD_EX64(entry, TLBENTRY, V); + } + + return !!present; +} + +static inline bool pte_write(CPULoongArchState *env, uint64_t entry) +{ + uint8_t writable; + + if (cpu_has_ptw(env)) { + writable = FIELD_EX64(entry, TLBENTRY, W); + } else { + writable = FIELD_EX64(entry, TLBENTRY, D); + } + + return !!writable; +} + bool check_ps(CPULoongArchState *ent, uint8_t ps); TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, MMUAccessType access_type, int mmu_idx); diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, { uint64_t plv = mmu_idx; uint64_t tlb_entry, tlb_ppn; - uint8_t tlb_ps, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv; + uint8_t tlb_ps, tlb_plv, tlb_nx, tlb_nr, tlb_rplv; + bool tlb_v, tlb_d; tlb_entry = context->pte; tlb_ps = context->ps; - tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V); - tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D); + tlb_v = pte_present(env, tlb_entry); + tlb_d = pte_write(env, tlb_entry); tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV); if (is_la64(env)) { tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN); diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index) uint8_t tlb_ps; LoongArchTLB *tlb = &env->tlb[index]; int idxmap = BIT(MMU_KERNEL_IDX) | BIT(MMU_USER_IDX); - uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V); - uint8_t tlb_v1 = FIELD_EX64(tlb->tlb_entry1, TLBENTRY, V); uint64_t tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); + bool tlb_v; tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); pagesize = MAKE_64BIT_MASK(tlb_ps, 1); @@ -XXX,XX +XXX,XX @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index) addr = (tlb_vppn << R_TLB_MISC_VPPN_SHIFT) & ~mask; addr = sextract64(addr, 0, TARGET_VIRT_ADDR_SPACE_BITS); - if (tlb_v0) { + tlb_v = pte_present(env, tlb->tlb_entry0); + if (tlb_v) { tlb_flush_range_by_mmuidx(env_cpu(env), addr, pagesize, idxmap, TARGET_LONG_BITS); } - if (tlb_v1) { + tlb_v = pte_present(env, tlb->tlb_entry1); + if (tlb_v) { tlb_flush_range_by_mmuidx(env_cpu(env), addr + pagesize, pagesize, idxmap, TARGET_LONG_BITS); } @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) { int index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); LoongArchTLB *old, new = {}; - bool skip_inv = false; - uint8_t tlb_v0, tlb_v1; + bool skip_inv = false, tlb_v0, tlb_v1; old = env->tlb + index; if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) /* Check whether ASID/VPPN is the same */ if (old->tlb_misc == new.tlb_misc) { /* Check whether both even/odd pages is the same or invalid */ - tlb_v0 = FIELD_EX64(old->tlb_entry0, TLBENTRY, V); - tlb_v1 = FIELD_EX64(old->tlb_entry1, TLBENTRY, V); + tlb_v0 = pte_present(env, old->tlb_entry0); + tlb_v1 = pte_present(env, old->tlb_entry1); if ((!tlb_v0 || new.tlb_entry0 == old->tlb_entry0) && (!tlb_v1 || new.tlb_entry1 == old->tlb_entry1)) { skip_inv = true; -- 2.43.5
With software page table walker, tlb entry comes from CSR registers. however with hardware page table walker, tlb entry comes from page table entry information directly, TLB CSR registers are not necessary. Here add function sptw_prepare_context(), get tlb entry information from TLB CSR registers. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-mmu.h | 1 + target/loongarch/tcg/tlb_helper.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ 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)) { @@ -XXX,XX +XXX,XX @@ 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); -- 2.43.5
With software PTW system, tlb index is calculated randomly when new TLB entry is added. For hardware PTW, it is the same logic to add new TLB entry. Here common function get_tlb_random_index() is added to get random tlb index when adding new TLB entry. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 39 +++++++++++++++++++------------ 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) *old = new; } -void helper_tlbfill(CPULoongArchState *env) +static int get_tlb_random_index(CPULoongArchState *env, vaddr addr, + int pagesize) { - uint64_t address, entryhi; + uint64_t address; int index, set, i, stlb_idx; - uint16_t pagesize, stlb_ps; - uint16_t asid, tlb_asid; + uint16_t asid, tlb_asid, stlb_ps; LoongArchTLB *tlb; uint8_t tlb_e, tlb_g; - if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { - entryhi = env->CSR_TLBREHI; - /* Validity of pagesize is checked in helper_ldpte() */ - pagesize = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, PS); - } else { - entryhi = env->CSR_TLBEHI; - /* Validity of pagesize is checked in helper_tlbrd() */ - pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); - } - /* Validity of stlb_ps is checked in helper_csrwr_stlbps() */ stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); if (pagesize == stlb_ps) { /* Only write into STLB bits [47:13] */ - address = entryhi & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_64_VPPN_SHIFT); + address = addr & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_64_VPPN_SHIFT); set = -1; stlb_idx = (address >> (stlb_ps + 1)) & 0xff; /* [0,255] */ for (i = 0; i < 8; ++i) { @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *env) } } + return index; +} + +void helper_tlbfill(CPULoongArchState *env) +{ + vaddr entryhi; + int index, pagesize; + + if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { + entryhi = env->CSR_TLBREHI; + /* Validity of pagesize is checked in helper_ldpte() */ + pagesize = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, PS); + } else { + entryhi = env->CSR_TLBEHI; + /* Validity of pagesize is checked in helper_tlbrd() */ + pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); + } + + index = get_tlb_random_index(env, entryhi, pagesize); invalidate_tlb(env, index); fill_tlb_entry(env, env->tlb + index); } -- 2.43.5
Function fill_tlb_entry() can be used with hardware PTW in future, here add input parameter MMUContext in fill_tlb_entry(). Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ static void sptw_prepare_context(CPULoongArchState *env, MMUContext *context) context->pte_buddy[1] = lo1; } -static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb) +static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb, + MMUContext *context) { 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]; + 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); @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) int index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); LoongArchTLB *old, new = {}; bool skip_inv = false, tlb_v0, tlb_v1; + MMUContext context; old = env->tlb + index; if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) return; } - fill_tlb_entry(env, &new); + sptw_prepare_context(env, &context); + fill_tlb_entry(env, &new, &context); /* Check whether ASID/VPPN is the same */ if (old->tlb_misc == new.tlb_misc) { /* Check whether both even/odd pages is the same or invalid */ @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *env) { vaddr entryhi; int index, pagesize; + MMUContext context; if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { entryhi = env->CSR_TLBREHI; @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *env) pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); } + sptw_prepare_context(env, &context); index = get_tlb_random_index(env, entryhi, pagesize); invalidate_tlb(env, index); - fill_tlb_entry(env, env->tlb + index); + fill_tlb_entry(env, env->tlb + index, &context); } void helper_tlbclr(CPULoongArchState *env) -- 2.43.5
Add debug parameter with function loongarch_page_table_walker(), in debug mode it is only to get physical address. And It used in future HW PTW usage, bit dirty and access will be updated in HW PTW mode. Also function loongarch_page_table_walker() is renamed as loongarch_ptw() for short. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu_helper.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, return TLBRET_MATCH; } -static TLBRet loongarch_page_table_walker(CPULoongArchState *env, - MMUContext *context, - int access_type, int mmu_idx) +static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, + int access_type, int mmu_idx, int debug) { CPUState *cs = env_cpu(env); target_ulong index, phys; @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_map_address(CPULoongArchState *env, * legal mapping, even if the mapping is not yet in TLB. return 0 if * there is a valid map, else none zero. */ - return loongarch_page_table_walker(env, context, access_type, mmu_idx); + return loongarch_ptw(env, context, access_type, mmu_idx, is_debug); } return TLBRET_NOMATCH; -- 2.43.5
With PTE entry, high bit 48-63 is valid HW bit for PTE attribute, for example bit 63 is RPLV and bit 62 is NX. With page directory table, it is physical address of page table from view of HW, so high bit 48-63 need be discarded. Here reverve high bit 48-63 with huge page since it is PTE entry, and only discard it with page directory table. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu_helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, /* get next level page directory */ index = (address >> dir_base) & ((1 << dir_width) - 1); phys = base | index << 3; - base = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK; + base = ldq_phys(cs->as, phys); if (FIELD_EX64(base, TLBENTRY, HUGE)) { /* base is a huge pte */ break; + } else { + /* Discard high bits with page directory table */ + base &= TARGET_PHYS_MASK; } } -- 2.43.5
The last PTE lookup sentence is much similiar with the whole page table walker loop, move it into the whole loop. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu_helper.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, } base &= TARGET_PHYS_MASK; - for (level = 4; level > 0; level--) { + for (level = 4; level >= 0; level--) { get_dir_base_width(env, &dir_base, &dir_width, level); if (dir_width == 0) { @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, index = (address >> dir_base) & ((1 << dir_width) - 1); phys = base | index << 3; base = ldq_phys(cs->as, phys); - if (FIELD_EX64(base, TLBENTRY, HUGE)) { - /* base is a huge pte */ - break; - } else { - /* Discard high bits with page directory table */ - base &= TARGET_PHYS_MASK; + if (level) { + if (FIELD_EX64(base, TLBENTRY, HUGE)) { + /* base is a huge pte */ + break; + } else { + /* Discard high bits with page directory table */ + base &= TARGET_PHYS_MASK; + } } } /* pte */ - if (FIELD_EX64(base, TLBENTRY, HUGE)) { + if (level > 0) { /* Huge Page. base is pte */ base = FIELD_DP64(base, TLBENTRY, LEVEL, 0); base = FIELD_DP64(base, TLBENTRY, HUGE, 0); @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, base = FIELD_DP64(base, TLBENTRY, HGLOBAL, 0); base = FIELD_DP64(base, TLBENTRY, G, 1); } - } else { - /* Normal Page. base points to pte */ - get_dir_base_width(env, &dir_base, &dir_width, 0); - index = (address >> dir_base) & ((1 << dir_width) - 1); - phys = base | index << 3; - base = ldq_phys(cs->as, phys); } context->ps = dir_base; -- 2.43.5
With hardware PTW function, TLB entry will be searched at first. If there is odd/even page on one TLB entry, and odd page is valid and even page is none. When software access memory with address in even page, hardware PTW will happen and fill new entry in the same TLB entry. Here add field tlb_index to record TLB index when search TLB tables. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-mmu.h | 2 ++ target/loongarch/cpu_helper.c | 3 +++ target/loongarch/tcg/tlb_helper.c | 1 + 3 files changed, 6 insertions(+) diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -XXX,XX +XXX,XX @@ typedef struct MMUContext { hwaddr physical; int ps; /* page size shift */ int prot; + int tlb_index; + int mmu_index; uint64_t pte_buddy[2]; } MMUContext; diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, context->physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) | (context->addr & MAKE_64BIT_MASK(0, tlb_ps)); context->prot = PAGE_READ; + context->mmu_index = tlb_plv; if (tlb_d) { context->prot |= PAGE_WRITE; } @@ -XXX,XX +XXX,XX @@ TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context, if (da & !pg) { context->physical = address & TARGET_PHYS_MASK; context->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + context->mmu_index = MMU_DA_IDX; return TLBRET_MATCH; } @@ -XXX,XX +XXX,XX @@ TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context, if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) { context->physical = dmw_va2pa(env, address, env->CSR_DMW[i]); context->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + context->mmu_index = MMU_DA_IDX; return TLBRET_MATCH; } } diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_map_tlb_entry(CPULoongArchState *env, n = (context->addr >> tlb_ps) & 0x1;/* Odd or even */ context->pte = n ? tlb->tlb_entry1 : tlb->tlb_entry0; context->ps = tlb_ps; + context->tlb_index = index; return loongarch_check_pte(env, context, access_type, mmu_idx); } -- 2.43.5
Common API update_tlb_index() is added here, it is to update TLB entry with specified index. It is called by helper_tlbwr() now, also it can be used by HW PTW when adding new TLB entry. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ void helper_tlbrd(CPULoongArchState *env) } } -void helper_tlbwr(CPULoongArchState *env) +static void update_tlb_index(CPULoongArchState *env, MMUContext *context, + int index) { - int index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); LoongArchTLB *old, new = {}; bool skip_inv = false, tlb_v0, tlb_v1; - MMUContext context; old = env->tlb + index; - if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { - invalidate_tlb(env, index); - return; - } - - sptw_prepare_context(env, &context); - fill_tlb_entry(env, &new, &context); + fill_tlb_entry(env, &new, context); /* Check whether ASID/VPPN is the same */ if (old->tlb_misc == new.tlb_misc) { /* Check whether both even/odd pages is the same or invalid */ @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) *old = new; } +void helper_tlbwr(CPULoongArchState *env) +{ + int index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + MMUContext context; + + if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { + invalidate_tlb(env, index); + return; + } + + sptw_prepare_context(env, &context); + update_tlb_index(env, &context, index); +} + static int get_tlb_random_index(CPULoongArchState *env, vaddr addr, int pagesize) { -- 2.43.5
However with hardware PTW supported, hardware will search page table with TLB miss. Also if there is no TLB miss however bit Present is not set, hardware PTW will happen also. Because there is odd/even page in one TLB entry on LoongArch system, for example in the first time odd TLB entry is valid and even TLB entry is 0. When software accesses with address within even page, there is no TLB miss only that TLB entry is 0. In this condition, hardwre PTW will happen also. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-mmu.h | 2 ++ target/loongarch/cpu_helper.c | 17 ++++++++++++++--- target/loongarch/tcg/tlb_helper.c | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context, MMUAccessType access_type, int mmu_idx, int is_debug); +TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, + int access_type, int mmu_idx, int debug); void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, uint64_t *dir_width, unsigned int level); hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, return TLBRET_MATCH; } -static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, - int access_type, int mmu_idx, int debug) +TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, + int access_type, int mmu_idx, int debug) { CPUState *cs = env_cpu(env); - target_ulong index, phys; + target_ulong index = 0, phys = 0; uint64_t dir_base, dir_width; uint64_t base; int level; @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, if (level) { if (FIELD_EX64(base, TLBENTRY, HUGE)) { /* base is a huge pte */ + index = 0; + dir_base -= 1; break; } else { /* Discard high bits with page directory table */ @@ -XXX,XX +XXX,XX @@ static TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, base = FIELD_DP64(base, TLBENTRY, HGLOBAL, 0); base = FIELD_DP64(base, TLBENTRY, G, 1); } + + context->pte_buddy[index] = base; + context->pte_buddy[1 - index] = base + BIT_ULL(dir_base); + base += (BIT_ULL(dir_base) & address); + } else if (cpu_has_ptw(env)) { + index &= 1; + context->pte_buddy[index] = base; + context->pte_buddy[1 - index] = ldq_phys(cs->as, + phys + 8 * (1 - 2 * index)); } context->ps = dir_base; diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ void helper_invtlb_page_asid_or_g(CPULoongArchState *env, } } +static void ptw_update_tlb(CPULoongArchState *env, MMUContext *context) +{ + int index; + + index = context->tlb_index; + if (index < 0) { + index = get_tlb_random_index(env, context->addr, context->ps); + } + + update_tlb_index(env, context, index); +} + bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) @@ -XXX,XX +XXX,XX @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, /* Data access */ context.addr = address; + context.tlb_index = -1; ret = get_physical_address(env, &context, access_type, mmu_idx, 0); + if (ret != TLBRET_MATCH && cpu_has_ptw(env)) { + /* Take HW PTW if TLB missed or bit P is zero */ + if (ret == TLBRET_NOMATCH || ret == TLBRET_INVALID) { + ret = loongarch_ptw(env, &context, access_type, mmu_idx, 0); + if (ret == TLBRET_MATCH) { + ptw_update_tlb(env, &context); + } + } else if (context.tlb_index >= 0) { + invalidate_tlb(env, context.tlb_index); + } + } + if (ret == TLBRET_MATCH) { physical = context.physical; prot = context.prot; -- 2.43.5
With hardware PTE supported, bit A will be set if there is read access or instruction fetch, and bit D will be set with write access. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-mmu.h | 26 ++++++++++ target/loongarch/cpu_helper.c | 93 ++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -XXX,XX +XXX,XX @@ static inline bool pte_write(CPULoongArchState *env, uint64_t entry) return !!writable; } +/* + * The folloing functions should be called with PTW enable checked + * With hardware PTW enabled + * Bit D will be set by hardware with write access + * Bit A will be set by hardware with read/intruction fetch access + */ +static inline uint64_t pte_mkaccess(uint64_t entry) +{ + return FIELD_DP64(entry, TLBENTRY, V, 1); +} + +static inline uint64_t pte_mkdirty(uint64_t entry) +{ + return FIELD_DP64(entry, TLBENTRY, D, 1); +} + +static inline bool pte_access(uint64_t entry) +{ + return !!FIELD_EX64(entry, TLBENTRY, V); +} + +static inline bool pte_dirty(uint64_t entry) +{ + return !!FIELD_EX64(entry, TLBENTRY, D); +} + bool check_ps(CPULoongArchState *ent, uint8_t ps); TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, MMUAccessType access_type, int mmu_idx); diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, return TLBRET_MATCH; } +static MemTxResult loongarch_cmpxchg_phys(CPUState *cs, hwaddr phys, + uint64_t old, uint64_t new) +{ + hwaddr addr1, l = 8; + MemoryRegion *mr; + uint8_t *ram_ptr; + uint64_t old1; + MemTxResult ret; + + rcu_read_lock(); + mr = address_space_translate(cs->as, phys, &addr1, &l, + false, MEMTXATTRS_UNSPECIFIED); + if (!memory_region_is_ram(mr)) { + /* + * Misconfigured PTE in ROM (AD bits are not preset) or + * PTE is in IO space and can't be updated atomically. + */ + rcu_read_unlock(); + return MEMTX_ACCESS_ERROR; + } + + ram_ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + old1 = qatomic_cmpxchg((uint64_t *)ram_ptr, cpu_to_le64(old), + cpu_to_le64(new)); + old1 = le64_to_cpu(old1); + if (old1 == old) { + ret = MEMTX_OK; + } else { + ret = MEMTX_DECODE_ERROR; + } + rcu_read_unlock(); + + return ret; +} + TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, int access_type, int mmu_idx, int debug) { CPUState *cs = env_cpu(env); target_ulong index = 0, phys = 0; uint64_t dir_base, dir_width; - uint64_t base; + uint64_t base, pte; int level; vaddr address; + TLBRet ret; + MemTxResult ret1; address = context->addr; if ((address >> 63) & 0x1) { @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, } } +restart: /* pte */ + pte = base; if (level > 0) { /* Huge Page. base is pte */ base = FIELD_DP64(base, TLBENTRY, LEVEL, 0); @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, context->ps = dir_base; context->pte = base; - return loongarch_check_pte(env, context, access_type, mmu_idx); + ret = loongarch_check_pte(env, context, access_type, mmu_idx); + if (debug) { + return ret; + } + + /* + * Update bit A/D with hardware PTW supported + * + * Need atomic compchxg operation with pte update, other vCPUs may + * update pte at the same time. + */ + if (ret == TLBRET_MATCH && cpu_has_ptw(env)) { + if (access_type == MMU_DATA_STORE && pte_dirty(base)) { + return ret; + } + + if (access_type != MMU_DATA_STORE && pte_access(base)) { + return ret; + } + + base = pte_mkaccess(pte); + if (access_type == MMU_DATA_STORE) { + base = pte_mkdirty(base); + } + ret1 = loongarch_cmpxchg_phys(cs, phys, pte, base); + /* PTE updated by other CPU, reload PTE entry */ + if (ret1 == MEMTX_DECODE_ERROR) { + base = ldq_phys(cs->as, phys); + goto restart; + } + + base = context->pte_buddy[index]; + base = pte_mkaccess(base); + if (access_type == MMU_DATA_STORE) { + base = pte_mkdirty(base); + } + context->pte_buddy[index] = base; + + /* Bit A/D need be updated with both Even/Odd page with huge pte */ + if (level > 0) { + index = 1 - index; + base = context->pte_buddy[index]; + base = pte_mkaccess(base); + if (access_type == MMU_DATA_STORE) { + base = pte_mkdirty(base); + } + context->pte_buddy[index] = base; + } + } + + return ret; } static TLBRet loongarch_map_address(CPULoongArchState *env, -- 2.43.5
With read/write access, add bit A/D checking if hardware PTW is supported. If no matched, hardware page table walk is called. And then bit A/D is updated in PTE entry and TLB entry is updated also. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, context.addr = address; context.tlb_index = -1; ret = get_physical_address(env, &context, access_type, mmu_idx, 0); + if (ret == TLBRET_MATCH && context.mmu_index != MMU_DA_IDX + && cpu_has_ptw(env)) { + bool need_update = true; + + if (access_type == MMU_DATA_STORE && pte_dirty(context.pte)) { + need_update = false; + } else if (access_type != MMU_DATA_STORE && pte_access(context.pte)) { + need_update = false; + + /* + * FIXME: should context.prot be set without PAGE_WRITE with + * pte_write(context.pte) && !pte_dirty(context.pte)?? + * + * Otherwise there will be no loongarch_cpu_tlb_fill() function call + * for MMU_DATA_STORE access_type in future since QEMU TLB with + * prot PAGE_WRITE is added already + */ + } + + if (need_update) { + /* Need update bit A/D in PTE entry, take PTW again */ + ret = TLBRET_NOMATCH; + } + } + if (ret != TLBRET_MATCH && cpu_has_ptw(env)) { /* Take HW PTW if TLB missed or bit P is zero */ if (ret == TLBRET_NOMATCH || ret == TLBRET_INVALID) { -- 2.43.5
The following changes since commit cc329c491768b2d91eb0b0984f3baa0bf805776d: Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2026-06-08 09:30:30 -0400) are available in the Git repository at: https://github.com/gaosong715/qemu.git tags/pull-loongarch-20260609 for you to fetch changes up to b653a954d427561fc563238af6b2feb8da209e41: target/loongarch: Add new structure CPUSysState (2026-06-09 08:37:18 -0400) ---------------------------------------------------------------- pull-loongarch-20260609 ---------------------------------------------------------------- Bibo Mao (14): target/loongarch: Add new field curState in CPULoongArchState target/loongarch: Use sys_state in cpu.c when accessing CSR registers target/loongarch: Use sys_state in cpu_helper.c when accessing CSR registers target/loongarch: Use sys_state in file arch_dump.c when accessing CSR registers target/loongarch: Use sys_state in kvm.c when accessing CSR registers target/loongarch: Use sys_state in tlb_helper.c when accessing CSR registers target/loongarch: Use sys_state in tcg_cpu.c when accessing CSR registers target/loongarch: Use sys_state in csr_helper.c when accessing CSR registers target/loongarch: Use sys_state in op_helper.c when accessing CSR registers linux-user/loongarch64: Use sys_state when accessing CSR registers target/loongarch: Add default CSRFL_BASIC info with flags field target/loongarch: Add wrapper function get_csr_offset() target/loongarch: Add macro CSR_OFFSET and CPU_CSR_OFFSET target/loongarch: Add new structure CPUSysState hw/intc/loongarch_dintc.c | 4 +- linux-user/loongarch64/cpu_loop.c | 5 +- linux-user/loongarch64/elfload.c | 4 +- linux-user/loongarch64/signal.c | 16 +- target/loongarch/arch_dump.c | 5 +- target/loongarch/cpu-mmu.h | 4 +- target/loongarch/cpu.c | 120 ++++++----- target/loongarch/cpu.h | 49 +++-- target/loongarch/cpu_helper.c | 41 ++-- target/loongarch/csr.c | 10 +- target/loongarch/csr.h | 10 + target/loongarch/gdbstub.c | 3 +- target/loongarch/kvm/kvm.c | 228 +++++++++++---------- target/loongarch/machine.c | 118 +++++------ target/loongarch/tcg/constant_timer.c | 10 +- target/loongarch/tcg/csr_helper.c | 55 ++--- target/loongarch/tcg/insn_trans/trans_extra.c.inc | 6 +- .../tcg/insn_trans/trans_privileged.c.inc | 16 +- target/loongarch/tcg/op_helper.c | 45 ++-- target/loongarch/tcg/tcg_cpu.c | 107 +++++----- target/loongarch/tcg/tlb_helper.c | 137 +++++++------ 21 files changed, 549 insertions(+), 444 deletions(-)
From: Bibo Mao <maobibo@loongson.cn> New field sys_state is added in structure CPULoongArchState, it points to CPULoongArchState itself now. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-2-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu.c | 2 ++ target/loongarch/cpu.h | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj) uint32_t data = 0, field; int i; + set_sys_state(env, env); for (i = 0; i < 21; i++) { env->cpucfg[i] = 0x0; } @@ -XXX,XX +XXX,XX @@ static void loongarch_la132_initfn(Object *obj) uint32_t data = 0; int i; + set_sys_state(env, env); for (i = 0; i < 21; i++) { env->cpucfg[i] = 0x0; } diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct LoongArchBT { #define CPU_VENDOR_LOONGSON "Loongson" #define CPU_MODEL_3A5000 "3A5000" #define CPU_MODEL_1C101 "1C101" +struct CPUArchState; +typedef struct CPUArchState CPUSysState; typedef struct CPUArchState { uint64_t gpr[32]; @@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState { AddressSpace *address_space_iocsr; uint32_t mp_state; #endif + CPUSysState *sys_state; } CPULoongArchState; typedef struct LoongArchCPUTopo { @@ -XXX,XX +XXX,XX @@ struct LoongArchCPUClass { #define MMU_USER_IDX MMU_PLV_USER #define MMU_DA_IDX 4 +static inline CPUSysState *env_sys(CPULoongArchState *env) +{ + return env->sys_state; +} + +static inline void set_sys_state(CPULoongArchState *env, CPUSysState *sys) +{ + env->sys_state = sys; +} + static inline bool is_la64(CPULoongArchState *env) { return FIELD_EX32(env->cpucfg[1], CPUCFG1, ARCH) == CPUCFG1_ARCH_LA64; -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR register in file cpu.c, use sys_state rather than env. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-3-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu.c | 114 ++++++++++++++++++++++------------------- target/loongarch/cpu.h | 5 +- 2 files changed, 63 insertions(+), 56 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -XXX,XX +XXX,XX @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level) LoongArchCPU *cpu = opaque; CPULoongArchState *env = &cpu->env; CPUState *cs = CPU(cpu); + CPUSysState *sys = env_sys(env); if (irq < 0 || irq >= N_IRQS) { return; @@ -XXX,XX +XXX,XX @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level) if (kvm_enabled()) { kvm_loongarch_set_interrupt(cpu, irq, level); } else if (tcg_enabled()) { - env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0); - if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) { + sys->CSR_ESTAT = deposit64(sys->CSR_ESTAT, irq, 1, level != 0); + if (FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS)) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); @@ -XXX,XX +XXX,XX @@ bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env) { uint32_t pending; uint32_t status; + CPUSysState *sys = env_sys(env); - pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS); - status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE); + pending = FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS); + status = FIELD_EX64(sys->CSR_ECFG, CSR_ECFG, LIE); return (pending & status) != 0; } @@ -XXX,XX +XXX,XX @@ static void loongarch_la464_init_csr(DeviceState *dev) static bool initialized; LoongArchCPU *cpu = LOONGARCH_CPU(dev); CPULoongArchState *env = &cpu->env; + CPUSysState *sys = env_sys(env); int i, num; if (!initialized) { initialized = true; - num = FIELD_EX64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM); + num = FIELD_EX64(sys->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM); for (i = num; i < 16; i++) { set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED); } @@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); CPULoongArchState *env = &cpu->env; + CPUSysState *sys; uint32_t data = 0, field; int i; @@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj) data = FIELD_DP32(data, CPUCFG20, L3IU_SIZE, 6); env->cpucfg[20] = data; - env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa); + sys = env_sys(env); + sys->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa); - env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM, 8); - env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, TIMER_BITS, 0x2f); - env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, VSMAX, 7); + sys->CSR_PRCFG1 = FIELD_DP64(sys->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM, 8); + sys->CSR_PRCFG1 = FIELD_DP64(sys->CSR_PRCFG1, CSR_PRCFG1, TIMER_BITS, 0x2f); + sys->CSR_PRCFG1 = FIELD_DP64(sys->CSR_PRCFG1, CSR_PRCFG1, VSMAX, 7); - env->CSR_PRCFG2 = 0x3ffff000; + sys->CSR_PRCFG2 = 0x3ffff000; - env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2); - env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63); - env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7); - env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); + sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2); + sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63); + sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7); + sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); cpu->msgint = ON_OFF_AUTO_OFF; cpu->ptw = ON_OFF_AUTO_OFF; @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type) CPUState *cs = CPU(obj); LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj); CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); if (lacc->parent_phases.hold) { lacc->parent_phases.hold(obj, type); @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type) int n; /* Set csr registers value after reset, see the manual 6.4. */ - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATF, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 0); - - env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, FPE, 0); - env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, SXE, 0); - env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, ASXE, 0); - env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, BTE, 0); - - env->CSR_MISC = 0; - - env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, VS, 0); - env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, LIE, 0); - - env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2)); - env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0); - env->CSR_CPUID = cs->cpu_index; - env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0); - env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0); - env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0); - env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0); - env->CSR_TID = cs->cpu_index; + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PLV, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, IE, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PG, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DATF, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DATM, 0); + + sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, FPE, 0); + sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, SXE, 0); + sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, ASXE, 0); + sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, BTE, 0); + + sys->CSR_MISC = 0; + + sys->CSR_ECFG = FIELD_DP64(sys->CSR_ECFG, CSR_ECFG, VS, 0); + sys->CSR_ECFG = FIELD_DP64(sys->CSR_ECFG, CSR_ECFG, LIE, 0); + + sys->CSR_ESTAT = sys->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2)); + sys->CSR_RVACFG = FIELD_DP64(sys->CSR_RVACFG, CSR_RVACFG, RBITS, 0); + sys->CSR_CPUID = cs->cpu_index; + sys->CSR_TCFG = FIELD_DP64(sys->CSR_TCFG, CSR_TCFG, EN, 0); + sys->CSR_LLBCTL = FIELD_DP64(sys->CSR_LLBCTL, CSR_LLBCTL, KLO, 0); + sys->CSR_TLBRERA = FIELD_DP64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0); + sys->CSR_MERRCTL = FIELD_DP64(sys->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0); + sys->CSR_TID = cs->cpu_index; /* * Workaround for edk2-stable202408, CSR PGD register is set only if * its value is equal to zero for boot cpu, it causes reboot issue. * * Here clear CSR registers relative with TLB. */ - env->CSR_PGDH = 0; - env->CSR_PGDL = 0; - env->CSR_PWCH = 0; - env->CSR_EENTRY = 0; - env->CSR_TLBRENTRY = 0; - env->CSR_MERRENTRY = 0; + sys->CSR_PGDH = 0; + sys->CSR_PGDL = 0; + sys->CSR_PWCH = 0; + sys->CSR_EENTRY = 0; + sys->CSR_TLBRENTRY = 0; + sys->CSR_MERRENTRY = 0; /* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */ - if (env->CSR_PRCFG2 == 0) { - env->CSR_PRCFG2 = 0x3fffff000; + if (sys->CSR_PRCFG2 == 0) { + sys->CSR_PRCFG2 = 0x3fffff000; } - tlb_ps = ctz32(env->CSR_PRCFG2); - env->CSR_STLBPS = FIELD_DP64(env->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps); - env->CSR_PWCL = FIELD_DP64(env->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps); + tlb_ps = ctz32(sys->CSR_PRCFG2); + sys->CSR_STLBPS = FIELD_DP64(sys->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps); + sys->CSR_PWCL = FIELD_DP64(sys->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps); for (n = 0; n < 4; n++) { - env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV0, 0); - env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV1, 0); - env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV2, 0); - env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV3, 0); + sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV0, 0); + sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV1, 0); + sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV2, 0); + sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV3, 0); } #ifndef CONFIG_USER_ONLY diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -XXX,XX +XXX,XX @@ static inline bool is_va32(CPULoongArchState *env) { /* VA32 if !LA64 or VA32L[1-3] */ bool va32 = !is_la64(env); - uint64_t plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); - if (plv >= 1 && (FIELD_EX64(env->CSR_MISC, CSR_MISC, VA32) & (1 << plv))) { + CPUSysState *sys = env_sys(env); + uint64_t plv = FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV); + if (plv >= 1 && (FIELD_EX64(sys->CSR_MISC, CSR_MISC, VA32) & (1 << plv))) { va32 = true; } return va32; -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR register in file cpu_helper.c, use sys_state rather than env. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-4-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu_helper.c | 41 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -XXX,XX +XXX,XX @@ void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, uint64_t *dir_width, unsigned int level) { + CPUSysState *sys = env_sys(env); + switch (level) { case 1: - *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE); - *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); + *dir_base = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, DIR1_BASE); + *dir_width = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, DIR1_WIDTH); break; case 2: - *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE); - *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH); + *dir_base = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, DIR2_BASE); + *dir_width = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, DIR2_WIDTH); break; case 3: - *dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE); - *dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); + *dir_base = FIELD_EX64(sys->CSR_PWCH, CSR_PWCH, DIR3_BASE); + *dir_width = FIELD_EX64(sys->CSR_PWCH, CSR_PWCH, DIR3_WIDTH); break; case 4: - *dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE); - *dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH); + *dir_base = FIELD_EX64(sys->CSR_PWCH, CSR_PWCH, DIR4_BASE); + *dir_width = FIELD_EX64(sys->CSR_PWCH, CSR_PWCH, DIR4_WIDTH); break; default: /* level may be zero for ldpte */ - *dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); - *dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + *dir_base = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, PTBASE); + *dir_width = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, PTWIDTH); break; } } @@ -XXX,XX +XXX,XX @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context, vaddr address; TLBRet ret; MemTxResult ret1; - + CPUSysState *sys = env_sys(env); address = context->addr; if ((address >> 63) & 0x1) { - base = env->CSR_PGDH; + base = sys->CSR_PGDH; } else { - base = env->CSR_PGDL; + base = sys->CSR_PGDL; } base &= palen_mask; @@ -XXX,XX +XXX,XX @@ TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context, int kernel_mode = mmu_idx == MMU_KERNEL_IDX; uint32_t plv, base_c, base_v; int64_t addr_high; - uint8_t da = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, DA); - uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG); + CPUSysState *sys = env_sys(env); + uint8_t da = FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, DA); + uint8_t pg = FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PG); vaddr address; /* Check PG and DA */ @@ -XXX,XX +XXX,XX @@ TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context, /* Check direct map window */ for (int i = 0; i < 4; i++) { if (is_la64(env)) { - base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_64, VSEG); + base_c = FIELD_EX64(sys->CSR_DMW[i], CSR_DMW_64, VSEG); } else { - base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG); + base_c = FIELD_EX64(sys->CSR_DMW[i], CSR_DMW_32, VSEG); } - if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) { - context->physical = dmw_va2pa(env, address, env->CSR_DMW[i]); + if ((plv & sys->CSR_DMW[i]) && (base_c == base_v)) { + context->physical = dmw_va2pa(env, address, sys->CSR_DMW[i]); context->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; context->mmu_index = MMU_DA_IDX; return TLBRET_MATCH; -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in file arch_dump.c, use sys_state rather than env. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-5-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- hw/intc/loongarch_dintc.c | 4 +++- target/loongarch/arch_dump.c | 5 +++-- target/loongarch/cpu-mmu.h | 4 +++- target/loongarch/gdbstub.c | 3 ++- target/loongarch/tcg/constant_timer.c | 10 ++++++---- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/hw/intc/loongarch_dintc.c b/hw/intc/loongarch_dintc.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/loongarch_dintc.c +++ b/hw/intc/loongarch_dintc.c @@ -XXX,XX +XXX,XX @@ static void do_set_vcpu_dintc_irq(CPUState *cs, run_on_cpu_data data) { int irq = data.host_int; CPULoongArchState *env; + CPUSysState *sys; env = &LOONGARCH_CPU(cs)->env; + sys = env_sys(env); cpu_synchronize_state(cs); - set_bit(irq, (unsigned long *)&env->CSR_MSGIS); + set_bit(irq, (unsigned long *)&sys->CSR_MSGIS); } static void loongarch_dintc_mem_write(void *opaque, hwaddr addr, diff --git a/target/loongarch/arch_dump.c b/target/loongarch/arch_dump.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/arch_dump.c +++ b/target/loongarch/arch_dump.c @@ -XXX,XX +XXX,XX @@ int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, { struct loongarch_note note; CPULoongArchState *env = &LOONGARCH_CPU(cs)->env; + CPUSysState *sys = env_sys(env); int ret, i; loongarch_note_init(¬e, s, "CORE", 5, NT_PRSTATUS, @@ -XXX,XX +XXX,XX @@ int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, for (i = 0; i < 32; ++i) { note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->gpr[i]); } - note.prstatus.pr_reg.csr_era = cpu_to_dump64(s, env->CSR_ERA); - note.prstatus.pr_reg.csr_badv = cpu_to_dump64(s, env->CSR_BADV); + note.prstatus.pr_reg.csr_era = cpu_to_dump64(s, sys->CSR_ERA); + note.prstatus.pr_reg.csr_badv = cpu_to_dump64(s, sys->CSR_BADV); ret = f(¬e, LOONGARCH_PRSTATUS_NOTE_SIZE, s); if (ret < 0) { return -1; diff --git a/target/loongarch/cpu-mmu.h b/target/loongarch/cpu-mmu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu-mmu.h +++ b/target/loongarch/cpu-mmu.h @@ -XXX,XX +XXX,XX @@ typedef struct MMUContext { static inline bool cpu_has_ptw(CPULoongArchState *env) { - return !!FIELD_EX64(env->CSR_PWCH, CSR_PWCH, HPTW_EN); + CPUSysState *sys = env_sys(env); + + return !!FIELD_EX64(sys->CSR_PWCH, CSR_PWCH, HPTW_EN); } static inline bool pte_present(CPULoongArchState *env, uint64_t entry) diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/gdbstub.c +++ b/target/loongarch/gdbstub.c @@ -XXX,XX +XXX,XX @@ void write_fcc(CPULoongArchState *env, uint64_t val) int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); if (0 <= n && n <= 34) { uint64_t val; @@ -XXX,XX +XXX,XX @@ int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) } else if (n == 33) { val = env->pc; } else /* if (n == 34) */ { - val = env->CSR_BADV; + val = sys->CSR_BADV; } if (is_la64(env)) { diff --git a/target/loongarch/tcg/constant_timer.c b/target/loongarch/tcg/constant_timer.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/constant_timer.c +++ b/target/loongarch/tcg/constant_timer.c @@ -XXX,XX +XXX,XX @@ void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu, uint64_t value) { CPULoongArchState *env = &cpu->env; + CPUSysState *sys = env_sys(env); uint64_t now, next; - env->CSR_TCFG = value; + sys->CSR_TCFG = value; if (value & CONSTANT_TIMER_ENABLE) { now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD; @@ -XXX,XX +XXX,XX @@ void loongarch_constant_timer_cb(void *opaque) { LoongArchCPU *cpu = opaque; CPULoongArchState *env = &cpu->env; + CPUSysState *sys = env_sys(env); uint64_t now, next; - if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) { + if (FIELD_EX64(sys->CSR_TCFG, CSR_TCFG, PERIODIC)) { now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - next = now + (env->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD; + next = now + (sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD; timer_mod(&cpu->timer, next); } else { - env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0); + sys->CSR_TCFG = FIELD_DP64(sys->CSR_TCFG, CSR_TCFG, EN, 0); } loongarch_cpu_set_irq(opaque, IRQ_TIMER, 1); -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in file kvm.c, use sys_state rather than env. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-6-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/kvm/kvm.c | 228 +++++++++++++++++++------------------ 1 file changed, 116 insertions(+), 112 deletions(-) diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/kvm/kvm.c +++ b/target/loongarch/kvm/kvm.c @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_put_pmu(CPUState *cs) int i, ret = 0; CPULoongArchState *env = cpu_env(cs); LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPUSysState *sys = env_sys(env); if (cpu->pmu != ON_OFF_AUTO_ON) { return 0; @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_put_pmu(CPUState *cs) for (i = 0; i < env->perf_event_num; i++) { ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL(i)), - &env->CSR_PERFCTRL[i]); + &sys->CSR_PERFCTRL[i]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR(i)), - &env->CSR_PERFCNTR[i]); + &sys->CSR_PERFCNTR[i]); } return ret; @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_get_pmu(CPUState *cs) int i, ret = 0; CPULoongArchState *env = cpu_env(cs); LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPUSysState *sys = env_sys(env); if (cpu->pmu != ON_OFF_AUTO_ON) { return 0; @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_get_pmu(CPUState *cs) for (i = 0; i < env->perf_event_num; i++) { ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL(i)), - &env->CSR_PERFCTRL[i]); + &sys->CSR_PERFCTRL[i]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR(i)), - &env->CSR_PERFCNTR[i]); + &sys->CSR_PERFCNTR[i]); } return ret; @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_get_csr(CPUState *cs) { int ret = 0; CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD), - &env->CSR_CRMD); + &sys->CSR_CRMD); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD), - &env->CSR_PRMD); + &sys->CSR_PRMD); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN), - &env->CSR_EUEN); + &sys->CSR_EUEN); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC), - &env->CSR_MISC); + &sys->CSR_MISC); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG), - &env->CSR_ECFG); + &sys->CSR_ECFG); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT), - &env->CSR_ESTAT); + &sys->CSR_ESTAT); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA), - &env->CSR_ERA); + &sys->CSR_ERA); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV), - &env->CSR_BADV); + &sys->CSR_BADV); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI), - &env->CSR_BADI); + &sys->CSR_BADI); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY), - &env->CSR_EENTRY); + &sys->CSR_EENTRY); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX), - &env->CSR_TLBIDX); + &sys->CSR_TLBIDX); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI), - &env->CSR_TLBEHI); + &sys->CSR_TLBEHI); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0), - &env->CSR_TLBELO0); + &sys->CSR_TLBELO0); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1), - &env->CSR_TLBELO1); + &sys->CSR_TLBELO1); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID), - &env->CSR_ASID); + &sys->CSR_ASID); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL), - &env->CSR_PGDL); + &sys->CSR_PGDL); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH), - &env->CSR_PGDH); + &sys->CSR_PGDH); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD), - &env->CSR_PGD); + &sys->CSR_PGD); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL), - &env->CSR_PWCL); + &sys->CSR_PWCL); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH), - &env->CSR_PWCH); + &sys->CSR_PWCH); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS), - &env->CSR_STLBPS); + &sys->CSR_STLBPS); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG), - &env->CSR_RVACFG); + &sys->CSR_RVACFG); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID), - &env->CSR_CPUID); + &sys->CSR_CPUID); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1), - &env->CSR_PRCFG1); + &sys->CSR_PRCFG1); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2), - &env->CSR_PRCFG2); + &sys->CSR_PRCFG2); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3), - &env->CSR_PRCFG3); + &sys->CSR_PRCFG3); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)), - &env->CSR_SAVE[0]); + &sys->CSR_SAVE[0]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)), - &env->CSR_SAVE[1]); + &sys->CSR_SAVE[1]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)), - &env->CSR_SAVE[2]); + &sys->CSR_SAVE[2]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)), - &env->CSR_SAVE[3]); + &sys->CSR_SAVE[3]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)), - &env->CSR_SAVE[4]); + &sys->CSR_SAVE[4]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)), - &env->CSR_SAVE[5]); + &sys->CSR_SAVE[5]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)), - &env->CSR_SAVE[6]); + &sys->CSR_SAVE[6]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)), - &env->CSR_SAVE[7]); + &sys->CSR_SAVE[7]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID), - &env->CSR_TID); + &sys->CSR_TID); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC), - &env->CSR_CNTC); + &sys->CSR_CNTC); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR), - &env->CSR_TICLR); + &sys->CSR_TICLR); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL), - &env->CSR_LLBCTL); + &sys->CSR_LLBCTL); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1), - &env->CSR_IMPCTL1); + &sys->CSR_IMPCTL1); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2), - &env->CSR_IMPCTL2); + &sys->CSR_IMPCTL2); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY), - &env->CSR_TLBRENTRY); + &sys->CSR_TLBRENTRY); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV), - &env->CSR_TLBRBADV); + &sys->CSR_TLBRBADV); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA), - &env->CSR_TLBRERA); + &sys->CSR_TLBRERA); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE), - &env->CSR_TLBRSAVE); + &sys->CSR_TLBRSAVE); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0), - &env->CSR_TLBRELO0); + &sys->CSR_TLBRELO0); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1), - &env->CSR_TLBRELO1); + &sys->CSR_TLBRELO1); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI), - &env->CSR_TLBREHI); + &sys->CSR_TLBREHI); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD), - &env->CSR_TLBRPRMD); + &sys->CSR_TLBRPRMD); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)), - &env->CSR_DMW[0]); + &sys->CSR_DMW[0]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)), - &env->CSR_DMW[1]); + &sys->CSR_DMW[1]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)), - &env->CSR_DMW[2]); + &sys->CSR_DMW[2]); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)), - &env->CSR_DMW[3]); + &sys->CSR_DMW[3]); ret |= kvm_loongarch_get_pmu(cs); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL), - &env->CSR_TVAL); + &sys->CSR_TVAL); ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG), - &env->CSR_TCFG); + &sys->CSR_TCFG); return ret; } @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level) { int ret = 0; CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD), - &env->CSR_CRMD); + &sys->CSR_CRMD); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD), - &env->CSR_PRMD); + &sys->CSR_PRMD); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN), - &env->CSR_EUEN); + &sys->CSR_EUEN); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC), - &env->CSR_MISC); + &sys->CSR_MISC); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG), - &env->CSR_ECFG); + &sys->CSR_ECFG); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT), - &env->CSR_ESTAT); + &sys->CSR_ESTAT); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA), - &env->CSR_ERA); + &sys->CSR_ERA); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV), - &env->CSR_BADV); + &sys->CSR_BADV); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI), - &env->CSR_BADI); + &sys->CSR_BADI); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY), - &env->CSR_EENTRY); + &sys->CSR_EENTRY); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX), - &env->CSR_TLBIDX); + &sys->CSR_TLBIDX); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI), - &env->CSR_TLBEHI); + &sys->CSR_TLBEHI); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0), - &env->CSR_TLBELO0); + &sys->CSR_TLBELO0); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1), - &env->CSR_TLBELO1); + &sys->CSR_TLBELO1); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID), - &env->CSR_ASID); + &sys->CSR_ASID); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL), - &env->CSR_PGDL); + &sys->CSR_PGDL); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH), - &env->CSR_PGDH); + &sys->CSR_PGDH); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD), - &env->CSR_PGD); + &sys->CSR_PGD); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL), - &env->CSR_PWCL); + &sys->CSR_PWCL); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH), - &env->CSR_PWCH); + &sys->CSR_PWCH); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS), - &env->CSR_STLBPS); + &sys->CSR_STLBPS); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG), - &env->CSR_RVACFG); + &sys->CSR_RVACFG); /* CPUID is constant after poweron, it should be set only once */ if (level >= KVM_PUT_FULL_STATE) { ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID), - &env->CSR_CPUID); + &sys->CSR_CPUID); } ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1), - &env->CSR_PRCFG1); + &sys->CSR_PRCFG1); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2), - &env->CSR_PRCFG2); + &sys->CSR_PRCFG2); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3), - &env->CSR_PRCFG3); + &sys->CSR_PRCFG3); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)), - &env->CSR_SAVE[0]); + &sys->CSR_SAVE[0]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)), - &env->CSR_SAVE[1]); + &sys->CSR_SAVE[1]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)), - &env->CSR_SAVE[2]); + &sys->CSR_SAVE[2]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)), - &env->CSR_SAVE[3]); + &sys->CSR_SAVE[3]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)), - &env->CSR_SAVE[4]); + &sys->CSR_SAVE[4]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)), - &env->CSR_SAVE[5]); + &sys->CSR_SAVE[5]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)), - &env->CSR_SAVE[6]); + &sys->CSR_SAVE[6]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)), - &env->CSR_SAVE[7]); + &sys->CSR_SAVE[7]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID), - &env->CSR_TID); + &sys->CSR_TID); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC), - &env->CSR_CNTC); + &sys->CSR_CNTC); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR), - &env->CSR_TICLR); + &sys->CSR_TICLR); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL), - &env->CSR_LLBCTL); + &sys->CSR_LLBCTL); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1), - &env->CSR_IMPCTL1); + &sys->CSR_IMPCTL1); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2), - &env->CSR_IMPCTL2); + &sys->CSR_IMPCTL2); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY), - &env->CSR_TLBRENTRY); + &sys->CSR_TLBRENTRY); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV), - &env->CSR_TLBRBADV); + &sys->CSR_TLBRBADV); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA), - &env->CSR_TLBRERA); + &sys->CSR_TLBRERA); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE), - &env->CSR_TLBRSAVE); + &sys->CSR_TLBRSAVE); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0), - &env->CSR_TLBRELO0); + &sys->CSR_TLBRELO0); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1), - &env->CSR_TLBRELO1); + &sys->CSR_TLBRELO1); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI), - &env->CSR_TLBREHI); + &sys->CSR_TLBREHI); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD), - &env->CSR_TLBRPRMD); + &sys->CSR_TLBRPRMD); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)), - &env->CSR_DMW[0]); + &sys->CSR_DMW[0]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)), - &env->CSR_DMW[1]); + &sys->CSR_DMW[1]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)), - &env->CSR_DMW[2]); + &sys->CSR_DMW[2]); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)), - &env->CSR_DMW[3]); + &sys->CSR_DMW[3]); ret |= kvm_loongarch_put_pmu(cs); @@ -XXX,XX +XXX,XX @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level) * guest timer */ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL), - &env->CSR_TVAL); + &sys->CSR_TVAL); ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG), - &env->CSR_TCFG); + &sys->CSR_TCFG); return ret; } -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in file tlb_helper.c, use sys_state rather than env. There is no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-7-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 137 +++++++++++++++++------------- 1 file changed, 77 insertions(+), 60 deletions(-) diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -XXX,XX +XXX,XX @@ static bool tlb_match_asid(bool global, int asid, int tlb_asid) bool check_ps(CPULoongArchState *env, uint8_t tlb_ps) { + CPUSysState *sys = env_sys(env); + if (tlb_ps >= 64) { return false; } - return BIT_ULL(tlb_ps) & (env->CSR_PRCFG2); + return BIT_ULL(tlb_ps) & (sys->CSR_PRCFG2); } static void raise_mmu_exception(CPULoongArchState *env, vaddr address, MMUAccessType access_type, TLBRet tlb_error) { CPUState *cs = env_cpu(env); + CPUSysState *sys = env_sys(env); switch (tlb_error) { default: @@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPULoongArchState *env, vaddr address, } else if (access_type == MMU_INST_FETCH) { cs->exception_index = EXCCODE_PIF; } - env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 1); + sys->CSR_TLBRERA = FIELD_DP64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 1); break; case TLBRET_INVALID: /* TLB match with no valid bit */ @@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPULoongArchState *env, vaddr address, } if (tlb_error == TLBRET_NOMATCH) { - env->CSR_TLBRBADV = address; + sys->CSR_TLBRBADV = address; if (is_la64(env)) { - env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI_64, + sys->CSR_TLBREHI = FIELD_DP64(sys->CSR_TLBREHI, CSR_TLBREHI_64, VPPN, extract64(address, 13, 35)); } else { - env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI_32, + sys->CSR_TLBREHI = FIELD_DP64(sys->CSR_TLBREHI, CSR_TLBREHI_32, VPPN, extract64(address, 13, 19)); } } else { - if (!FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) { - env->CSR_BADV = address; + if (!FIELD_EX64(sys->CSR_DBG, CSR_DBG, DST)) { + sys->CSR_BADV = address; } - env->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1); + sys->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1); } } @@ -XXX,XX +XXX,XX @@ static void invalidate_tlb(CPULoongArchState *env, int index) LoongArchTLB *tlb; uint16_t csr_asid, tlb_asid, tlb_g; uint8_t tlb_e; + CPUSysState *sys = env_sys(env); - csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + csr_asid = FIELD_EX64(sys->CSR_ASID, CSR_ASID, ASID); tlb = &env->tlb[index]; tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); if (!tlb_e) { @@ -XXX,XX +XXX,XX @@ static void sptw_prepare_context(CPULoongArchState *env, MMUContext *context) { uint64_t lo0, lo1, csr_vppn; uint8_t csr_ps; + CPUSysState *sys = env_sys(env); - if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { - csr_ps = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, PS); + if (FIELD_EX64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { + csr_ps = FIELD_EX64(sys->CSR_TLBREHI, CSR_TLBREHI, PS); if (is_la64(env)) { - csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI_64, VPPN); + csr_vppn = FIELD_EX64(sys->CSR_TLBREHI, CSR_TLBREHI_64, VPPN); } else { - csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI_32, VPPN); + csr_vppn = FIELD_EX64(sys->CSR_TLBREHI, CSR_TLBREHI_32, VPPN); } - lo0 = env->CSR_TLBRELO0; - lo1 = env->CSR_TLBRELO1; + lo0 = sys->CSR_TLBRELO0; + lo1 = sys->CSR_TLBRELO1; } else { - csr_ps = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); + csr_ps = FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, PS); if (is_la64(env)) { - csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI_64, VPPN); + csr_vppn = FIELD_EX64(sys->CSR_TLBEHI, CSR_TLBEHI_64, VPPN); } else { - csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI_32, VPPN); + csr_vppn = FIELD_EX64(sys->CSR_TLBEHI, CSR_TLBEHI_32, VPPN); } - lo0 = env->CSR_TLBELO0; - lo1 = env->CSR_TLBELO1; + lo0 = sys->CSR_TLBELO0; + lo1 = sys->CSR_TLBELO1; } context->ps = csr_ps; @@ -XXX,XX +XXX,XX @@ static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb, uint64_t lo0, lo1, csr_vppn; uint16_t csr_asid; uint8_t csr_ps; + CPUSysState *sys = env_sys(env); csr_vppn = context->addr >> R_TLB_MISC_VPPN_SHIFT; csr_ps = context->ps; @@ -XXX,XX +XXX,XX @@ static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb, 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); tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 1); - csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + csr_asid = FIELD_EX64(sys->CSR_ASID, CSR_ASID, ASID); tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, ASID, csr_asid); tlb->tlb_entry0 = lo0; @@ -XXX,XX +XXX,XX @@ static LoongArchTLB *loongarch_tlb_search_cb(CPULoongArchState *env, bool tlb_g; int i, compare_shift; uint64_t vpn, tlb_vppn; + CPUSysState *sys = env_sys(env); - stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); + stlb_ps = FIELD_EX64(sys->CSR_STLBPS, CSR_STLBPS, PS); vpn = (vaddr & TARGET_VIRT_MASK) >> (stlb_ps + 1); stlb_idx = vpn & 0xff; /* VA[25:15] <==> TLBIDX.index for 16KiB Page */ compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT; @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, int csr_asid; tlb_match func; LoongArchTLB *tlb; + CPUSysState *sys = env_sys(env); func = tlb_match_any; - csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + csr_asid = FIELD_EX64(sys->CSR_ASID, CSR_ASID, ASID); tlb = loongarch_tlb_search_cb(env, vaddr, csr_asid, func); if (tlb) { *index = tlb - env->tlb; @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, void helper_tlbsrch(CPULoongArchState *env) { int index, match; + CPUSysState *sys = env_sys(env); - if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { - match = loongarch_tlb_search(env, env->CSR_TLBREHI, &index); + if (FIELD_EX64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { + match = loongarch_tlb_search(env, sys->CSR_TLBREHI, &index); } else { - match = loongarch_tlb_search(env, env->CSR_TLBEHI, &index); + match = loongarch_tlb_search(env, sys->CSR_TLBEHI, &index); } if (match) { - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX, index); - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 0); + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, INDEX, index); + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, NE, 0); return; } - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 1); + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, NE, 1); } void helper_tlbrd(CPULoongArchState *env) @@ -XXX,XX +XXX,XX @@ void helper_tlbrd(CPULoongArchState *env) LoongArchTLB *tlb; int index; uint8_t tlb_ps, tlb_e; + CPUSysState *sys = env_sys(env); - index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + index = FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, INDEX); tlb = &env->tlb[index]; tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); if (!tlb_e) { /* Invalid TLB entry */ - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 1); - env->CSR_ASID = FIELD_DP64(env->CSR_ASID, CSR_ASID, ASID, 0); - env->CSR_TLBEHI = 0; - env->CSR_TLBELO0 = 0; - env->CSR_TLBELO1 = 0; - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, PS, 0); + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, NE, 1); + sys->CSR_ASID = FIELD_DP64(sys->CSR_ASID, CSR_ASID, ASID, 0); + sys->CSR_TLBEHI = 0; + sys->CSR_TLBELO0 = 0; + sys->CSR_TLBELO1 = 0; + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, PS, 0); } else { /* Valid TLB entry */ - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 0); - env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, NE, 0); + sys->CSR_TLBIDX = FIELD_DP64(sys->CSR_TLBIDX, CSR_TLBIDX, PS, (tlb_ps & 0x3f)); - env->CSR_TLBEHI = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN) << + sys->CSR_TLBEHI = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN) << R_TLB_MISC_VPPN_SHIFT; - env->CSR_TLBELO0 = tlb->tlb_entry0; - env->CSR_TLBELO1 = tlb->tlb_entry1; + sys->CSR_TLBELO0 = tlb->tlb_entry0; + sys->CSR_TLBELO1 = tlb->tlb_entry1; } } @@ -XXX,XX +XXX,XX @@ static void update_tlb_index(CPULoongArchState *env, MMUContext *context, void helper_tlbwr(CPULoongArchState *env) { - int index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + CPUSysState *sys = env_sys(env); + int index = FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, INDEX); MMUContext context; - if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { + if (FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, NE)) { invalidate_tlb(env, index); return; } @@ -XXX,XX +XXX,XX @@ static int get_tlb_random_index(CPULoongArchState *env, vaddr addr, uint16_t asid, tlb_asid, stlb_ps; LoongArchTLB *tlb; uint8_t tlb_e, tlb_g; + CPUSysState *sys = env_sys(env); /* Validity of stlb_ps is checked in helper_csrwr_stlbps() */ - stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); - asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + stlb_ps = FIELD_EX64(sys->CSR_STLBPS, CSR_STLBPS, PS); + asid = FIELD_EX64(sys->CSR_ASID, CSR_ASID, ASID); if (pagesize == stlb_ps) { /* Only write into STLB bits [47:13] */ address = addr & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_64_VPPN_SHIFT); @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *env) vaddr entryhi; int index, pagesize; MMUContext context; + CPUSysState *sys = env_sys(env); - if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { - entryhi = env->CSR_TLBREHI; + if (FIELD_EX64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { + entryhi = sys->CSR_TLBREHI; /* Validity of pagesize is checked in helper_ldpte() */ - pagesize = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, PS); + pagesize = FIELD_EX64(sys->CSR_TLBREHI, CSR_TLBREHI, PS); } else { - entryhi = env->CSR_TLBEHI; + entryhi = sys->CSR_TLBEHI; /* Validity of pagesize is checked in helper_tlbrd() */ - pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS); + pagesize = FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, PS); } sptw_prepare_context(env, &context); @@ -XXX,XX +XXX,XX @@ void helper_tlbclr(CPULoongArchState *env) LoongArchTLB *tlb; int i, index; uint16_t csr_asid, tlb_asid, tlb_g; + CPUSysState *sys = env_sys(env); - csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); - index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + csr_asid = FIELD_EX64(sys->CSR_ASID, CSR_ASID, ASID); + index = FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, INDEX); if (index < LOONGARCH_STLB) { /* STLB. One line per operation */ @@ -XXX,XX +XXX,XX @@ void helper_tlbclr(CPULoongArchState *env) void helper_tlbflush(CPULoongArchState *env) { int i, index; + CPUSysState *sys = env_sys(env); - index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + index = FIELD_EX64(sys->CSR_TLBIDX, CSR_TLBIDX, INDEX); if (index < LOONGARCH_STLB) { /* STLB. One line per operation */ @@ -XXX,XX +XXX,XX @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, uint64_t palen_mask = loongarch_palen_mask(env); uint64_t dir_base, dir_width; uint64_t val; + CPUSysState *sys = env_sys(env); if (unlikely((level == 0) || (level > 4))) { qemu_log_mask(LOG_GUEST_ERROR, @@ -XXX,XX +XXX,XX @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base, } } - badvaddr = env->CSR_TLBRBADV; + badvaddr = sys->CSR_TLBRBADV; base = base & palen_mask; get_dir_base_width(env, &dir_base, &dir_width, level); index = (badvaddr >> dir_base) & ((1 << dir_width) - 1); @@ -XXX,XX +XXX,XX @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd, { CPUState *cs = env_cpu(env); hwaddr phys, tmp0, ptindex, ptoffset0, ptoffset1; + CPUSysState *sys = env_sys(env); uint64_t pte_raw; uint64_t badv; - uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE); - uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH); + uint64_t ptbase = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, PTBASE); + uint64_t ptwidth = FIELD_EX64(sys->CSR_PWCL, CSR_PWCL, PTWIDTH); uint64_t palen_mask = loongarch_palen_mask(env); uint64_t dir_base, dir_width; uint8_t ps; @@ -XXX,XX +XXX,XX @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd, return; } } else { - badv = env->CSR_TLBRBADV; + badv = sys->CSR_TLBRBADV; base = base & palen_mask; @@ -XXX,XX +XXX,XX @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd, } if (odd) { - env->CSR_TLBRELO1 = tmp0; + sys->CSR_TLBRELO1 = tmp0; } else { - env->CSR_TLBRELO0 = tmp0; + sys->CSR_TLBRELO0 = tmp0; } - env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI, PS, ps); + sys->CSR_TLBREHI = FIELD_DP64(sys->CSR_TLBREHI, CSR_TLBREHI, PS, ps); } static TLBRet loongarch_map_tlb_entry(CPULoongArchState *env, -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in file tcg_cpu.c, use sys_state rather than env. There is no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-8-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tcg_cpu.c | 107 +++++++++++++++++---------------- 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/target/loongarch/tcg/tcg_cpu.c b/target/loongarch/tcg/tcg_cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/tcg_cpu.c +++ b/target/loongarch/tcg/tcg_cpu.c @@ -XXX,XX +XXX,XX @@ void G_NORETURN do_raise_exception(CPULoongArchState *env, static void loongarch_cpu_do_interrupt(CPUState *cs) { CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); bool update_badinstr = 1; int cause = -1; - bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR); - uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS); + bool tlbfill = FIELD_EX64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR); + uint32_t vec_size = FIELD_EX64(sys->CSR_ECFG, CSR_ECFG, VS); uint64_t last_pc = env->pc; if (cs->exception_index != EXCCODE_INT) { qemu_log_mask(CPU_LOG_INT, "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx " TLBRERA " TARGET_FMT_lx " exception: %d (%s)\n", - __func__, env->pc, env->CSR_ERA, env->CSR_TLBRERA, + __func__, env->pc, sys->CSR_ERA, sys->CSR_TLBRERA, cs->exception_index, loongarch_exception_name(cs->exception_index)); } switch (cs->exception_index) { case EXCCODE_DBP: - env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1); - env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC); + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DCL, 1); + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, ECODE, 0xC); goto set_DERA; set_DERA: - env->CSR_DERA = env->pc; - env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1); - set_pc(env, env->CSR_EENTRY + 0x480); + sys->CSR_DERA = env->pc; + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DST, 1); + set_pc(env, sys->CSR_EENTRY + 0x480); break; case EXCCODE_INT: - if (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) { - env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DEI, 1); + if (FIELD_EX64(sys->CSR_DBG, CSR_DBG, DST)) { + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DEI, 1); goto set_DERA; } QEMU_FALLTHROUGH; @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_do_interrupt(CPUState *cs) update_badinstr = 0; break; case EXCCODE_BCE: - env->CSR_BADV = env->pc; + sys->CSR_BADV = env->pc; QEMU_FALLTHROUGH; case EXCCODE_SYS: case EXCCODE_BRK: @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_do_interrupt(CPUState *cs) if (update_badinstr) { MemOpIdx oi = make_memop_idx(MO_LEUL, cpu_mmu_index(cs, true)); - env->CSR_BADI = cpu_ldl_code_mmu(env, env->pc, oi, 0); + sys->CSR_BADI = cpu_ldl_code_mmu(env, env->pc, oi, 0); } /* Save PLV and IE */ if (tlbfill) { - env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV, - FIELD_EX64(env->CSR_CRMD, + sys->CSR_TLBRPRMD = FIELD_DP64(sys->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV, + FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV)); - env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE, - FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE)); + sys->CSR_TLBRPRMD = FIELD_DP64(sys->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE, + FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, IE)); /* set the DA mode */ - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0); - env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PG, 0); + sys->CSR_TLBRERA = FIELD_DP64(sys->CSR_TLBRERA, CSR_TLBRERA, PC, (env->pc >> 2)); } else { - env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, + sys->CSR_ESTAT = FIELD_DP64(sys->CSR_ESTAT, CSR_ESTAT, ECODE, EXCODE_MCODE(cause)); - env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ESUBCODE, + sys->CSR_ESTAT = FIELD_DP64(sys->CSR_ESTAT, CSR_ESTAT, ESUBCODE, EXCODE_SUBCODE(cause)); - env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV, - FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV)); - env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PIE, - FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE)); - env->CSR_ERA = env->pc; + sys->CSR_PRMD = FIELD_DP64(sys->CSR_PRMD, CSR_PRMD, PPLV, + FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV)); + sys->CSR_PRMD = FIELD_DP64(sys->CSR_PRMD, CSR_PRMD, PIE, + FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, IE)); + sys->CSR_ERA = env->pc; } - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PLV, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, IE, 0); if (vec_size) { vec_size = (1 << vec_size) * 4; @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_do_interrupt(CPUState *cs) if (cs->exception_index == EXCCODE_INT) { /* Interrupt */ uint32_t vector = 0; - uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS); - pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE); + uint32_t pending = FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS); + pending &= FIELD_EX64(sys->CSR_ECFG, CSR_ECFG, LIE); /* Find the highest-priority interrupt. */ vector = 31 - clz32(pending); - set_pc(env, env->CSR_EENTRY + \ + set_pc(env, sys->CSR_EENTRY + \ (EXCCODE_EXTERNAL_INT + vector) * vec_size); qemu_log_mask(CPU_LOG_INT, "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx " cause %d\n" " A " TARGET_FMT_lx " D " TARGET_FMT_lx " vector = %d ExC " TARGET_FMT_lx "ExS" TARGET_FMT_lx "\n", - __func__, env->pc, env->CSR_ERA, - cause, env->CSR_BADV, env->CSR_DERA, vector, - env->CSR_ECFG, env->CSR_ESTAT); + __func__, env->pc, sys->CSR_ERA, + cause, sys->CSR_BADV, sys->CSR_DERA, vector, + sys->CSR_ECFG, sys->CSR_ESTAT); qemu_plugin_vcpu_interrupt_cb(cs, last_pc); } else { if (tlbfill) { - set_pc(env, env->CSR_TLBRENTRY); + set_pc(env, sys->CSR_TLBRENTRY); } else { - set_pc(env, env->CSR_EENTRY + EXCODE_MCODE(cause) * vec_size); + set_pc(env, sys->CSR_EENTRY + EXCODE_MCODE(cause) * vec_size); } qemu_log_mask(CPU_LOG_INT, "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_do_interrupt(CPUState *cs) " EXCFG " TARGET_FMT_lx " BADVA " TARGET_FMT_lx "BADI " TARGET_FMT_lx " SYS_NUM " TARGET_FMT_lu " cpu %d asid " TARGET_FMT_lx "\n", __func__, env->pc, - tlbfill ? env->CSR_TLBRERA : env->CSR_ERA, - cause, tlbfill ? "(refill)" : "", env->CSR_ESTAT, - env->CSR_ECFG, - tlbfill ? env->CSR_TLBRBADV : env->CSR_BADV, - env->CSR_BADI, env->gpr[11], cs->cpu_index, - env->CSR_ASID); + tlbfill ? sys->CSR_TLBRERA : sys->CSR_ERA, + cause, tlbfill ? "(refill)" : "", sys->CSR_ESTAT, + sys->CSR_ECFG, + tlbfill ? sys->CSR_TLBRBADV : sys->CSR_BADV, + sys->CSR_BADI, env->gpr[11], cs->cpu_index, + sys->CSR_ASID); qemu_plugin_vcpu_exception_cb(cs, last_pc); } cs->exception_index = -1; @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, uintptr_t retaddr) { CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); - env->CSR_BADV = addr; + sys->CSR_BADV = addr; if (access_type == MMU_INST_FETCH) { do_raise_exception(env, EXCCODE_ADEF, retaddr); } else { @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env) { bool ret = 0; + CPUSysState *sys = env_sys(env); - ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) && - !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST))); + ret = (FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, IE) && + !(FIELD_EX64(sys->CSR_DBG, CSR_DBG, DST))); return ret; } @@ -XXX,XX +XXX,XX @@ static vaddr loongarch_pointer_wrap(CPUState *cs, int mmu_idx, static TCGTBCPUState loongarch_get_tb_cpu_state(CPUState *cs) { CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); uint32_t flags; - flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK); - flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE; - flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE; - flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE; + flags = sys->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK); + flags |= FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE; + flags |= FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE; + flags |= FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE; flags |= is_va32(env) * HW_FLAGS_VA32; return (TCGTBCPUState){ .pc = env->pc, .flags = flags }; @@ -XXX,XX +XXX,XX @@ static void loongarch_restore_state_to_opc(CPUState *cs, static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) { CPULoongArchState *env = cpu_env(cs); + CPUSysState *sys = env_sys(env); - if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) { - return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); + if (FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PG)) { + return FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV); } return MMU_DA_IDX; } -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in file csr_helper.c, use sys_state rather than env. There is no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605082552.175336-9-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/csr_helper.c | 55 ++++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/csr_helper.c +++ b/target/loongarch/tcg/csr_helper.c @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val) { - int64_t old_v = env->CSR_STLBPS; + CPUSysState *sys = env_sys(env); + int64_t old_v = sys->CSR_STLBPS; /* * The real hardware only supports the min tlb_ps is 12 @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val) } else { /* Only update PS field, reserved bit keeps zero */ val = FIELD_DP64(val, CSR_STLBPS, RESERVE, 0); - env->CSR_STLBPS = val; + sys->CSR_STLBPS = val; } return old_v; @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val) target_ulong helper_csrrd_pgd(CPULoongArchState *env) { int64_t v; + CPUSysState *sys = env_sys(env); - if (env->CSR_TLBRERA & 0x1) { - v = env->CSR_TLBRBADV; + if (sys->CSR_TLBRERA & 0x1) { + v = sys->CSR_TLBRBADV; } else { - v = env->CSR_BADV; + v = sys->CSR_BADV; } if ((v >> 63) & 0x1) { - v = env->CSR_PGDH; + v = sys->CSR_PGDH; } else { - v = env->CSR_PGDL; + v = sys->CSR_PGDL; } return v; @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrd_pgd(CPULoongArchState *env) target_ulong helper_csrrd_cpuid(CPULoongArchState *env) { LoongArchCPU *lac = env_archcpu(env); + CPUSysState *sys = env_sys(env); - env->CSR_CPUID = CPU(lac)->cpu_index; + sys->CSR_CPUID = CPU(lac)->cpu_index; - return env->CSR_CPUID; + return sys->CSR_CPUID; } target_ulong helper_csrrd_tval(CPULoongArchState *env) @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrd_tval(CPULoongArchState *env) target_ulong helper_csrrd_msgir(CPULoongArchState *env) { int irq, new; + CPUSysState *sys = env_sys(env); - irq = find_first_bit((unsigned long *)env->CSR_MSGIS, 256); + irq = find_first_bit((unsigned long *)sys->CSR_MSGIS, 256); if (irq < 256) { - clear_bit(irq, (unsigned long *)env->CSR_MSGIS); - new = find_first_bit((unsigned long *)env->CSR_MSGIS, 256); + clear_bit(irq, (unsigned long *)sys->CSR_MSGIS); + new = find_first_bit((unsigned long *)sys->CSR_MSGIS, 256); if (new < 256) { return irq; } - env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0); + sys->CSR_ESTAT = FIELD_DP64(sys->CSR_ESTAT, CSR_ESTAT, MSGINT, 0); } else { /* bit 31 set 1 for no invalid irq */ irq = BIT(31); @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrrd_msgir(CPULoongArchState *env) target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val) { - int64_t old_v = env->CSR_ESTAT; + CPUSysState *sys = env_sys(env); + int64_t old_v = sys->CSR_ESTAT; /* Only IS[1:0] can be written */ - env->CSR_ESTAT = deposit64(env->CSR_ESTAT, 0, 2, val); + sys->CSR_ESTAT = deposit64(sys->CSR_ESTAT, 0, 2, val); return old_v; } target_ulong helper_csrwr_asid(CPULoongArchState *env, target_ulong val) { - int64_t old_v = env->CSR_ASID; + CPUSysState *sys = env_sys(env); + int64_t old_v = sys->CSR_ASID; /* Only ASID filed of CSR_ASID can be written */ - env->CSR_ASID = deposit64(env->CSR_ASID, 0, 10, val); - if (old_v != env->CSR_ASID) { + sys->CSR_ASID = deposit64(sys->CSR_ASID, 0, 10, val); + if (old_v != sys->CSR_ASID) { tlb_flush(env_cpu(env)); } return old_v; @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_asid(CPULoongArchState *env, target_ulong val) target_ulong helper_csrwr_tcfg(CPULoongArchState *env, target_ulong val) { LoongArchCPU *cpu = env_archcpu(env); - int64_t old_v = env->CSR_TCFG; + CPUSysState *sys = env_sys(env); + int64_t old_v = sys->CSR_TCFG; cpu_loongarch_store_constant_timer_config(cpu, val); @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val) target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) { uint8_t shift, ptbase; - int64_t old_v = env->CSR_PWCL; + CPUSysState *sys = env_sys(env); + int64_t old_v = sys->CSR_PWCL; /* * The real hardware only supports 64bit PTE width now, 128bit or others @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) qemu_log_mask(LOG_GUEST_ERROR, "Attempted set ptbase 2^%d\n", ptbase); } - env->CSR_PWCL = val; + sys->CSR_PWCL = val; return old_v; } target_ulong helper_csrwr_pwch(CPULoongArchState *env, target_ulong val) { uint8_t has_ptw; - int64_t old_v = env->CSR_PWCH; + CPUSysState *sys = env_sys(env); + int64_t old_v = sys->CSR_PWCH; val = FIELD_DP64(val, CSR_PWCH, RESERVE, 0); has_ptw = FIELD_EX32(env->cpucfg[2], CPUCFG2, HPTW); @@ -XXX,XX +XXX,XX @@ target_ulong helper_csrwr_pwch(CPULoongArchState *env, target_ulong val) val = FIELD_DP64(val, CSR_PWCH, HPTW_EN, 0); } - env->CSR_PWCH = val; + sys->CSR_PWCH = val; return old_v; } -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in file op_helper.c, use sys_state rather than env. There is no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605083756.175598-1-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/op_helper.c | 45 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/target/loongarch/tcg/op_helper.c b/target/loongarch/tcg/op_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/op_helper.c +++ b/target/loongarch/tcg/op_helper.c @@ -XXX,XX +XXX,XX @@ target_ulong helper_bitswap(target_ulong v) /* loongarch assert op */ void helper_asrtle_d(CPULoongArchState *env, target_ulong rj, target_ulong rk) { + CPUSysState *sys = env_sys(env); + if (rj > rk) { - env->CSR_BADV = rj; + sys->CSR_BADV = rj; do_raise_exception(env, EXCCODE_BCE, GETPC()); } } void helper_asrtgt_d(CPULoongArchState *env, target_ulong rj, target_ulong rk) { + CPUSysState *sys = env_sys(env); + if (rj <= rk) { - env->CSR_BADV = rj; + sys->CSR_BADV = rj; do_raise_exception(env, EXCCODE_BCE, GETPC()); } } @@ -XXX,XX +XXX,XX @@ uint64_t helper_rdtime_d(CPULoongArchState *env) #else uint64_t plv; LoongArchCPU *cpu = env_archcpu(env); + CPUSysState *sys = env_sys(env); - plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); - if (extract64(env->CSR_MISC, R_CSR_MISC_DRDTL_SHIFT + plv, 1)) { + plv = FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV); + if (extract64(sys->CSR_MISC, R_CSR_MISC_DRDTL_SHIFT + plv, 1)) { do_raise_exception(env, EXCCODE_IPE, GETPC()); } @@ -XXX,XX +XXX,XX @@ uint64_t helper_rdtime_d(CPULoongArchState *env) void helper_ertn(CPULoongArchState *env) { uint64_t csr_pplv, csr_pie; - if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { - csr_pplv = FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV); - csr_pie = FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE); - - env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 0); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 1); - set_pc(env, env->CSR_TLBRERA); + CPUSysState *sys = env_sys(env); + + if (FIELD_EX64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { + csr_pplv = FIELD_EX64(sys->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV); + csr_pie = FIELD_EX64(sys->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE); + + sys->CSR_TLBRERA = FIELD_DP64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 0); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PG, 1); + set_pc(env, sys->CSR_TLBRERA); qemu_log_mask(CPU_LOG_INT, "%s: TLBRERA " TARGET_FMT_lx "\n", - __func__, env->CSR_TLBRERA); + __func__, sys->CSR_TLBRERA); } else { - csr_pplv = FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV); - csr_pie = FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE); + csr_pplv = FIELD_EX64(sys->CSR_PRMD, CSR_PRMD, PPLV); + csr_pie = FIELD_EX64(sys->CSR_PRMD, CSR_PRMD, PIE); - set_pc(env, env->CSR_ERA); + set_pc(env, sys->CSR_ERA); qemu_log_mask(CPU_LOG_INT, "%s: ERA " TARGET_FMT_lx "\n", - __func__, env->CSR_ERA); + __func__, sys->CSR_ERA); } - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, csr_pplv); - env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, csr_pie); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PLV, csr_pplv); + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, IE, csr_pie); env->lladdr = 1; } -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> When accessing CSR registers in directory linux-user/loongarch64/, use sys_state rather than env. There is no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605083844.175612-1-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- linux-user/loongarch64/cpu_loop.c | 5 +++-- linux-user/loongarch64/elfload.c | 4 +++- linux-user/loongarch64/signal.c | 16 ++++++++++------ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/loongarch64/cpu_loop.c +++ b/linux-user/loongarch64/cpu_loop.c @@ -XXX,XX +XXX,XX @@ enum { void cpu_loop(CPULoongArchState *env) { + CPUSysState *sys = env_sys(env); CPUState *cs = env_cpu(env); int trapnr, si_code; abi_long ret; @@ -XXX,XX +XXX,XX @@ void cpu_loop(CPULoongArchState *env) * choose the layout of any signal frame. */ case EXCCODE_SXD: - env->CSR_EUEN |= R_CSR_EUEN_SXE_MASK; + sys->CSR_EUEN |= R_CSR_EUEN_SXE_MASK; break; case EXCCODE_ASXD: - env->CSR_EUEN |= R_CSR_EUEN_ASXE_MASK; + sys->CSR_EUEN |= R_CSR_EUEN_ASXE_MASK; break; case EXCP_ATOMIC: diff --git a/linux-user/loongarch64/elfload.c b/linux-user/loongarch64/elfload.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/loongarch64/elfload.c +++ b/linux-user/loongarch64/elfload.c @@ -XXX,XX +XXX,XX @@ const char *get_elf_platform(CPUState *cs) void elf_core_copy_regs(target_elf_gregset_t *r, const CPULoongArchState *env) { + CPUSysState *sys = env_sys((CPULoongArchState *)env); + r->pt.regs[0] = 0; for (int i = 1; i < ARRAY_SIZE(env->gpr); i++) { @@ -XXX,XX +XXX,XX @@ void elf_core_copy_regs(target_elf_gregset_t *r, const CPULoongArchState *env) } r->pt.csr_era = tswapreg(env->pc); - r->pt.csr_badv = tswapreg(env->CSR_BADV); + r->pt.csr_badv = tswapreg(sys->CSR_BADV); } diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/loongarch64/signal.c +++ b/linux-user/loongarch64/signal.c @@ -XXX,XX +XXX,XX @@ static abi_ptr extframe_alloc(struct extctx_layout *extctx, static abi_ptr setup_extcontext(CPULoongArchState *env, struct extctx_layout *extctx, abi_ptr sp) { + CPUSysState *sys = env_sys(env); + memset(extctx, 0, sizeof(struct extctx_layout)); /* Grow down, alloc "end" context info first. */ @@ -XXX,XX +XXX,XX @@ static abi_ptr setup_extcontext(CPULoongArchState *env, /* For qemu, there is no lazy fp context switch, so fp always present. */ extctx->flags = SC_USED_FP; - if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE)) { + if (FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, ASXE)) { sp = extframe_alloc(extctx, &extctx->lasx, sizeof(struct target_lasx_context), LASX_CTX_ALIGN, sp); - } else if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE)) { + } else if (FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, SXE)) { sp = extframe_alloc(extctx, &extctx->lsx, sizeof(struct target_lsx_context), LSX_CTX_ALIGN, sp); } else { @@ -XXX,XX +XXX,XX @@ static void setup_sigframe(CPULoongArchState *env, struct target_sigcontext *sc, struct extctx_layout *extctx) { + CPUSysState *sys = env_sys(env); struct target_sctx_info *info; int i; @@ -XXX,XX +XXX,XX @@ static void setup_sigframe(CPULoongArchState *env, * Set extension context */ - if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE)) { + if (FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, ASXE)) { struct target_lasx_context *lasx_ctx; info = extctx->lasx.haddr; @@ -XXX,XX +XXX,XX @@ static void setup_sigframe(CPULoongArchState *env, } __put_user(read_fcc(env), &lasx_ctx->fcc); __put_user(env->fcsr0, &lasx_ctx->fcsr); - } else if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE)) { + } else if (FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, SXE)) { struct target_lsx_context *lsx_ctx; info = extctx->lsx.haddr; @@ -XXX,XX +XXX,XX @@ void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPULoongArchState *env) { + CPUSysState *sys = env_sys(env); struct target_rt_sigframe *frame; struct extctx_layout extctx; abi_ptr frame_addr; @@ -XXX,XX +XXX,XX @@ void setup_rt_frame(int sig, struct target_sigaction *ka, return; } - if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE)) { + if (FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, ASXE)) { extctx.lasx.haddr = (void *)frame + (extctx.lasx.gaddr - frame_addr); extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr); - } else if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE)) { + } else if (FIELD_EX64(sys->CSR_EUEN, CSR_EUEN, SXE)) { extctx.lsx.haddr = (void *)frame + (extctx.lsx.gaddr - frame_addr); extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr); } else { -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> With CSR array structure, its validity is checked from offset field. Now default CSRFL_BASIC information is added with flags field and its validility can be checked with flags field. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605083854.175625-1-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/csr.c | 6 +++--- target/loongarch/csr.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/csr.c +++ b/target/loongarch/csr.c @@ -XXX,XX +XXX,XX @@ [LOONGARCH_CSR_##NAME(N)] = { \ .name = (stringify(NAME##N)), \ .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \ - .flags = 0, .readfn = NULL, .writefn = NULL \ + .flags = CSRFL_BASIC, .readfn = NULL, .writefn = NULL \ } #define CSR_OFF_FLAGS(NAME, FL) CSR_OFF_FUNCS(NAME, FL, NULL, NULL) -#define CSR_OFF(NAME) CSR_OFF_FLAGS(NAME, 0) +#define CSR_OFF(NAME) CSR_OFF_FLAGS(NAME, CSRFL_BASIC) static CSRInfo csr_info[] = { CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB), @@ -XXX,XX +XXX,XX @@ CSRInfo *get_csr(unsigned int csr_num) } csr = &csr_info[csr_num]; - if (csr->offset == 0) { + if (csr->flags == 0) { return NULL; } diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/csr.h +++ b/target/loongarch/csr.h @@ -XXX,XX +XXX,XX @@ enum { CSRFL_EXITTB = (1 << 1), CSRFL_IO = (1 << 2), CSRFL_UNUSED = (1 << 3), + CSRFL_BASIC = (1 << 4), }; typedef struct { -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> Add wrapper function get_csr_offset(), it is to get offset from structure CPULoongArchState. There is no function change, and it is used for future LVZ feature. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605083904.175636-1-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu.c | 4 ++-- target/loongarch/csr.h | 4 ++++ .../tcg/insn_trans/trans_privileged.c.inc | 16 +++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f) { #ifndef CONFIG_USER_ONLY CPULoongArchState *env = cpu_env(cs); - CSRInfo *csr_info; + const CSRInfo *csr_info; int64_t *addr; int i, j, len, col = 0; @@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f) qemu_fprintf(f, " CSR%03d:", col); } - addr = (void *)env + csr_info->offset; + addr = (void *)env + get_csr_offset(csr_info, 0); qemu_fprintf(f, " %s ", csr_info->name); len = strlen(csr_info->name); for (; len < 6; len++) { diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/csr.h +++ b/target/loongarch/csr.h @@ -XXX,XX +XXX,XX @@ typedef struct { CSRInfo *get_csr(unsigned int csr_num); bool set_csr_flag(unsigned int csr_num, int flag); +static inline unsigned int get_csr_offset(const CSRInfo *csr, int vm_level) +{ + return csr->offset; +} #endif /* TARGET_LOONGARCH_CSR_H */ diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc @@ -XXX,XX +XXX,XX @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a) TCGv dest; const CSRInfo *csr; GenCSRRead readfn; + tcg_target_long offset; if (check_plv(ctx)) { return false; @@ -XXX,XX +XXX,XX @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a) if (readfn) { readfn(dest, tcg_env); } else { - tcg_gen_ld_tl(dest, tcg_env, csr->offset); + offset = get_csr_offset(csr, 0); + tcg_gen_ld_tl(dest, tcg_env, offset); } } gen_set_gpr(a->rd, dest, EXT_NONE); @@ -XXX,XX +XXX,XX @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a) TCGv dest, src1; const CSRInfo *csr; GenCSRWrite writefn; + tcg_target_long offset; if (check_plv(ctx)) { return false; @@ -XXX,XX +XXX,XX @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a) writefn(dest, tcg_env, src1); } else { dest = tcg_temp_new(); - tcg_gen_ld_tl(dest, tcg_env, csr->offset); - tcg_gen_st_tl(src1, tcg_env, csr->offset); + offset = get_csr_offset(csr, 0); + tcg_gen_ld_tl(dest, tcg_env, offset); + tcg_gen_st_tl(src1, tcg_env, offset); } gen_set_gpr(a->rd, dest, EXT_NONE); return true; @@ -XXX,XX +XXX,XX @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) TCGv src1, mask, oldv, newv, temp; const CSRInfo *csr; GenCSRWrite writefn; + tcg_target_long offset; if (check_plv(ctx)) { return false; @@ -XXX,XX +XXX,XX @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) newv = tcg_temp_new(); temp = tcg_temp_new(); - tcg_gen_ld_tl(oldv, tcg_env, csr->offset); + offset = get_csr_offset(csr, 0); + tcg_gen_ld_tl(oldv, tcg_env, offset); tcg_gen_and_tl(newv, src1, mask); tcg_gen_andc_tl(temp, oldv, mask); tcg_gen_or_tl(newv, newv, temp); @@ -XXX,XX +XXX,XX @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) if (writefn) { writefn(oldv, tcg_env, newv); } else { - tcg_gen_st_tl(newv, tcg_env, csr->offset); + tcg_gen_st_tl(newv, tcg_env, offset); } gen_set_gpr(a->rd, oldv, EXT_NONE); return true; -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> Instruction rdtime is to read TSC timestamp and logic vCPU id, it is also used by Linux user mode emulation. However function get_csr_offset() cannot be called in user mode emulation, here macro CSR_OFFSET and CPU_CSR_OFFSET are added. The added macro can be called in both user emulation and system emulation. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@mailo.com> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605083910.175647-1-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/csr.c | 4 ++-- target/loongarch/csr.h | 3 +++ target/loongarch/tcg/insn_trans/trans_extra.c.inc | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/csr.c +++ b/target/loongarch/csr.c @@ -XXX,XX +XXX,XX @@ #define CSR_OFF_FUNCS(NAME, FL, RD, WR) \ [LOONGARCH_CSR_##NAME] = { \ .name = (stringify(NAME)), \ - .offset = offsetof(CPULoongArchState, CSR_##NAME), \ + .offset = CSR_OFFSET(CSR_##NAME), \ .flags = FL, .readfn = RD, .writefn = WR \ } #define CSR_OFF_ARRAY(NAME, N) \ [LOONGARCH_CSR_##NAME(N)] = { \ .name = (stringify(NAME##N)), \ - .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \ + .offset = CSR_OFFSET(CSR_##NAME[N]), \ .flags = CSRFL_BASIC, .readfn = NULL, .writefn = NULL \ } diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/csr.h +++ b/target/loongarch/csr.h @@ -XXX,XX +XXX,XX @@ #include "cpu-csr.h" +#define CSR_OFFSET(id) offsetof(CPULoongArchState, id) +#define CPU_CSR_OFFSET(id, vm_level) CSR_OFFSET(id) + typedef void (*GenCSRFunc)(void); enum { CSRFL_READONLY = (1 << 0), diff --git a/target/loongarch/tcg/insn_trans/trans_extra.c.inc b/target/loongarch/tcg/insn_trans/trans_extra.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/tcg/insn_trans/trans_extra.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_extra.c.inc @@ -XXX,XX +XXX,XX @@ * Copyright (c) 2021 Loongson Technology Corporation Limited */ +#include "csr.h" static bool trans_break(DisasContext *ctx, arg_break *a) { generate_exception(ctx, EXCCODE_BRK); @@ -XXX,XX +XXX,XX @@ static bool gen_rdtime(DisasContext *ctx, arg_rr *a, { TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE); TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE); + tcg_target_long offset; translator_io_start(&ctx->base); gen_helper_rdtime_d(dst1, tcg_env); if (word) { tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32); } - tcg_gen_ld_i64(dst2, tcg_env, offsetof(CPULoongArchState, CSR_TID)); + + offset = CPU_CSR_OFFSET(CSR_TID, 0); + tcg_gen_ld_i64(dst2, tcg_env, offset); return true; } -- 2.54.0
From: Bibo Mao <maobibo@loongson.cn> New structure CPUSysState is added here, now it only contains CSR registers, in future TLB and timer can be moved to this structure also. It is only code movement, no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Tested-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260605083938.175658-1-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu.c | 4 +- target/loongarch/cpu.h | 35 +++++------ target/loongarch/csr.h | 8 ++- target/loongarch/machine.c | 118 +++++++++++++++++++------------------ 4 files changed, 85 insertions(+), 80 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -XXX,XX +XXX,XX @@ static void loongarch_la464_initfn(Object *obj) uint32_t data = 0, field; int i; - set_sys_state(env, env); + set_sys_state(env, &env->sys_states[0]); for (i = 0; i < 21; i++) { env->cpucfg[i] = 0x0; } @@ -XXX,XX +XXX,XX @@ static void loongarch_la132_initfn(Object *obj) uint32_t data = 0; int i; - set_sys_state(env, env); + set_sys_state(env, &env->sys_states[0]); for (i = 0; i < 21; i++) { env->cpucfg[i] = 0x0; } diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct LoongArchBT { #define CPU_VENDOR_LOONGSON "Loongson" #define CPU_MODEL_3A5000 "3A5000" #define CPU_MODEL_1C101 "1C101" -struct CPUArchState; -typedef struct CPUArchState CPUSysState; - -typedef struct CPUArchState { - uint64_t gpr[32]; - uint64_t pc; - - fpr_t fpr[32]; - bool cf[8]; - uint32_t fcsr0; - lbt_t lbt; - - uint32_t cpucfg[21]; - uint32_t pv_features; - uint64_t vendor_id; - uint64_t cpu_id; - +typedef struct CPUSysState { /* LoongArch CSRs */ uint64_t CSR_CRMD; uint64_t CSR_PRMD; @@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState { uint64_t CSR_MSGIS[N_MSGIS]; uint64_t CSR_MSGIR; uint64_t CSR_MSGIE; +} CPUSysState; + +typedef struct CPUArchState { + uint64_t gpr[32]; + uint64_t pc; + + fpr_t fpr[32]; + bool cf[8]; + uint32_t fcsr0; + lbt_t lbt; + + uint32_t cpucfg[21]; + uint32_t pv_features; + uint64_t vendor_id; + uint64_t cpu_id; + CPUSysState sys_states[1]; + struct { uint64_t guest_addr; } stealtime; diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/csr.h +++ b/target/loongarch/csr.h @@ -XXX,XX +XXX,XX @@ #include "cpu-csr.h" -#define CSR_OFFSET(id) offsetof(CPULoongArchState, id) -#define CPU_CSR_OFFSET(id, vm_level) CSR_OFFSET(id) +#define CSR_OFFSET(id) offsetof(CPUSysState, id) +#define CPU_CSR_OFFSET(id, vm_level) \ + (offsetof(CPULoongArchState, sys_states[vm_level]) \ + + CSR_OFFSET(id)) typedef void (*GenCSRFunc)(void); enum { @@ -XXX,XX +XXX,XX @@ CSRInfo *get_csr(unsigned int csr_num); bool set_csr_flag(unsigned int csr_num, int flag); static inline unsigned int get_csr_offset(const CSRInfo *csr, int vm_level) { - return csr->offset; + return csr->offset + offsetof(CPULoongArchState, sys_states[vm_level]); } #endif /* TARGET_LOONGARCH_CSR_H */ diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/loongarch/machine.c +++ b/target/loongarch/machine.c @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_msgint = { .minimum_version_id = 1, .needed = msgint_needed, .fields = (const VMStateField[]) { - VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, N_MSGIS), - VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU), + VMSTATE_UINT64_ARRAY(env.sys_states[0].CSR_MSGIS, LoongArchCPU, N_MSGIS), + VMSTATE_UINT64(env.sys_states[0].CSR_MSGIR, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MSGIE, LoongArchCPU), VMSTATE_END_OF_LIST() }, }; @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmu = { .needed = pmu_needed, .fields = (const VMStateField[]) { VMSTATE_UINT32(env.perf_event_num, LoongArchCPU), - VMSTATE_UINT64_ARRAY(env.CSR_PERFCTRL, LoongArchCPU, MAX_PERF_EVENTS), - VMSTATE_UINT64_ARRAY(env.CSR_PERFCNTR, LoongArchCPU, MAX_PERF_EVENTS), + VMSTATE_UINT64_ARRAY(env.sys_states[0].CSR_PERFCTRL, LoongArchCPU,\ + MAX_PERF_EVENTS), + VMSTATE_UINT64_ARRAY(env.sys_states[0].CSR_PERFCNTR, LoongArchCPU, \ + MAX_PERF_EVENTS), VMSTATE_END_OF_LIST() }, }; @@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_loongarch_cpu = { VMSTATE_UINT64(env.pc, LoongArchCPU), /* Remaining CSRs */ - VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU), - VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU), - VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU), - VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU), - VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU), - VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU), - VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU), - VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU), - VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU), - VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU), - VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU), - VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU), - VMSTATE_UINT64_ARRAY(env.CSR_SAVE, LoongArchCPU, 16), - VMSTATE_UINT64(env.CSR_TID, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU), - VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TICLR, LoongArchCPU), - VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU), - VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU), - VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU), - VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MERRINFO2, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MERRENTRY, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU), - VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU), - VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU), - VMSTATE_UINT64_ARRAY(env.CSR_DMW, LoongArchCPU, 4), + VMSTATE_UINT64(env.sys_states[0].CSR_CRMD, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PRMD, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_EUEN, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MISC, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_ECFG, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_ESTAT, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_ERA, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_BADV, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_BADI, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_EENTRY, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBIDX, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBEHI, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBELO0, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBELO1, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_ASID, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PGDL, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PGDH, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PGD, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PWCL, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PWCH, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_STLBPS, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_RVACFG, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PRCFG1, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PRCFG2, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_PRCFG3, LoongArchCPU), + VMSTATE_UINT64_ARRAY(env.sys_states[0].CSR_SAVE, LoongArchCPU, 16), + VMSTATE_UINT64(env.sys_states[0].CSR_TID, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TCFG, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TVAL, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_CNTC, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TICLR, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_LLBCTL, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_IMPCTL1, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_IMPCTL2, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRENTRY, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRBADV, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRERA, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRSAVE, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRELO0, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRELO1, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBREHI, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_TLBRPRMD, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MERRCTL, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MERRINFO1, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MERRINFO2, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MERRENTRY, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MERRERA, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_MERRSAVE, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_CTAG, LoongArchCPU), + VMSTATE_UINT64_ARRAY(env.sys_states[0].CSR_DMW, LoongArchCPU, 4), /* Debug CSRs */ - VMSTATE_UINT64(env.CSR_DBG, LoongArchCPU), - VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU), - VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_DBG, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_DERA, LoongArchCPU), + VMSTATE_UINT64(env.sys_states[0].CSR_DSAVE, LoongArchCPU), VMSTATE_UINT64(kvm_state_counter, LoongArchCPU), /* PV steal time */ -- 2.54.0