target/loongarch/internals.h | 20 ++- target/loongarch/cpu.c | 2 - target/loongarch/cpu_helper.c | 231 ++++++++++++++++++++++++++++++ target/loongarch/tcg/tlb_helper.c | 230 ----------------------------- target/loongarch/meson.build | 1 + 5 files changed, 250 insertions(+), 234 deletions(-) create mode 100644 target/loongarch/cpu_helper.c
The cc->sysemu_ops->get_phys_page_debug() is NULL when
KVM-only build. this patch fixes it.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/internals.h | 20 ++-
target/loongarch/cpu.c | 2 -
target/loongarch/cpu_helper.c | 231 ++++++++++++++++++++++++++++++
target/loongarch/tcg/tlb_helper.c | 230 -----------------------------
target/loongarch/meson.build | 1 +
5 files changed, 250 insertions(+), 234 deletions(-)
create mode 100644 target/loongarch/cpu_helper.c
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 0beb034748..a2fc54c8a7 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -37,6 +37,17 @@ void restore_fp_status(CPULoongArchState *env);
#endif
#ifndef CONFIG_USER_ONLY
+enum {
+ TLBRET_MATCH = 0,
+ TLBRET_BADADDR = 1,
+ TLBRET_NOMATCH = 2,
+ TLBRET_INVALID = 3,
+ TLBRET_DIRTY = 4,
+ TLBRET_RI = 5,
+ TLBRET_XI = 6,
+ TLBRET_PE = 7,
+};
+
extern const VMStateDescription vmstate_loongarch_cpu;
void loongarch_cpu_set_irq(void *opaque, int irq, int level);
@@ -46,12 +57,17 @@ uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
uint64_t value);
+bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
+ int *index);
+int get_physical_address(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx);
+hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+
#ifdef CONFIG_TCG
bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
-
-hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
#endif
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 064540397d..1e58c160ab 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -752,9 +752,7 @@ static struct TCGCPUOps loongarch_tcg_ops = {
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps loongarch_sysemu_ops = {
-#ifdef CONFIG_TCG
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
-#endif
};
static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c
new file mode 100644
index 0000000000..f68d63f466
--- /dev/null
+++ b/target/loongarch/cpu_helper.c
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch CPU helpers for qemu
+ *
+ * Copyright (c) 2024 Loongson Technology Corporation Limited
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+#include "cpu-csr.h"
+
+static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ int access_type, int index, int mmu_idx)
+{
+ LoongArchTLB *tlb = &env->tlb[index];
+ uint64_t plv = mmu_idx;
+ uint64_t tlb_entry, tlb_ppn;
+ uint8_t tlb_ps, n, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv;
+
+ if (index >= LOONGARCH_STLB) {
+ tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
+ } else {
+ tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
+ }
+ n = (address >> tlb_ps) & 0x1;/* Odd or even */
+
+ tlb_entry = n ? tlb->tlb_entry1 : tlb->tlb_entry0;
+ tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
+ tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
+ tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
+ if (is_la64(env)) {
+ tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
+ tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
+ tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
+ tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
+ } else {
+ tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
+ tlb_nx = 0;
+ tlb_nr = 0;
+ tlb_rplv = 0;
+ }
+
+ /* Remove sw bit between bit12 -- bit PS*/
+ tlb_ppn = tlb_ppn & ~(((0x1UL << (tlb_ps - 12)) -1));
+
+ /* Check access rights */
+ if (!tlb_v) {
+ return TLBRET_INVALID;
+ }
+
+ if (access_type == MMU_INST_FETCH && tlb_nx) {
+ return TLBRET_XI;
+ }
+
+ if (access_type == MMU_DATA_LOAD && tlb_nr) {
+ return TLBRET_RI;
+ }
+
+ if (((tlb_rplv == 0) && (plv > tlb_plv)) ||
+ ((tlb_rplv == 1) && (plv != tlb_plv))) {
+ return TLBRET_PE;
+ }
+
+ if ((access_type == MMU_DATA_STORE) && !tlb_d) {
+ return TLBRET_DIRTY;
+ }
+
+ *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
+ (address & MAKE_64BIT_MASK(0, tlb_ps));
+ *prot = PAGE_READ;
+ if (tlb_d) {
+ *prot |= PAGE_WRITE;
+ }
+ if (!tlb_nx) {
+ *prot |= PAGE_EXEC;
+ }
+ return TLBRET_MATCH;
+}
+
+/*
+ * One tlb entry holds an adjacent odd/even pair, the vpn is the
+ * content of the virtual page number divided by 2. So the
+ * compare vpn is bit[47:15] for 16KiB page. while the vppn
+ * field in tlb entry contains bit[47:13], so need adjust.
+ * virt_vpn = vaddr[47:13]
+ */
+bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
+ int *index)
+{
+ LoongArchTLB *tlb;
+ uint16_t csr_asid, tlb_asid, stlb_idx;
+ uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps;
+ int i, compare_shift;
+ uint64_t vpn, tlb_vppn;
+
+ 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 */
+ compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
+
+ /* Search STLB */
+ 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) {
+ 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);
+
+ if ((tlb_g == 1 || tlb_asid == csr_asid) &&
+ (vpn == (tlb_vppn >> compare_shift))) {
+ *index = i * 256 + stlb_idx;
+ return true;
+ }
+ }
+ }
+
+ /* Search MTLB */
+ 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) {
+ tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
+ tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
+ tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
+ 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) &&
+ (vpn == (tlb_vppn >> compare_shift))) {
+ *index = i;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx)
+{
+ int index, match;
+
+ match = loongarch_tlb_search(env, address, &index);
+ if (match) {
+ return loongarch_map_tlb_entry(env, physical, prot,
+ address, access_type, index, mmu_idx);
+ }
+
+ return TLBRET_NOMATCH;
+}
+
+static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
+ target_ulong dmw)
+{
+ if (is_la64(env)) {
+ return va & TARGET_VIRT_MASK;
+ } else {
+ uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
+ return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
+ (pseg << R_CSR_DMW_32_VSEG_SHIFT);
+ }
+}
+
+int get_physical_address(CPULoongArchState *env, hwaddr *physical,
+ int *prot, target_ulong address,
+ MMUAccessType access_type, int mmu_idx)
+{
+ int user_mode = mmu_idx == MMU_IDX_USER;
+ int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
+ 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);
+
+ /* Check PG and DA */
+ if (da & !pg) {
+ *physical = address & TARGET_PHYS_MASK;
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return TLBRET_MATCH;
+ }
+
+ plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
+ if (is_la64(env)) {
+ base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
+ } else {
+ base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
+ }
+ /* 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);
+ } else {
+ base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
+ }
+ if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
+ *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return TLBRET_MATCH;
+ }
+ }
+
+ /* Check valid extension */
+ addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16);
+ if (!(addr_high == 0 || addr_high == -1)) {
+ return TLBRET_BADADDR;
+ }
+
+ /* Mapped address */
+ return loongarch_map_address(env, physical, prot, address,
+ access_type, mmu_idx);
+}
+
+hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+ hwaddr phys_addr;
+ int prot;
+
+ if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD,
+ cpu_mmu_index(env, false)) != 0) {
+ return -1;
+ }
+ return phys_addr;
+}
diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 449043c68b..804ab7a263 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,236 +17,6 @@
#include "exec/log.h"
#include "cpu-csr.h"
-enum {
- TLBRET_MATCH = 0,
- TLBRET_BADADDR = 1,
- TLBRET_NOMATCH = 2,
- TLBRET_INVALID = 3,
- TLBRET_DIRTY = 4,
- TLBRET_RI = 5,
- TLBRET_XI = 6,
- TLBRET_PE = 7,
-};
-
-static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address,
- int access_type, int index, int mmu_idx)
-{
- LoongArchTLB *tlb = &env->tlb[index];
- uint64_t plv = mmu_idx;
- uint64_t tlb_entry, tlb_ppn;
- uint8_t tlb_ps, n, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv;
-
- if (index >= LOONGARCH_STLB) {
- tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
- } else {
- tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
- }
- n = (address >> tlb_ps) & 0x1;/* Odd or even */
-
- tlb_entry = n ? tlb->tlb_entry1 : tlb->tlb_entry0;
- tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
- tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
- tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
- if (is_la64(env)) {
- tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
- tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
- tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
- tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
- } else {
- tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
- tlb_nx = 0;
- tlb_nr = 0;
- tlb_rplv = 0;
- }
-
- /* Remove sw bit between bit12 -- bit PS*/
- tlb_ppn = tlb_ppn & ~(((0x1UL << (tlb_ps - 12)) -1));
-
- /* Check access rights */
- if (!tlb_v) {
- return TLBRET_INVALID;
- }
-
- if (access_type == MMU_INST_FETCH && tlb_nx) {
- return TLBRET_XI;
- }
-
- if (access_type == MMU_DATA_LOAD && tlb_nr) {
- return TLBRET_RI;
- }
-
- if (((tlb_rplv == 0) && (plv > tlb_plv)) ||
- ((tlb_rplv == 1) && (plv != tlb_plv))) {
- return TLBRET_PE;
- }
-
- if ((access_type == MMU_DATA_STORE) && !tlb_d) {
- return TLBRET_DIRTY;
- }
-
- *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
- (address & MAKE_64BIT_MASK(0, tlb_ps));
- *prot = PAGE_READ;
- if (tlb_d) {
- *prot |= PAGE_WRITE;
- }
- if (!tlb_nx) {
- *prot |= PAGE_EXEC;
- }
- return TLBRET_MATCH;
-}
-
-/*
- * One tlb entry holds an adjacent odd/even pair, the vpn is the
- * content of the virtual page number divided by 2. So the
- * compare vpn is bit[47:15] for 16KiB page. while the vppn
- * field in tlb entry contains bit[47:13], so need adjust.
- * virt_vpn = vaddr[47:13]
- */
-static bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
- int *index)
-{
- LoongArchTLB *tlb;
- uint16_t csr_asid, tlb_asid, stlb_idx;
- uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps;
- int i, compare_shift;
- uint64_t vpn, tlb_vppn;
-
- 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 */
- compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
-
- /* Search STLB */
- 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) {
- 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);
-
- if ((tlb_g == 1 || tlb_asid == csr_asid) &&
- (vpn == (tlb_vppn >> compare_shift))) {
- *index = i * 256 + stlb_idx;
- return true;
- }
- }
- }
-
- /* Search MTLB */
- 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) {
- tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
- tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
- tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- 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) &&
- (vpn == (tlb_vppn >> compare_shift))) {
- *index = i;
- return true;
- }
- }
- }
- return false;
-}
-
-static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address,
- MMUAccessType access_type, int mmu_idx)
-{
- int index, match;
-
- match = loongarch_tlb_search(env, address, &index);
- if (match) {
- return loongarch_map_tlb_entry(env, physical, prot,
- address, access_type, index, mmu_idx);
- }
-
- return TLBRET_NOMATCH;
-}
-
-static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
- target_ulong dmw)
-{
- if (is_la64(env)) {
- return va & TARGET_VIRT_MASK;
- } else {
- uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
- return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
- (pseg << R_CSR_DMW_32_VSEG_SHIFT);
- }
-}
-
-static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address,
- MMUAccessType access_type, int mmu_idx)
-{
- int user_mode = mmu_idx == MMU_IDX_USER;
- int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
- 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);
-
- /* Check PG and DA */
- if (da & !pg) {
- *physical = address & TARGET_PHYS_MASK;
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return TLBRET_MATCH;
- }
-
- plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
- if (is_la64(env)) {
- base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
- } else {
- base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
- }
- /* 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);
- } else {
- base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
- }
- if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
- *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- return TLBRET_MATCH;
- }
- }
-
- /* Check valid extension */
- addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16);
- if (!(addr_high == 0 || addr_high == -1)) {
- return TLBRET_BADADDR;
- }
-
- /* Mapped address */
- return loongarch_map_address(env, physical, prot, address,
- access_type, mmu_idx);
-}
-
-hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
-{
- LoongArchCPU *cpu = LOONGARCH_CPU(cs);
- CPULoongArchState *env = &cpu->env;
- hwaddr phys_addr;
- int prot;
-
- if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD,
- cpu_mmu_index(env, false)) != 0) {
- return -1;
- }
- return phys_addr;
-}
-
static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
MMUAccessType access_type, int tlb_error)
{
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index db310f6022..e002e9aaf6 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -8,6 +8,7 @@ loongarch_ss.add(files(
loongarch_system_ss = ss.source_set()
loongarch_system_ss.add(files(
+ 'cpu_helper.c',
'loongarch-qmp-cmds.c',
'machine.c',
))
--
2.25.1
With qemu is compiled with option "--target-list=loongarch64-softmmu
--disable-tcg", it passes to run with "make check" command.
Also gdb debug for LoongArch kvm support depends on this.
Tested-by: Bibo Mao <maobibo@loongson.cn>
On 2024/1/25 下午2:14, Song Gao wrote:
> The cc->sysemu_ops->get_phys_page_debug() is NULL when
> KVM-only build. this patch fixes it.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/internals.h | 20 ++-
> target/loongarch/cpu.c | 2 -
> target/loongarch/cpu_helper.c | 231 ++++++++++++++++++++++++++++++
> target/loongarch/tcg/tlb_helper.c | 230 -----------------------------
> target/loongarch/meson.build | 1 +
> 5 files changed, 250 insertions(+), 234 deletions(-)
> create mode 100644 target/loongarch/cpu_helper.c
>
> diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
> index 0beb034748..a2fc54c8a7 100644
> --- a/target/loongarch/internals.h
> +++ b/target/loongarch/internals.h
> @@ -37,6 +37,17 @@ void restore_fp_status(CPULoongArchState *env);
> #endif
>
> #ifndef CONFIG_USER_ONLY
> +enum {
> + TLBRET_MATCH = 0,
> + TLBRET_BADADDR = 1,
> + TLBRET_NOMATCH = 2,
> + TLBRET_INVALID = 3,
> + TLBRET_DIRTY = 4,
> + TLBRET_RI = 5,
> + TLBRET_XI = 6,
> + TLBRET_PE = 7,
> +};
> +
> extern const VMStateDescription vmstate_loongarch_cpu;
>
> void loongarch_cpu_set_irq(void *opaque, int irq, int level);
> @@ -46,12 +57,17 @@ uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
> uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
> void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
> uint64_t value);
> +bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
> + int *index);
> +int get_physical_address(CPULoongArchState *env, hwaddr *physical,
> + int *prot, target_ulong address,
> + MMUAccessType access_type, int mmu_idx);
> +hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
> +
> #ifdef CONFIG_TCG
> bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> MMUAccessType access_type, int mmu_idx,
> bool probe, uintptr_t retaddr);
> -
> -hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
> #endif
> #endif /* !CONFIG_USER_ONLY */
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 064540397d..1e58c160ab 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -752,9 +752,7 @@ static struct TCGCPUOps loongarch_tcg_ops = {
> #include "hw/core/sysemu-cpu-ops.h"
>
> static const struct SysemuCPUOps loongarch_sysemu_ops = {
> -#ifdef CONFIG_TCG
> .get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
> -#endif
> };
>
> static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
> diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c
> new file mode 100644
> index 0000000000..f68d63f466
> --- /dev/null
> +++ b/target/loongarch/cpu_helper.c
> @@ -0,0 +1,231 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch CPU helpers for qemu
> + *
> + * Copyright (c) 2024 Loongson Technology Corporation Limited
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "internals.h"
> +#include "cpu-csr.h"
> +
> +static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
> + int *prot, target_ulong address,
> + int access_type, int index, int mmu_idx)
> +{
> + LoongArchTLB *tlb = &env->tlb[index];
> + uint64_t plv = mmu_idx;
> + uint64_t tlb_entry, tlb_ppn;
> + uint8_t tlb_ps, n, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv;
> +
> + if (index >= LOONGARCH_STLB) {
> + tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
> + } else {
> + tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
> + }
> + n = (address >> tlb_ps) & 0x1;/* Odd or even */
> +
> + tlb_entry = n ? tlb->tlb_entry1 : tlb->tlb_entry0;
> + tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
> + tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
> + tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
> + if (is_la64(env)) {
> + tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
> + tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
> + tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
> + tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
> + } else {
> + tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
> + tlb_nx = 0;
> + tlb_nr = 0;
> + tlb_rplv = 0;
> + }
> +
> + /* Remove sw bit between bit12 -- bit PS*/
> + tlb_ppn = tlb_ppn & ~(((0x1UL << (tlb_ps - 12)) -1));
> +
> + /* Check access rights */
> + if (!tlb_v) {
> + return TLBRET_INVALID;
> + }
> +
> + if (access_type == MMU_INST_FETCH && tlb_nx) {
> + return TLBRET_XI;
> + }
> +
> + if (access_type == MMU_DATA_LOAD && tlb_nr) {
> + return TLBRET_RI;
> + }
> +
> + if (((tlb_rplv == 0) && (plv > tlb_plv)) ||
> + ((tlb_rplv == 1) && (plv != tlb_plv))) {
> + return TLBRET_PE;
> + }
> +
> + if ((access_type == MMU_DATA_STORE) && !tlb_d) {
> + return TLBRET_DIRTY;
> + }
> +
> + *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
> + (address & MAKE_64BIT_MASK(0, tlb_ps));
> + *prot = PAGE_READ;
> + if (tlb_d) {
> + *prot |= PAGE_WRITE;
> + }
> + if (!tlb_nx) {
> + *prot |= PAGE_EXEC;
> + }
> + return TLBRET_MATCH;
> +}
> +
> +/*
> + * One tlb entry holds an adjacent odd/even pair, the vpn is the
> + * content of the virtual page number divided by 2. So the
> + * compare vpn is bit[47:15] for 16KiB page. while the vppn
> + * field in tlb entry contains bit[47:13], so need adjust.
> + * virt_vpn = vaddr[47:13]
> + */
> +bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
> + int *index)
> +{
> + LoongArchTLB *tlb;
> + uint16_t csr_asid, tlb_asid, stlb_idx;
> + uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps;
> + int i, compare_shift;
> + uint64_t vpn, tlb_vppn;
> +
> + 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 */
> + compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
> +
> + /* Search STLB */
> + 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) {
> + 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);
> +
> + if ((tlb_g == 1 || tlb_asid == csr_asid) &&
> + (vpn == (tlb_vppn >> compare_shift))) {
> + *index = i * 256 + stlb_idx;
> + return true;
> + }
> + }
> + }
> +
> + /* Search MTLB */
> + 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) {
> + tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
> + tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
> + tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
> + 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) &&
> + (vpn == (tlb_vppn >> compare_shift))) {
> + *index = i;
> + return true;
> + }
> + }
> + }
> + return false;
> +}
> +
> +static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
> + int *prot, target_ulong address,
> + MMUAccessType access_type, int mmu_idx)
> +{
> + int index, match;
> +
> + match = loongarch_tlb_search(env, address, &index);
> + if (match) {
> + return loongarch_map_tlb_entry(env, physical, prot,
> + address, access_type, index, mmu_idx);
> + }
> +
> + return TLBRET_NOMATCH;
> +}
> +
> +static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
> + target_ulong dmw)
> +{
> + if (is_la64(env)) {
> + return va & TARGET_VIRT_MASK;
> + } else {
> + uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
> + return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
> + (pseg << R_CSR_DMW_32_VSEG_SHIFT);
> + }
> +}
> +
> +int get_physical_address(CPULoongArchState *env, hwaddr *physical,
> + int *prot, target_ulong address,
> + MMUAccessType access_type, int mmu_idx)
> +{
> + int user_mode = mmu_idx == MMU_IDX_USER;
> + int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
> + 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);
> +
> + /* Check PG and DA */
> + if (da & !pg) {
> + *physical = address & TARGET_PHYS_MASK;
> + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> + return TLBRET_MATCH;
> + }
> +
> + plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
> + if (is_la64(env)) {
> + base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
> + } else {
> + base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
> + }
> + /* 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);
> + } else {
> + base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
> + }
> + if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
> + *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
> + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> + return TLBRET_MATCH;
> + }
> + }
> +
> + /* Check valid extension */
> + addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16);
> + if (!(addr_high == 0 || addr_high == -1)) {
> + return TLBRET_BADADDR;
> + }
> +
> + /* Mapped address */
> + return loongarch_map_address(env, physical, prot, address,
> + access_type, mmu_idx);
> +}
> +
> +hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
> +{
> + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> + CPULoongArchState *env = &cpu->env;
> + hwaddr phys_addr;
> + int prot;
> +
> + if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD,
> + cpu_mmu_index(env, false)) != 0) {
> + return -1;
> + }
> + return phys_addr;
> +}
> diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
> index 449043c68b..804ab7a263 100644
> --- a/target/loongarch/tcg/tlb_helper.c
> +++ b/target/loongarch/tcg/tlb_helper.c
> @@ -17,236 +17,6 @@
> #include "exec/log.h"
> #include "cpu-csr.h"
>
> -enum {
> - TLBRET_MATCH = 0,
> - TLBRET_BADADDR = 1,
> - TLBRET_NOMATCH = 2,
> - TLBRET_INVALID = 3,
> - TLBRET_DIRTY = 4,
> - TLBRET_RI = 5,
> - TLBRET_XI = 6,
> - TLBRET_PE = 7,
> -};
> -
> -static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
> - int *prot, target_ulong address,
> - int access_type, int index, int mmu_idx)
> -{
> - LoongArchTLB *tlb = &env->tlb[index];
> - uint64_t plv = mmu_idx;
> - uint64_t tlb_entry, tlb_ppn;
> - uint8_t tlb_ps, n, tlb_v, tlb_d, tlb_plv, tlb_nx, tlb_nr, tlb_rplv;
> -
> - if (index >= LOONGARCH_STLB) {
> - tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
> - } else {
> - tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS);
> - }
> - n = (address >> tlb_ps) & 0x1;/* Odd or even */
> -
> - tlb_entry = n ? tlb->tlb_entry1 : tlb->tlb_entry0;
> - tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
> - tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
> - tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
> - if (is_la64(env)) {
> - tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
> - tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
> - tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
> - tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
> - } else {
> - tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
> - tlb_nx = 0;
> - tlb_nr = 0;
> - tlb_rplv = 0;
> - }
> -
> - /* Remove sw bit between bit12 -- bit PS*/
> - tlb_ppn = tlb_ppn & ~(((0x1UL << (tlb_ps - 12)) -1));
> -
> - /* Check access rights */
> - if (!tlb_v) {
> - return TLBRET_INVALID;
> - }
> -
> - if (access_type == MMU_INST_FETCH && tlb_nx) {
> - return TLBRET_XI;
> - }
> -
> - if (access_type == MMU_DATA_LOAD && tlb_nr) {
> - return TLBRET_RI;
> - }
> -
> - if (((tlb_rplv == 0) && (plv > tlb_plv)) ||
> - ((tlb_rplv == 1) && (plv != tlb_plv))) {
> - return TLBRET_PE;
> - }
> -
> - if ((access_type == MMU_DATA_STORE) && !tlb_d) {
> - return TLBRET_DIRTY;
> - }
> -
> - *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
> - (address & MAKE_64BIT_MASK(0, tlb_ps));
> - *prot = PAGE_READ;
> - if (tlb_d) {
> - *prot |= PAGE_WRITE;
> - }
> - if (!tlb_nx) {
> - *prot |= PAGE_EXEC;
> - }
> - return TLBRET_MATCH;
> -}
> -
> -/*
> - * One tlb entry holds an adjacent odd/even pair, the vpn is the
> - * content of the virtual page number divided by 2. So the
> - * compare vpn is bit[47:15] for 16KiB page. while the vppn
> - * field in tlb entry contains bit[47:13], so need adjust.
> - * virt_vpn = vaddr[47:13]
> - */
> -static bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr,
> - int *index)
> -{
> - LoongArchTLB *tlb;
> - uint16_t csr_asid, tlb_asid, stlb_idx;
> - uint8_t tlb_e, tlb_ps, tlb_g, stlb_ps;
> - int i, compare_shift;
> - uint64_t vpn, tlb_vppn;
> -
> - 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 */
> - compare_shift = stlb_ps + 1 - R_TLB_MISC_VPPN_SHIFT;
> -
> - /* Search STLB */
> - 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) {
> - 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);
> -
> - if ((tlb_g == 1 || tlb_asid == csr_asid) &&
> - (vpn == (tlb_vppn >> compare_shift))) {
> - *index = i * 256 + stlb_idx;
> - return true;
> - }
> - }
> - }
> -
> - /* Search MTLB */
> - 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) {
> - tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
> - tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
> - tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
> - 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) &&
> - (vpn == (tlb_vppn >> compare_shift))) {
> - *index = i;
> - return true;
> - }
> - }
> - }
> - return false;
> -}
> -
> -static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
> - int *prot, target_ulong address,
> - MMUAccessType access_type, int mmu_idx)
> -{
> - int index, match;
> -
> - match = loongarch_tlb_search(env, address, &index);
> - if (match) {
> - return loongarch_map_tlb_entry(env, physical, prot,
> - address, access_type, index, mmu_idx);
> - }
> -
> - return TLBRET_NOMATCH;
> -}
> -
> -static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
> - target_ulong dmw)
> -{
> - if (is_la64(env)) {
> - return va & TARGET_VIRT_MASK;
> - } else {
> - uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
> - return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
> - (pseg << R_CSR_DMW_32_VSEG_SHIFT);
> - }
> -}
> -
> -static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
> - int *prot, target_ulong address,
> - MMUAccessType access_type, int mmu_idx)
> -{
> - int user_mode = mmu_idx == MMU_IDX_USER;
> - int kernel_mode = mmu_idx == MMU_IDX_KERNEL;
> - 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);
> -
> - /* Check PG and DA */
> - if (da & !pg) {
> - *physical = address & TARGET_PHYS_MASK;
> - *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> - return TLBRET_MATCH;
> - }
> -
> - plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
> - if (is_la64(env)) {
> - base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
> - } else {
> - base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
> - }
> - /* 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);
> - } else {
> - base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
> - }
> - if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
> - *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
> - *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> - return TLBRET_MATCH;
> - }
> - }
> -
> - /* Check valid extension */
> - addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16);
> - if (!(addr_high == 0 || addr_high == -1)) {
> - return TLBRET_BADADDR;
> - }
> -
> - /* Mapped address */
> - return loongarch_map_address(env, physical, prot, address,
> - access_type, mmu_idx);
> -}
> -
> -hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
> -{
> - LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> - CPULoongArchState *env = &cpu->env;
> - hwaddr phys_addr;
> - int prot;
> -
> - if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD,
> - cpu_mmu_index(env, false)) != 0) {
> - return -1;
> - }
> - return phys_addr;
> -}
> -
> static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
> MMUAccessType access_type, int tlb_error)
> {
> diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
> index db310f6022..e002e9aaf6 100644
> --- a/target/loongarch/meson.build
> +++ b/target/loongarch/meson.build
> @@ -8,6 +8,7 @@ loongarch_ss.add(files(
>
> loongarch_system_ss = ss.source_set()
> loongarch_system_ss.add(files(
> + 'cpu_helper.c',
> 'loongarch-qmp-cmds.c',
> 'machine.c',
> ))
>
© 2016 - 2026 Red Hat, Inc.