:p
atchew
Login
The following changes since commit d6dfd8d40cebebc3378d379cd28879e0345fbf91: Merge tag 'pull-target-arm-20250926' of https://gitlab.com/pm215/qemu into staging (2025-09-26 13:27:01 -0700) are available in the Git repository at: https://github.com/bibo-mao/qemu.git tags/pull-loongarch-20250928 for you to fetch changes up to 8d26856fabf8faac60de03a2e0fc35e5338e248e: target/loongarch: Only flush one TLB entry in helper_invtlb_page_asid() (2025-09-28 16:10:34 +0800) ---------------------------------------------------------------- pull-loongarch-20250928 queue ---------------------------------------------------------------- Bibo Mao (13): target/loongarch: Use mmu idx bitmap method when flush TLB target/loongarch: Add parameter tlb pointer with fill_tlb_entry target/loongarch: Reduce TLB flush with helper_tlbwr target/loongarch: Update TLB index selection method target/loongarch: Fix page size set issue with CSR_STLBPS target/loongarch: Add tlb search callback in loongarch_tlb_search() target/loongarch: Add common API loongarch_tlb_search_cb() target/loongarch: Change return value type with loongarch_tlb_search_cb() target/loongarch: Use loongarch_tlb_search_cb in helper_invtlb_page_asid_or_g target/loongarch: Use loongarch_tlb_search_cb in helper_invtlb_page_asid target/loongarch: Invalid tlb entry in invalidate_tlb() target/loongarch: Only flush one TLB entry in helper_invtlb_page_asid_or_g() target/loongarch: Only flush one TLB entry in helper_invtlb_page_asid() target/loongarch/cpu-csr.h | 1 + target/loongarch/tcg/csr_helper.c | 5 +- target/loongarch/tcg/tlb_helper.c | 205 +++++++++++++++++++++++--------------- 3 files changed, 131 insertions(+), 80 deletions(-)
With API tlb_flush_range_by_mmuidx(), bitmap of mmu idx should be used rather than itself. Also bitmap of MMU_KERNEL_IDX and MMU_USER_IDX are used rather than that of current running mmu idx when flush TLB. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 7 +++---- 1 file changed, 3 insertions(+), 4 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 invalidate_tlb_entry(CPULoongArchState *env, int index) target_ulong addr, mask, pagesize; uint8_t tlb_ps; LoongArchTLB *tlb = &env->tlb[index]; - - int mmu_idx = cpu_mmu_index(env_cpu(env), false); + 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); @@ -XXX,XX +XXX,XX @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index) if (tlb_v0) { tlb_flush_range_by_mmuidx(env_cpu(env), addr, pagesize, - mmu_idx, TARGET_LONG_BITS); + idxmap, TARGET_LONG_BITS); } if (tlb_v1) { tlb_flush_range_by_mmuidx(env_cpu(env), addr + pagesize, pagesize, - mmu_idx, TARGET_LONG_BITS); + idxmap, TARGET_LONG_BITS); } } -- 2.43.5
With function fill_tlb_entry(), it will update LoongArch emulated TLB information. Here parameter tlb pointer is added so that TLB entry will be updated based on relative TLB CSR registers. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 7 +++---- 1 file changed, 3 insertions(+), 4 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 invalidate_tlb(CPULoongArchState *env, int index) invalidate_tlb_entry(env, index); } -static void fill_tlb_entry(CPULoongArchState *env, int index) +static void fill_tlb_entry(CPULoongArchState *env, LoongArchTLB *tlb) { - LoongArchTLB *tlb = &env->tlb[index]; uint64_t lo0, lo1, csr_vppn; uint16_t csr_asid; uint8_t csr_ps; @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) return; } - fill_tlb_entry(env, index); + fill_tlb_entry(env, env->tlb + index); } void helper_tlbfill(CPULoongArchState *env) @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *env) } invalidate_tlb(env, index); - fill_tlb_entry(env, index); + fill_tlb_entry(env, env->tlb + index); } void helper_tlbclr(CPULoongArchState *env) -- 2.43.5
With function helper_tlbwr(), specified LoongArch TLB entry will be updated. There are two PTE pages in one TLB entry called even/odd pages. Supposing even/odd page is normal/none state, when odd page is added, TLB entry is changed as normal/normal state and even page keeps unchanged. In this situation, it is not necessary to flush QEMU TLB since even page keep unchanged and odd page is newly changed. Here check whether PTE page is the same or not, TLB flush can be skipped if both are the same or newly added. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 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) { int index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); + LoongArchTLB *old, new = {}; + bool skip_inv = false; + uint8_t tlb_v0, tlb_v1; - invalidate_tlb(env, index); - + old = env->tlb + index; if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { - env->tlb[index].tlb_misc = FIELD_DP64(env->tlb[index].tlb_misc, - TLB_MISC, E, 0); + invalidate_tlb(env, index); + old->tlb_misc = FIELD_DP64(old->tlb_misc, TLB_MISC, E, 0); return; } - fill_tlb_entry(env, env->tlb + index); + fill_tlb_entry(env, &new); + /* 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); + if ((!tlb_v0 || new.tlb_entry0 == old->tlb_entry0) && + (!tlb_v1 || new.tlb_entry1 == old->tlb_entry1)) { + skip_inv = true; + } + } + + /* flush tlb before updating the entry */ + if (!skip_inv) { + invalidate_tlb(env, index); + } + + *old = new; } void helper_tlbfill(CPULoongArchState *env) -- 2.43.5
With function helper_tlbfill(), since there is no suitable TLB entry, new TLB will be added and flush one old TLB entry. The old TLB entry index is selected randomly now, instead it can be optimized as following: 1. invalid TLB entry can be selected at first. 2. TLB entry with other ASID can be selected secondly 3. random method is used by last. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 49 ++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 7 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) void helper_tlbfill(CPULoongArchState *env) { uint64_t address, entryhi; - int index, set, stlb_idx; + int index, set, i, stlb_idx; uint16_t pagesize, stlb_ps; + uint16_t asid, tlb_asid; + LoongArchTLB *tlb; + uint8_t tlb_e; if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { entryhi = env->CSR_TLBREHI; @@ -XXX,XX +XXX,XX @@ void helper_tlbfill(CPULoongArchState *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); if (pagesize == stlb_ps) { /* Only write into STLB bits [47:13] */ address = entryhi & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_64_VPPN_SHIFT); - - /* Choose one set ramdomly */ - set = get_random_tlb(0, 7); - - /* Index in one set */ + set = -1; stlb_idx = (address >> (stlb_ps + 1)) & 0xff; /* [0,255] */ + for (i = 0; i < 8; ++i) { + tlb = &env->tlb[i * 256 + stlb_idx]; + tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); + if (!tlb_e) { + set = i; + break; + } + + tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); + if (asid != tlb_asid) { + set = i; + } + } + /* Choose one set randomly */ + if (set < 0) { + set = get_random_tlb(0, 7); + } index = set * 256 + stlb_idx; } else { /* Only write into MTLB */ - index = get_random_tlb(LOONGARCH_STLB, LOONGARCH_TLB_MAX - 1); + index = -1; + for (i = LOONGARCH_STLB; i < LOONGARCH_TLB_MAX; i++) { + tlb = &env->tlb[i]; + tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); + + if (!tlb_e) { + index = i; + break; + } + + tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); + if (asid != tlb_asid) { + index = i; + } + } + + if (index < 0) { + index = get_random_tlb(LOONGARCH_STLB, LOONGARCH_TLB_MAX - 1); + } } invalidate_tlb(env, index); -- 2.43.5
When modify register CSR_STLBPS, the page size should come from input parameter rather than old value. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/cpu-csr.h | 1 + target/loongarch/tcg/csr_helper.c | 5 +++-- 2 files changed, 4 insertions(+), 2 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(CSR_PWCH, DIR4_WIDTH, 18, 6) #define LOONGARCH_CSR_STLBPS 0x1e /* Stlb page size */ FIELD(CSR_STLBPS, PS, 0, 5) +FIELD(CSR_STLBPS, RESERVE, 5, 27) #define LOONGARCH_CSR_RVACFG 0x1f /* Reduced virtual address config */ FIELD(CSR_RVACFG, RBITS, 0, 4) 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) * The real hardware only supports the min tlb_ps is 12 * tlb_ps=0 may cause undefined-behavior. */ - uint8_t tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); + uint8_t tlb_ps = FIELD_EX64(val, CSR_STLBPS, PS); if (!check_ps(env, tlb_ps)) { qemu_log_mask(LOG_GUEST_ERROR, "Attempted set ps %d\n", tlb_ps); } else { /* Only update PS field, reserved bit keeps zero */ - env->CSR_STLBPS = FIELD_DP64(old_v, CSR_STLBPS, PS, tlb_ps); + val = FIELD_DP64(val, CSR_STLBPS, RESERVE, 0); + env->CSR_STLBPS = val; } return old_v; -- 2.43.5
With function loongarch_tlb_search(), it is to search TLB entry with speficied virtual address, the difference is selection with asid and global bit. Here add selection callback with asid and global bit. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 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 @@ #include "cpu-csr.h" #include "tcg/tcg_loongarch.h" +typedef bool (*tlb_match)(bool global, int asid, int tlb_asid); + +static bool tlb_match_any(bool global, int asid, int tlb_asid) +{ + return global || tlb_asid == asid; +} + bool check_ps(CPULoongArchState *env, uint8_t tlb_ps) { if (tlb_ps >= 64) { @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, { LoongArchTLB *tlb; uint16_t csr_asid, tlb_asid, stlb_idx; - uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps; + uint8_t tlb_e, tlb_ps, stlb_ps; + bool tlb_g; int i, compare_shift; uint64_t vpn, tlb_vppn; + tlb_match func; + func = tlb_match_any; csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); - stlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); + stlb_ps = FIELD_EX64(env->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, if (tlb_e) { tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); - tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G); + tlb_g = !!FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G); - if ((tlb_g == 1 || tlb_asid == csr_asid) && + if (func(tlb_g, csr_asid, tlb_asid) && (vpn == (tlb_vppn >> compare_shift))) { *index = i * 256 + stlb_idx; return true; @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G); compare_shift = tlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT; vpn = (vaddr & TARGET_VIRT_MASK) >> (tlb_ps + 1); - if ((tlb_g == 1 || tlb_asid == csr_asid) && + if (func(tlb_g, csr_asid, tlb_asid) && (vpn == (tlb_vppn >> compare_shift))) { *index = i; return true; -- 2.43.5
Common API loongarch_tlb_search_cb() is added here to search TLB entry with specified address. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 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 uint32_t get_random_tlb(uint32_t low, uint32_t high) * field in tlb entry contains bit[47:13], so need adjust. * virt_vpn = vaddr[47:13] */ -static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, - int *index) +static bool loongarch_tlb_search_cb(CPULoongArchState *env, vaddr vaddr, + int *index, int csr_asid, tlb_match func) { LoongArchTLB *tlb; - uint16_t csr_asid, tlb_asid, stlb_idx; + uint16_t tlb_asid, stlb_idx; uint8_t tlb_e, tlb_ps, stlb_ps; bool tlb_g; int i, compare_shift; uint64_t vpn, tlb_vppn; - tlb_match func; - func = tlb_match_any; - csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); stlb_ps = FIELD_EX64(env->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 */ @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, return false; } +static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, + int *index) +{ + int csr_asid; + tlb_match func; + + func = tlb_match_any; + csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); + return loongarch_tlb_search_cb(env, vaddr, index, csr_asid, func); +} + void helper_tlbsrch(CPULoongArchState *env) { int index, match; -- 2.43.5
With function loongarch_tlb_search_cb(), change return value type from bool type to pointer LoongArchTLB *, the pointer type can be use directly in future. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 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 uint32_t get_random_tlb(uint32_t low, uint32_t high) * field in tlb entry contains bit[47:13], so need adjust. * virt_vpn = vaddr[47:13] */ -static bool loongarch_tlb_search_cb(CPULoongArchState *env, vaddr vaddr, - int *index, int csr_asid, tlb_match func) +static LoongArchTLB *loongarch_tlb_search_cb(CPULoongArchState *env, + vaddr vaddr, int csr_asid, + tlb_match func) { LoongArchTLB *tlb; uint16_t tlb_asid, stlb_idx; @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search_cb(CPULoongArchState *env, vaddr vaddr, if (func(tlb_g, csr_asid, tlb_asid) && (vpn == (tlb_vppn >> compare_shift))) { - *index = i * 256 + stlb_idx; - return true; + return tlb; } } } @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search_cb(CPULoongArchState *env, vaddr vaddr, vpn = (vaddr & TARGET_VIRT_MASK) >> (tlb_ps + 1); if (func(tlb_g, csr_asid, tlb_asid) && (vpn == (tlb_vppn >> compare_shift))) { - *index = i; - return true; + return tlb; } } } - return false; + return NULL; } static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, @@ -XXX,XX +XXX,XX @@ static bool loongarch_tlb_search(CPULoongArchState *env, vaddr vaddr, { int csr_asid; tlb_match func; + LoongArchTLB *tlb; func = tlb_match_any; csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID); - return loongarch_tlb_search_cb(env, vaddr, index, csr_asid, func); + tlb = loongarch_tlb_search_cb(env, vaddr, csr_asid, func); + if (tlb) { + *index = tlb - env->tlb; + return true; + } + + return false; } void helper_tlbsrch(CPULoongArchState *env) -- 2.43.5
With function helper_invtlb_page_asid_or_g(), currently it is to search TLB entry one by one. Instead STLB can be searched at first with hash method, and then search MTLB with one by one method. Here common API loongarch_tlb_search_cb() is used in function helper_invtlb_page_asid_or_g(). Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 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_invtlb_page_asid(CPULoongArchState *env, target_ulong info, void helper_invtlb_page_asid_or_g(CPULoongArchState *env, target_ulong info, target_ulong addr) { - uint16_t asid = info & 0x3ff; - - for (int i = 0; i < LOONGARCH_TLB_MAX; i++) { - LoongArchTLB *tlb = &env->tlb[i]; - uint8_t tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G); - uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); - uint64_t vpn, tlb_vppn; - uint8_t tlb_ps, compare_shift; - uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); - - if (!tlb_e) { - continue; - } - - tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); - tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); - vpn = (addr & TARGET_VIRT_MASK) >> (tlb_ps + 1); - compare_shift = tlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT; + int asid = info & 0x3ff; + LoongArchTLB *tlb; + tlb_match func; - if ((tlb_g || (tlb_asid == asid)) && - (vpn == (tlb_vppn >> compare_shift))) { - tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); - } + func = tlb_match_any; + tlb = loongarch_tlb_search_cb(env, addr, asid, func); + if (tlb) { + tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); + tlb_flush(env_cpu(env)); } - tlb_flush(env_cpu(env)); } bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, -- 2.43.5
With function helper_invtlb_page_asid(), currently it is to search TLB entry one by one. Instead STLB can be searched at first with hash method, and then search MTLB with one by one method Here common API loongarch_tlb_search_cb() is used in function helper_invtlb_page_asid() Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 36 +++++++++++-------------------- 1 file changed, 13 insertions(+), 23 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_any(bool global, int asid, int tlb_asid) return global || tlb_asid == asid; } +static bool tlb_match_asid(bool global, int asid, int tlb_asid) +{ + return !global && tlb_asid == asid; +} + bool check_ps(CPULoongArchState *env, uint8_t tlb_ps) { if (tlb_ps >= 64) { @@ -XXX,XX +XXX,XX @@ void helper_invtlb_all_asid(CPULoongArchState *env, target_ulong info) void helper_invtlb_page_asid(CPULoongArchState *env, target_ulong info, target_ulong addr) { - uint16_t asid = info & 0x3ff; - - for (int i = 0; i < LOONGARCH_TLB_MAX; i++) { - LoongArchTLB *tlb = &env->tlb[i]; - uint8_t tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G); - uint16_t tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID); - uint64_t vpn, tlb_vppn; - uint8_t tlb_ps, compare_shift; - uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E); - - if (!tlb_e) { - continue; - } - - tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); - tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN); - vpn = (addr & TARGET_VIRT_MASK) >> (tlb_ps + 1); - compare_shift = tlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT; + int asid = info & 0x3ff; + LoongArchTLB *tlb; + tlb_match func; - if (!tlb_g && (tlb_asid == asid) && - (vpn == (tlb_vppn >> compare_shift))) { - tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); - } + func = tlb_match_asid; + tlb = loongarch_tlb_search_cb(env, addr, asid, func); + if (tlb) { + tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); + tlb_flush(env_cpu(env)); } - tlb_flush(env_cpu(env)); } void helper_invtlb_page_asid_or_g(CPULoongArchState *env, -- 2.43.5
Invalid tlb entry in function invalidate_tlb(), and its usage is simple and easy to use. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> --- target/loongarch/tcg/tlb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) return; } + tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS); pagesize = MAKE_64BIT_MASK(tlb_ps, 1); mask = MAKE_64BIT_MASK(0, tlb_ps + 1); @@ -XXX,XX +XXX,XX @@ void helper_tlbwr(CPULoongArchState *env) old = env->tlb + index; if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) { invalidate_tlb(env, index); - old->tlb_misc = FIELD_DP64(old->tlb_misc, TLB_MISC, E, 0); return; } -- 2.43.5
With function helper_invtlb_page_asid_or_g(), only one TLB entry in LoongArch emulated TLB is invalidated. so with QEMU TLB, it is not necessary to flush all QEMU TLB, only flush address range specified LoongArch emulated TLB is ok. Here invalidate_tlb_entry() is called so that only QEMU TLB entry with specified address range is flushed. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 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_invtlb_page_asid_or_g(CPULoongArchState *env, func = tlb_match_any; tlb = loongarch_tlb_search_cb(env, addr, asid, func); if (tlb) { - tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); - tlb_flush(env_cpu(env)); + invalidate_tlb(env, tlb - env->tlb); } } -- 2.43.5
With function helper_invtlb_page_asid(), only one TLB entry in LoongArch emulated TLB is invalidated. so with QEMU TLB, it is not necessary to flush all QEMU TLB, only flush address range specified LoongArch emulated TLB is ok. Here invalidate_tlb_entry() is called so that only QEMU TLB entry with specified address range is flushed. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> --- target/loongarch/tcg/tlb_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 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_invtlb_page_asid(CPULoongArchState *env, target_ulong info, func = tlb_match_asid; tlb = loongarch_tlb_search_cb(env, addr, asid, func); if (tlb) { - tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0); - tlb_flush(env_cpu(env)); + invalidate_tlb(env, tlb - env->tlb); } } -- 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