loongarch queue
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ5M4AwAKCRAfewwSUazn 0aJAAP45/9qfbGSYiMCrBXpRFlyvtRN+GEXHEsERfk9Q1V+tQgEA/mMiUEcyc/xc Z1Z27cDoqUFRhPmxbd6/KyTGHzo2+As= =Zanw -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20250124' of https://gitlab.com/bibo-mao/qemu into staging loongarch queue # -----BEGIN PGP SIGNATURE----- # # iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ5M4AwAKCRAfewwSUazn # 0aJAAP45/9qfbGSYiMCrBXpRFlyvtRN+GEXHEsERfk9Q1V+tQgEA/mMiUEcyc/xc # Z1Z27cDoqUFRhPmxbd6/KyTGHzo2+As= # =Zanw # -----END PGP SIGNATURE----- # gpg: Signature made Fri 24 Jan 2025 01:49:39 EST # gpg: using EDDSA key 0D8642A3A2659F80B0B3D1A41F7B0C1251ACE7D1 # gpg: Good signature from "bibo mao <maobibo@loongson.cn>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 7044 3A00 19C0 E97A 31C7 13C4 8E86 8FB7 A176 9D4C # Subkey fingerprint: 0D86 42A3 A265 9F80 B0B3 D1A4 1F7B 0C12 51AC E7D1 * tag 'pull-loongarch-20250124' of https://gitlab.com/bibo-mao/qemu: target/loongarch: Dump all generic CSR registers target/loongarch: Set unused flag with CSR registers target/loongarch: Add common source file for CSR register target/loongarch: Add common header file for CSR registers target/loongarch: Add generic csr function type target/loongarch: Remove static CSR function setting target/loongarch: Add dynamic function access with CSR register Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
8f9cb50fe6
@ -19,7 +19,7 @@
|
||||
#include "cpu.h"
|
||||
#include "internals.h"
|
||||
#include "fpu/softfloat-helpers.h"
|
||||
#include "cpu-csr.h"
|
||||
#include "csr.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "system/reset.h"
|
||||
#endif
|
||||
@ -375,6 +375,33 @@ static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch)
|
||||
return MMU_DA_IDX;
|
||||
}
|
||||
|
||||
static void loongarch_la464_init_csr(Object *obj)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static bool initialized;
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
int i, num;
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
num = FIELD_EX64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM);
|
||||
for (i = num; i < 16; i++) {
|
||||
set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED);
|
||||
}
|
||||
set_csr_flag(LOONGARCH_CSR_IMPCTL1, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_IMPCTL2, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_MERRCTL, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_MERRINFO1, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_MERRINFO2, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_MERRENTRY, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_MERRERA, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_MERRSAVE, CSRFL_UNUSED);
|
||||
set_csr_flag(LOONGARCH_CSR_CTAG, CSRFL_UNUSED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void loongarch_la464_initfn(Object *obj)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||
@ -470,6 +497,7 @@ static void loongarch_la464_initfn(Object *obj)
|
||||
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);
|
||||
|
||||
loongarch_la464_init_csr(obj);
|
||||
loongarch_cpu_post_init(obj);
|
||||
}
|
||||
|
||||
@ -765,6 +793,54 @@ static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
|
||||
return oc;
|
||||
}
|
||||
|
||||
static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
CPULoongArchState *env = cpu_env(cs);
|
||||
CSRInfo *csr_info;
|
||||
int64_t *addr;
|
||||
int i, j, len, col = 0;
|
||||
|
||||
qemu_fprintf(f, "\n");
|
||||
|
||||
/* Dump all generic CSR register */
|
||||
for (i = 0; i < LOONGARCH_CSR_DBG; i++) {
|
||||
csr_info = get_csr(i);
|
||||
if (!csr_info || (csr_info->flags & CSRFL_UNUSED)) {
|
||||
if (i == (col + 3)) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((i > (col + 3)) || (i == col)) {
|
||||
col = i & ~3;
|
||||
qemu_fprintf(f, " CSR%03d:", col);
|
||||
}
|
||||
|
||||
addr = (void *)env + csr_info->offset;
|
||||
qemu_fprintf(f, " %s ", csr_info->name);
|
||||
len = strlen(csr_info->name);
|
||||
for (; len < 6; len++) {
|
||||
qemu_fprintf(f, " ");
|
||||
}
|
||||
|
||||
qemu_fprintf(f, "%" PRIx64, *addr);
|
||||
j = find_last_bit((void *)addr, BITS_PER_LONG) & (BITS_PER_LONG - 1);
|
||||
len += j / 4 + 1;
|
||||
for (; len < 22; len++) {
|
||||
qemu_fprintf(f, " ");
|
||||
}
|
||||
|
||||
if (i == (col + 3)) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
qemu_fprintf(f, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
{
|
||||
CPULoongArchState *env = cpu_env(cs);
|
||||
@ -784,22 +860,8 @@ static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
|
||||
qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
|
||||
qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
|
||||
qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
|
||||
qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
|
||||
qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
|
||||
qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
|
||||
qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
|
||||
qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
|
||||
" PRCFG3=%016" PRIx64 "\n",
|
||||
env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
|
||||
qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
|
||||
qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
|
||||
qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
|
||||
qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG);
|
||||
qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL);
|
||||
/* csr */
|
||||
loongarch_cpu_dump_csr(cs, f);
|
||||
|
||||
/* fpr */
|
||||
if (flags & CPU_DUMP_FPU) {
|
||||
|
129
target/loongarch/csr.c
Normal file
129
target/loongarch/csr.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2025 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "csr.h"
|
||||
|
||||
#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \
|
||||
[LOONGARCH_CSR_##NAME] = { \
|
||||
.name = (stringify(NAME)), \
|
||||
.offset = offsetof(CPULoongArchState, 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]), \
|
||||
.flags = 0, .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)
|
||||
|
||||
static CSRInfo csr_info[] = {
|
||||
CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
|
||||
CSR_OFF(PRMD),
|
||||
CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB),
|
||||
CSR_OFF_FLAGS(MISC, CSRFL_READONLY),
|
||||
CSR_OFF(ECFG),
|
||||
CSR_OFF_FLAGS(ESTAT, CSRFL_EXITTB),
|
||||
CSR_OFF(ERA),
|
||||
CSR_OFF(BADV),
|
||||
CSR_OFF_FLAGS(BADI, CSRFL_READONLY),
|
||||
CSR_OFF(EENTRY),
|
||||
CSR_OFF(TLBIDX),
|
||||
CSR_OFF(TLBEHI),
|
||||
CSR_OFF(TLBELO0),
|
||||
CSR_OFF(TLBELO1),
|
||||
CSR_OFF_FLAGS(ASID, CSRFL_EXITTB),
|
||||
CSR_OFF(PGDL),
|
||||
CSR_OFF(PGDH),
|
||||
CSR_OFF_FLAGS(PGD, CSRFL_READONLY),
|
||||
CSR_OFF(PWCL),
|
||||
CSR_OFF(PWCH),
|
||||
CSR_OFF(STLBPS),
|
||||
CSR_OFF(RVACFG),
|
||||
CSR_OFF_FLAGS(CPUID, CSRFL_READONLY),
|
||||
CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY),
|
||||
CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY),
|
||||
CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY),
|
||||
CSR_OFF_ARRAY(SAVE, 0),
|
||||
CSR_OFF_ARRAY(SAVE, 1),
|
||||
CSR_OFF_ARRAY(SAVE, 2),
|
||||
CSR_OFF_ARRAY(SAVE, 3),
|
||||
CSR_OFF_ARRAY(SAVE, 4),
|
||||
CSR_OFF_ARRAY(SAVE, 5),
|
||||
CSR_OFF_ARRAY(SAVE, 6),
|
||||
CSR_OFF_ARRAY(SAVE, 7),
|
||||
CSR_OFF_ARRAY(SAVE, 8),
|
||||
CSR_OFF_ARRAY(SAVE, 9),
|
||||
CSR_OFF_ARRAY(SAVE, 10),
|
||||
CSR_OFF_ARRAY(SAVE, 11),
|
||||
CSR_OFF_ARRAY(SAVE, 12),
|
||||
CSR_OFF_ARRAY(SAVE, 13),
|
||||
CSR_OFF_ARRAY(SAVE, 14),
|
||||
CSR_OFF_ARRAY(SAVE, 15),
|
||||
CSR_OFF(TID),
|
||||
CSR_OFF_FLAGS(TCFG, CSRFL_IO),
|
||||
CSR_OFF_FLAGS(TVAL, CSRFL_READONLY | CSRFL_IO),
|
||||
CSR_OFF(CNTC),
|
||||
CSR_OFF_FLAGS(TICLR, CSRFL_IO),
|
||||
CSR_OFF(LLBCTL),
|
||||
CSR_OFF(IMPCTL1),
|
||||
CSR_OFF(IMPCTL2),
|
||||
CSR_OFF(TLBRENTRY),
|
||||
CSR_OFF(TLBRBADV),
|
||||
CSR_OFF(TLBRERA),
|
||||
CSR_OFF(TLBRSAVE),
|
||||
CSR_OFF(TLBRELO0),
|
||||
CSR_OFF(TLBRELO1),
|
||||
CSR_OFF(TLBREHI),
|
||||
CSR_OFF(TLBRPRMD),
|
||||
CSR_OFF(MERRCTL),
|
||||
CSR_OFF(MERRINFO1),
|
||||
CSR_OFF(MERRINFO2),
|
||||
CSR_OFF(MERRENTRY),
|
||||
CSR_OFF(MERRERA),
|
||||
CSR_OFF(MERRSAVE),
|
||||
CSR_OFF(CTAG),
|
||||
CSR_OFF_ARRAY(DMW, 0),
|
||||
CSR_OFF_ARRAY(DMW, 1),
|
||||
CSR_OFF_ARRAY(DMW, 2),
|
||||
CSR_OFF_ARRAY(DMW, 3),
|
||||
CSR_OFF(DBG),
|
||||
CSR_OFF(DERA),
|
||||
CSR_OFF(DSAVE),
|
||||
};
|
||||
|
||||
CSRInfo *get_csr(unsigned int csr_num)
|
||||
{
|
||||
CSRInfo *csr;
|
||||
|
||||
if (csr_num >= ARRAY_SIZE(csr_info)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
csr = &csr_info[csr_num];
|
||||
if (csr->offset == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return csr;
|
||||
}
|
||||
|
||||
bool set_csr_flag(unsigned int csr_num, int flag)
|
||||
{
|
||||
CSRInfo *csr;
|
||||
|
||||
csr = get_csr(csr_num);
|
||||
if (!csr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
csr->flags |= flag;
|
||||
return true;
|
||||
}
|
29
target/loongarch/csr.h
Normal file
29
target/loongarch/csr.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2025 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef TARGET_LOONGARCH_CSR_H
|
||||
#define TARGET_LOONGARCH_CSR_H
|
||||
|
||||
#include "cpu-csr.h"
|
||||
|
||||
typedef void (*GenCSRFunc)(void);
|
||||
enum {
|
||||
CSRFL_READONLY = (1 << 0),
|
||||
CSRFL_EXITTB = (1 << 1),
|
||||
CSRFL_IO = (1 << 2),
|
||||
CSRFL_UNUSED = (1 << 3),
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int offset;
|
||||
int flags;
|
||||
GenCSRFunc readfn;
|
||||
GenCSRFunc writefn;
|
||||
} CSRInfo;
|
||||
|
||||
CSRInfo *get_csr(unsigned int csr_num);
|
||||
bool set_csr_flag(unsigned int csr_num, int flag);
|
||||
#endif /* TARGET_LOONGARCH_CSR_H */
|
@ -10,6 +10,7 @@ loongarch_system_ss = ss.source_set()
|
||||
loongarch_system_ss.add(files(
|
||||
'arch_dump.c',
|
||||
'cpu_helper.c',
|
||||
'csr.c',
|
||||
'loongarch-qmp-cmds.c',
|
||||
'machine.c',
|
||||
))
|
||||
|
@ -5,7 +5,7 @@
|
||||
* LoongArch translation routines for the privileged instructions.
|
||||
*/
|
||||
|
||||
#include "cpu-csr.h"
|
||||
#include "csr.h"
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
||||
@ -45,112 +45,6 @@ GEN_FALSE_TRANS(idle)
|
||||
typedef void (*GenCSRRead)(TCGv dest, TCGv_ptr env);
|
||||
typedef void (*GenCSRWrite)(TCGv dest, TCGv_ptr env, TCGv src);
|
||||
|
||||
typedef struct {
|
||||
int offset;
|
||||
int flags;
|
||||
GenCSRRead readfn;
|
||||
GenCSRWrite writefn;
|
||||
} CSRInfo;
|
||||
|
||||
enum {
|
||||
CSRFL_READONLY = (1 << 0),
|
||||
CSRFL_EXITTB = (1 << 1),
|
||||
CSRFL_IO = (1 << 2),
|
||||
};
|
||||
|
||||
#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \
|
||||
[LOONGARCH_CSR_##NAME] = { \
|
||||
.offset = offsetof(CPULoongArchState, CSR_##NAME), \
|
||||
.flags = FL, .readfn = RD, .writefn = WR \
|
||||
}
|
||||
|
||||
#define CSR_OFF_ARRAY(NAME, N) \
|
||||
[LOONGARCH_CSR_##NAME(N)] = { \
|
||||
.offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \
|
||||
.flags = 0, .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)
|
||||
|
||||
static const CSRInfo csr_info[] = {
|
||||
CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
|
||||
CSR_OFF(PRMD),
|
||||
CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB),
|
||||
CSR_OFF_FLAGS(MISC, CSRFL_READONLY),
|
||||
CSR_OFF(ECFG),
|
||||
CSR_OFF_FUNCS(ESTAT, CSRFL_EXITTB, NULL, gen_helper_csrwr_estat),
|
||||
CSR_OFF(ERA),
|
||||
CSR_OFF(BADV),
|
||||
CSR_OFF_FLAGS(BADI, CSRFL_READONLY),
|
||||
CSR_OFF(EENTRY),
|
||||
CSR_OFF(TLBIDX),
|
||||
CSR_OFF(TLBEHI),
|
||||
CSR_OFF(TLBELO0),
|
||||
CSR_OFF(TLBELO1),
|
||||
CSR_OFF_FUNCS(ASID, CSRFL_EXITTB, NULL, gen_helper_csrwr_asid),
|
||||
CSR_OFF(PGDL),
|
||||
CSR_OFF(PGDH),
|
||||
CSR_OFF_FUNCS(PGD, CSRFL_READONLY, gen_helper_csrrd_pgd, NULL),
|
||||
CSR_OFF_FUNCS(PWCL, 0, NULL, gen_helper_csrwr_pwcl),
|
||||
CSR_OFF(PWCH),
|
||||
CSR_OFF(STLBPS),
|
||||
CSR_OFF(RVACFG),
|
||||
CSR_OFF_FUNCS(CPUID, CSRFL_READONLY, gen_helper_csrrd_cpuid, NULL),
|
||||
CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY),
|
||||
CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY),
|
||||
CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY),
|
||||
CSR_OFF_ARRAY(SAVE, 0),
|
||||
CSR_OFF_ARRAY(SAVE, 1),
|
||||
CSR_OFF_ARRAY(SAVE, 2),
|
||||
CSR_OFF_ARRAY(SAVE, 3),
|
||||
CSR_OFF_ARRAY(SAVE, 4),
|
||||
CSR_OFF_ARRAY(SAVE, 5),
|
||||
CSR_OFF_ARRAY(SAVE, 6),
|
||||
CSR_OFF_ARRAY(SAVE, 7),
|
||||
CSR_OFF_ARRAY(SAVE, 8),
|
||||
CSR_OFF_ARRAY(SAVE, 9),
|
||||
CSR_OFF_ARRAY(SAVE, 10),
|
||||
CSR_OFF_ARRAY(SAVE, 11),
|
||||
CSR_OFF_ARRAY(SAVE, 12),
|
||||
CSR_OFF_ARRAY(SAVE, 13),
|
||||
CSR_OFF_ARRAY(SAVE, 14),
|
||||
CSR_OFF_ARRAY(SAVE, 15),
|
||||
CSR_OFF(TID),
|
||||
CSR_OFF_FUNCS(TCFG, CSRFL_IO, NULL, gen_helper_csrwr_tcfg),
|
||||
CSR_OFF_FUNCS(TVAL, CSRFL_READONLY | CSRFL_IO, gen_helper_csrrd_tval, NULL),
|
||||
CSR_OFF(CNTC),
|
||||
CSR_OFF_FUNCS(TICLR, CSRFL_IO, NULL, gen_helper_csrwr_ticlr),
|
||||
CSR_OFF(LLBCTL),
|
||||
CSR_OFF(IMPCTL1),
|
||||
CSR_OFF(IMPCTL2),
|
||||
CSR_OFF(TLBRENTRY),
|
||||
CSR_OFF(TLBRBADV),
|
||||
CSR_OFF(TLBRERA),
|
||||
CSR_OFF(TLBRSAVE),
|
||||
CSR_OFF(TLBRELO0),
|
||||
CSR_OFF(TLBRELO1),
|
||||
CSR_OFF(TLBREHI),
|
||||
CSR_OFF(TLBRPRMD),
|
||||
CSR_OFF(MERRCTL),
|
||||
CSR_OFF(MERRINFO1),
|
||||
CSR_OFF(MERRINFO2),
|
||||
CSR_OFF(MERRENTRY),
|
||||
CSR_OFF(MERRERA),
|
||||
CSR_OFF(MERRSAVE),
|
||||
CSR_OFF(CTAG),
|
||||
CSR_OFF_ARRAY(DMW, 0),
|
||||
CSR_OFF_ARRAY(DMW, 1),
|
||||
CSR_OFF_ARRAY(DMW, 2),
|
||||
CSR_OFF_ARRAY(DMW, 3),
|
||||
CSR_OFF(DBG),
|
||||
CSR_OFF(DERA),
|
||||
CSR_OFF(DSAVE),
|
||||
};
|
||||
|
||||
static bool check_plv(DisasContext *ctx)
|
||||
{
|
||||
if (ctx->plv == MMU_PLV_USER) {
|
||||
@ -160,20 +54,37 @@ static bool check_plv(DisasContext *ctx)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const CSRInfo *get_csr(unsigned csr_num)
|
||||
static bool set_csr_trans_func(unsigned int csr_num, GenCSRRead readfn,
|
||||
GenCSRWrite writefn)
|
||||
{
|
||||
const CSRInfo *csr;
|
||||
CSRInfo *csr;
|
||||
|
||||
if (csr_num >= ARRAY_SIZE(csr_info)) {
|
||||
return NULL;
|
||||
csr = get_csr(csr_num);
|
||||
if (!csr) {
|
||||
return false;
|
||||
}
|
||||
csr = &csr_info[csr_num];
|
||||
if (csr->offset == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return csr;
|
||||
|
||||
csr->readfn = (GenCSRFunc)readfn;
|
||||
csr->writefn = (GenCSRFunc)writefn;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define SET_CSR_FUNC(NAME, read, write) \
|
||||
set_csr_trans_func(LOONGARCH_CSR_##NAME, read, write)
|
||||
|
||||
void loongarch_csr_translate_init(void)
|
||||
{
|
||||
SET_CSR_FUNC(ESTAT, NULL, gen_helper_csrwr_estat);
|
||||
SET_CSR_FUNC(ASID, NULL, gen_helper_csrwr_asid);
|
||||
SET_CSR_FUNC(PGD, gen_helper_csrrd_pgd, NULL);
|
||||
SET_CSR_FUNC(PWCL, NULL, gen_helper_csrwr_pwcl);
|
||||
SET_CSR_FUNC(CPUID, gen_helper_csrrd_cpuid, NULL);
|
||||
SET_CSR_FUNC(TCFG, NULL, gen_helper_csrwr_tcfg);
|
||||
SET_CSR_FUNC(TVAL, gen_helper_csrrd_tval, NULL);
|
||||
SET_CSR_FUNC(TICLR, NULL, gen_helper_csrwr_ticlr);
|
||||
}
|
||||
#undef SET_CSR_FUNC
|
||||
|
||||
static bool check_csr_flags(DisasContext *ctx, const CSRInfo *csr, bool write)
|
||||
{
|
||||
if ((csr->flags & CSRFL_READONLY) && write) {
|
||||
@ -191,6 +102,7 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a)
|
||||
{
|
||||
TCGv dest;
|
||||
const CSRInfo *csr;
|
||||
GenCSRRead readfn;
|
||||
|
||||
if (check_plv(ctx)) {
|
||||
return false;
|
||||
@ -202,8 +114,9 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a)
|
||||
} else {
|
||||
check_csr_flags(ctx, csr, false);
|
||||
dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
if (csr->readfn) {
|
||||
csr->readfn(dest, tcg_env);
|
||||
readfn = (GenCSRRead)csr->readfn;
|
||||
if (readfn) {
|
||||
readfn(dest, tcg_env);
|
||||
} else {
|
||||
tcg_gen_ld_tl(dest, tcg_env, csr->offset);
|
||||
}
|
||||
@ -216,6 +129,7 @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a)
|
||||
{
|
||||
TCGv dest, src1;
|
||||
const CSRInfo *csr;
|
||||
GenCSRWrite writefn;
|
||||
|
||||
if (check_plv(ctx)) {
|
||||
return false;
|
||||
@ -231,9 +145,10 @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a)
|
||||
return false;
|
||||
}
|
||||
src1 = gpr_src(ctx, a->rd, EXT_NONE);
|
||||
if (csr->writefn) {
|
||||
writefn = (GenCSRWrite)csr->writefn;
|
||||
if (writefn) {
|
||||
dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
csr->writefn(dest, tcg_env, src1);
|
||||
writefn(dest, tcg_env, src1);
|
||||
} else {
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_ld_tl(dest, tcg_env, csr->offset);
|
||||
@ -247,6 +162,7 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
|
||||
{
|
||||
TCGv src1, mask, oldv, newv, temp;
|
||||
const CSRInfo *csr;
|
||||
GenCSRWrite writefn;
|
||||
|
||||
if (check_plv(ctx)) {
|
||||
return false;
|
||||
@ -277,8 +193,9 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
|
||||
tcg_gen_andc_tl(temp, oldv, mask);
|
||||
tcg_gen_or_tl(newv, newv, temp);
|
||||
|
||||
if (csr->writefn) {
|
||||
csr->writefn(oldv, tcg_env, newv);
|
||||
writefn = (GenCSRWrite)csr->writefn;
|
||||
if (writefn) {
|
||||
writefn(oldv, tcg_env, newv);
|
||||
} else {
|
||||
tcg_gen_st_tl(newv, tcg_env, csr->offset);
|
||||
}
|
||||
|
12
target/loongarch/tcg/tcg_loongarch.h
Normal file
12
target/loongarch/tcg/tcg_loongarch.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* QEMU LoongArch TCG interface
|
||||
*
|
||||
* Copyright (c) 2025 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef TARGET_LOONGARCH_TCG_LOONGARCH_H
|
||||
#define TARGET_LOONGARCH_TCG_LOONGARCH_H
|
||||
|
||||
void loongarch_csr_translate_init(void);
|
||||
|
||||
#endif /* TARGET_LOONGARCH_TCG_LOONGARCH_H */
|
@ -16,6 +16,7 @@
|
||||
#include "exec/log.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "tcg_loongarch.h"
|
||||
#include "translate.h"
|
||||
#include "internals.h"
|
||||
#include "vec.h"
|
||||
@ -358,4 +359,8 @@ void loongarch_translate_init(void)
|
||||
offsetof(CPULoongArchState, lladdr), "lladdr");
|
||||
cpu_llval = tcg_global_mem_new(tcg_env,
|
||||
offsetof(CPULoongArchState, llval), "llval");
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
loongarch_csr_translate_init();
|
||||
#endif
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user