diff mbox series

[RFC,v4,02/30] target/loongarch: Add CSR registers definition

Message ID 20220108091419.2027710-3-yangxiaojuan@loongson.cn (mailing list archive)
State New, archived
Headers show
Series Add LoongArch softmmu support. | expand

Commit Message

Xiaojuan Yang Jan. 8, 2022, 9:13 a.m. UTC
1.Define All the CSR registers and its field.
2.Set some default csr values.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu-csr.h | 236 +++++++++++++++++++++++++++++++++++++
 target/loongarch/cpu.c     |  35 ++++++
 target/loongarch/cpu.h     |  57 +++++++++
 3 files changed, 328 insertions(+)
 create mode 100644 target/loongarch/cpu-csr.h

Comments

WANG Xuerui Jan. 9, 2022, 9:25 a.m. UTC | #1
On 1/8/22 17:13, Xiaojuan Yang wrote:
> 1.Define All the CSR registers and its field.
> 2.Set some default csr values.
Unnecessary explanation; the code addition itself should be obvious 
enough as to its intention.
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> ---
>   target/loongarch/cpu-csr.h | 236 +++++++++++++++++++++++++++++++++++++
>   target/loongarch/cpu.c     |  35 ++++++
>   target/loongarch/cpu.h     |  57 +++++++++
>   3 files changed, 328 insertions(+)
>   create mode 100644 target/loongarch/cpu-csr.h
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> new file mode 100644
> index 0000000000..7a57b7ea36
> --- /dev/null
> +++ b/target/loongarch/cpu-csr.h
> @@ -0,0 +1,236 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch CPU CSR registers
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#ifndef LOONGARCH_CPU_CSR_H
> +#define LOONGARCH_CPU_CSR_H
> +
> +/* Base on: kernal: arch/loongarch/include/asm/loongarch.h */
"Based on kernel definitions: ..."
> +
> +/* Basic CSR register */
> +#define LOONGARCH_CSR_CRMD           0x0 /* Current mode info */
Do we really need all these ad-hoc translated names when people could 
easily be pointed to the manuals? This way translation errors can be 
avoided, such as...
> +FIELD(CSR_CRMD, PLV, 0, 2)
> +FIELD(CSR_CRMD, IE, 2, 1)
> +FIELD(CSR_CRMD, DA, 3, 1)
> +FIELD(CSR_CRMD, PG, 4, 1)
> +FIELD(CSR_CRMD, DATF, 5, 2)
> +FIELD(CSR_CRMD, DATM, 7, 2)
> +FIELD(CSR_CRMD, WE, 9, 1)
> +
> +#define LOONGARCH_CSR_PRMD           0x1 /* Prev-exception mode info */
> +FIELD(CSR_PRMD, PPLV, 0, 2)
> +FIELD(CSR_PRMD, PIE, 2, 1)
> +FIELD(CSR_PRMD, PWE, 3, 1)
> +
> +#define LOONGARCH_CSR_EUEN           0x2 /* Extended unit enable */
> +FIELD(CSR_EUEN, FPE, 0, 1)
> +FIELD(CSR_EUEN, SXE, 1, 1)
> +FIELD(CSR_EUEN, ASXE, 2, 1)
> +FIELD(CSR_EUEN, BTE, 3, 1)
> +
> +#define LOONGARCH_CSR_MISC           0x3 /* Misc config */
> +
> +#define LOONGARCH_CSR_ECFG           0x4 /* Exception config */
> +FIELD(CSR_ECFG, LIE, 0, 13)
> +FIELD(CSR_ECFG, VS, 16, 3)
> +
> +#define LOONGARCH_CSR_ESTAT          0x5 /* Exception status */
> +FIELD(CSR_ESTAT, IS, 0, 13)
> +FIELD(CSR_ESTAT, ECODE, 16, 6)
> +FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
> +
> +#define  EXCCODE_EXTERNAL_INT   64   /* plus external interrupt number */
what's "plus external interrupt"?
> +#define  EXCCODE_INT                 0
> +#define  EXCCODE_PIL                 1
> +#define  EXCCODE_PIS                 2
> +#define  EXCCODE_PIF                 3
> +#define  EXCCODE_PME                 4
> +#define  EXCCODE_PNR                 5
> +#define  EXCCODE_PNX                 6
> +#define  EXCCODE_PPI                 7
> +#define  EXCCODE_ADEF                8 /* Have different expsubcode */
"different exception subcodes"
> +#define  EXCCODE_ADEM                8 /* Have different expsubcode */
> +#define  EXCCODE_ALE                 9
> +#define  EXCCODE_BCE                 10
> +#define  EXCCODE_SYS                 11
> +#define  EXCCODE_BRK                 12
> +#define  EXCCODE_INE                 13
> +#define  EXCCODE_IPE                 14
> +#define  EXCCODE_FPD                 15
> +#define  EXCCODE_SXD                 16
> +#define  EXCCODE_ASXD                17
> +#define  EXCCODE_FPE                 18 /* Have different expsubcode */
> +#define  EXCCODE_VFPE                18
> +#define  EXCCODE_WPEF                19 /* Have different expsubcode */
> +#define  EXCCODE_WPEM                19
> +#define  EXCCODE_BTD                 20
> +#define  EXCCODE_BTE                 21
> +#define  EXCCODE_DBP                 26 /* Reserved decode used for debug */
"decode"? also "used for debugging"?
> +
> +#define LOONGARCH_CSR_ERA            0x6 /* Exception return address */
> +
> +#define LOONGARCH_CSR_BADV           0x7 /* Bad virtual address */
> +
> +#define LOONGARCH_CSR_BADI           0x8 /* Bad instruction */
> +
> +#define LOONGARCH_CSR_EENTRY         0xc /* Exception enter base address */
"exception entrypoint"?
> +
> +/* TLB related CSR register */
"CSR register" is duplication; "R" is already "register". Also "CSRs"...
> +#define LOONGARCH_CSR_TLBIDX         0x10 /* TLB Index, EHINV, PageSize, NP */
> +FIELD(CSR_TLBIDX, INDEX, 0, 12)
> +FIELD(CSR_TLBIDX, PS, 24, 6)
> +FIELD(CSR_TLBIDX, NE, 31, 1)
> +
> +#define LOONGARCH_CSR_TLBEHI         0x11 /* TLB EntryHi without ASID */
I cannot find the "without ASID" part in the Chinese manual...
> +FIELD(CSR_TLBEHI, VPPN, 13, 35)
> +
> +#define LOONGARCH_CSR_TLBELO0        0x12 /* TLB EntryLo0 */
> +#define LOONGARCH_CSR_TLBELO1        0x13 /* TLB EntryLo1 */
> +FIELD(TLBENTRY, V, 0, 1)
> +FIELD(TLBENTRY, D, 1, 1)
> +FIELD(TLBENTRY, PLV, 2, 2)
> +FIELD(TLBENTRY, MAT, 4, 2)
> +FIELD(TLBENTRY, G, 6, 1)
> +FIELD(TLBENTRY, PPN, 12, 36)
> +FIELD(TLBENTRY, NR, 61, 1)
> +FIELD(TLBENTRY, NX, 62, 1)
> +FIELD(TLBENTRY, RPLV, 63, 1)
> +
> +#define LOONGARCH_CSR_ASID           0x18 /* Address space identifier */
> +FIELD(CSR_ASID, ASID, 0, 10)
> +FIELD(CSR_ASID, ASIDBITS, 16, 8)
> +
> +/* Page table base address when badv[47] = 0 */
> +#define LOONGARCH_CSR_PGDL           0x19
> +/* Page table base address when badv[47] = 1 */
> +#define LOONGARCH_CSR_PGDH           0x1a
> +
> +#define LOONGARCH_CSR_PGD            0x1b /* Page table base */
> +
> +/* Page walk controller's low addr */
> +#define LOONGARCH_CSR_PWCL           0x1c
> +FIELD(CSR_PWCL, PTBASE, 0, 5)
> +FIELD(CSR_PWCL, PTWIDTH, 5, 5)
> +FIELD(CSR_PWCL, DIR1_BASE, 10, 5)
> +FIELD(CSR_PWCL, DIR1_WIDTH, 15, 5)
> +FIELD(CSR_PWCL, DIR2_BASE, 20, 5)
> +FIELD(CSR_PWCL, DIR2_WIDTH, 25, 5)
> +FIELD(CSR_PWCL, PTEWIDTH, 30, 2)
> +
> +/* Page walk controller's high addr */
> +#define LOONGARCH_CSR_PWCH           0x1d
> +FIELD(CSR_PWCH, DIR3_BASE, 0, 6)
> +FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6)
> +FIELD(CSR_PWCH, DIR4_BASE, 12, 6)
> +FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6)
> +
> +#define LOONGARCH_CSR_STLBPS         0x1e /*Stlb page size*/
Spaces around the comment text...
> +FIELD(CSR_STLBPS, PS, 0, 5)
> +
> +#define LOONGARCH_CSR_RVACFG         0x1f /* Reduced virtual address config */
> +FIELD(CSR_RVACFG, RBITS, 0, 4)
> +
> +/* Config CSR registers */
> +#define LOONGARCH_CSR_CPUID          0x20 /* CPU core id */
> +
> +#define LOONGARCH_CSR_PRCFG1         0x21 /* Config1 */
> +FIELD(CSR_PRCFG1, SAVE_NUM, 0, 4)
> +FIELD(CSR_PRCFG1, TIMER_BITS, 4, 8)
> +FIELD(CSR_PRCFG1, VSMAX, 12, 3)
> +
> +#define LOONGARCH_CSR_PRCFG2         0x22 /* Config2 */
> +
> +#define LOONGARCH_CSR_PRCFG3         0x23 /* Config3 */
> +FIELD(CSR_PRCFG3, TLB_TYPE, 0, 4)
> +FIELD(CSR_PRCFG3, MTLB_ENTRY, 4, 8)
> +FIELD(CSR_PRCFG3, STLB_WAYS, 12, 8)
> +FIELD(CSR_PRCFG3, STLB_SETS, 20, 8)
> +
> +/*
> + * Save registers count can read from PRCFG1.SAVE_NUM
> + * The Min count is 1. Max count is 15.
> + */
> +#define LOONGARCH_CSR_SAVE(N)        (0x30 + N)
> +
> +/* Timer registers */
> +#define LOONGARCH_CSR_TID            0x40 /* Timer ID */
> +
> +#define LOONGARCH_CSR_TCFG           0x41 /* Timer config */
> +FIELD(CSR_TCFG, EN, 0, 1)
> +FIELD(CSR_TCFG, PERIODIC, 1, 1)
> +FIELD(CSR_TCFG, INIT_VAL, 2, 46)
> +
> +#define LOONGARCH_CSR_TVAL           0x42 /* Timer ticks remain */
> +
> +#define LOONGARCH_CSR_CNTC           0x43 /* Timer offset */
> +
> +#define LOONGARCH_CSR_TICLR          0x44 /* Timer interrupt clear */
> +
> +/* LLBCTL register */
> +#define LOONGARCH_CSR_LLBCTL         0x60 /* LLBit control */
> +FIELD(CSR_LLBCTL, ROLLB, 0, 1)
> +FIELD(CSR_LLBCTL, WCLLB, 1, 1)
> +FIELD(CSR_LLBCTL, KLO, 2, 1)
> +
> +/* Implement dependent */
> +#define LOONGARCH_CSR_IMPCTL1        0x80 /* LoongArch config1 */
> +
> +#define LOONGARCH_CSR_IMPCTL2        0x81 /* LoongArch config2*/
Space after "control"...
> +
> +/* TLB Refill registers */
> +#define LOONGARCH_CSR_TLBRENTRY      0x88 /* TLB refill exception address */
> +#define LOONGARCH_CSR_TLBRBADV       0x89 /* TLB refill badvaddr */
Proper casing, this seems to just be "BADV" according to the manual.
> +#define LOONGARCH_CSR_TLBRERA        0x8a /* TLB refill ERA */
> +#define LOONGARCH_CSR_TLBRSAVE       0x8b /* KScratch for TLB refill */
> +FIELD(CSR_TLBRERA, ISTLBR, 0, 1)
> +FIELD(CSR_TLBRERA, PC, 2, 62)
> +#define LOONGARCH_CSR_TLBRELO0       0x8c /* TLB refill entrylo0 */
> +#define LOONGARCH_CSR_TLBRELO1       0x8d /* TLB refill entrylo1 */
> +#define LOONGARCH_CSR_TLBREHI        0x8e /* TLB refill entryhi */
> +FIELD(CSR_TLBREHI, PS, 0, 6)
> +FIELD(CSR_TLBREHI, VPPN, 13, 35)
> +#define LOONGARCH_CSR_TLBRPRMD       0x8f /* TLB refill mode info */
> +FIELD(CSR_TLBRPRMD, PPLV, 0, 2)
> +FIELD(CSR_TLBRPRMD, PIE, 2, 1)
> +FIELD(CSR_TLBRPRMD, PWE, 4, 1)
> +
> +/* Machine Error registers */
> +#define LOONGARCH_CSR_MERRCTL        0x90 /* ERRCTL */
> +FIELD(CSR_MERRCTL, ISMERR, 0, 1)
> +#define LOONGARCH_CSR_MERRINFO1      0x91
> +#define LOONGARCH_CSR_MERRINFO2      0x92
> +#define LOONGARCH_CSR_MERRENTRY      0x93 /* MError exception base */
> +#define LOONGARCH_CSR_MERRERA        0x94 /* MError exception PC */
> +#define LOONGARCH_CSR_MERRSAVE       0x95 /* KScratch for error exception */
> +
> +#define LOONGARCH_CSR_CTAG           0x98 /* TagLo + TagHi */
This "TagLo + TagHi" is not present in the manual either.
> +
> +/* Direct map windows */
> +#define LOONGARCH_CSR_DMW(N)         (0x180 + N) /* direct map win MEM & IF */
> +FIELD(CSR_DMW, PLV0, 0, 1)
> +FIELD(CSR_DMW, PLV1, 1, 1)
> +FIELD(CSR_DMW, PLV2, 2, 1)
> +FIELD(CSR_DMW, PLV3, 3, 1)
> +FIELD(CSR_DMW, MAT, 4, 2)
> +FIELD(CSR_DMW, VSEG, 60, 4)
> +
> +#define dmw_va2pa(va) \
> +    (va & MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS))
> +
> +/* Debug registers */
> +#define LOONGARCH_CSR_DBG            0x500 /* debug config */
> +FIELD(CSR_DBG, DST, 0, 1)
> +FIELD(CSR_DBG, DREV, 1, 7)
> +FIELD(CSR_DBG, DEI, 8, 1)
> +FIELD(CSR_DBG, DCL, 9, 1)
> +FIELD(CSR_DBG, DFW, 10, 1)
> +FIELD(CSR_DBG, DMW, 11, 1)
> +FIELD(CSR_DBG, ECODE, 16, 6)
> +
> +#define LOONGARCH_CSR_DERA           0x501 /* Debug era */
> +#define LOONGARCH_CSR_DSAVE          0x502 /* Debug save */
> +
> +#endif /* LOONGARCH_CPU_CSR_H */
As pointed out in the numerous comments above, there are so many errors 
and inconsistencies in the comments, that it's probably better to just 
remove all of them. People working with this low level piece of software 
are expected to be familiar with the manuals, so the comments really 
don't serve any purpose if all they did were explaining the abbreviations.
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 883c6c623f..ed03ec2986 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -156,6 +156,8 @@ static void loongarch_3a5000_initfn(Object *obj)
>       data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 0xf00f);
>       data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 0x60);
>       env->cpucfg[20] = data;
> +
> +    env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
>   }
>   
>   static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
> @@ -179,12 +181,45 @@ static void loongarch_cpu_reset(DeviceState *dev)
>       LoongArchCPU *cpu = LOONGARCH_CPU(cs);
>       LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu);
>       CPULoongArchState *env = &cpu->env;
> +    int n;
>   
>       lacc->parent_reset(dev);
>   
>       env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
>       env->fcsr0 = 0x0;
>   
> +    /* Set csr registers value after reset */
> +    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, 1);
> +    env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 1);
> +
> +    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_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);
> +
> +    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);
> +    }
> +
>       restore_fp_status(env);
>       cs->exception_index = EXCP_NONE;
>   }
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index b036cdee5f..cf7fc46f72 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -11,6 +11,7 @@
>   #include "exec/cpu-defs.h"
>   #include "fpu/softfloat-types.h"
>   #include "hw/registerfields.h"
> +#include "cpu-csr.h"
>   
>   #define TCG_GUEST_DEFAULT_MO (0)
>   
> @@ -170,6 +171,62 @@ struct CPULoongArchState {
>       uint64_t llval;
>   
>       uint64_t badaddr;
> +
> +    /* LoongArch CSR registers */
> +    uint64_t CSR_CRMD;
> +    uint64_t CSR_PRMD;
> +    uint64_t CSR_EUEN;
> +    uint64_t CSR_MISC;
> +    uint64_t CSR_ECFG;
> +    uint64_t CSR_ESTAT;
> +    uint64_t CSR_ERA;
> +    uint64_t CSR_BADV;
> +    uint64_t CSR_BADI;
> +    uint64_t CSR_EENTRY;
> +    uint64_t CSR_TLBIDX;
> +    uint64_t CSR_TLBEHI;
> +    uint64_t CSR_TLBELO0;
> +    uint64_t CSR_TLBELO1;
> +    uint64_t CSR_ASID;
> +    uint64_t CSR_PGDL;
> +    uint64_t CSR_PGDH;
> +    uint64_t CSR_PGD;
> +    uint64_t CSR_PWCL;
> +    uint64_t CSR_PWCH;
> +    uint64_t CSR_STLBPS;
> +    uint64_t CSR_RVACFG;
> +    uint64_t CSR_CPUID;
> +    uint64_t CSR_PRCFG1;
> +    uint64_t CSR_PRCFG2;
> +    uint64_t CSR_PRCFG3;
> +    uint64_t CSR_SAVE[16];
> +    uint64_t CSR_TID;
> +    uint64_t CSR_TCFG;
> +    uint64_t CSR_TVAL;
> +    uint64_t CSR_CNTC;
> +    uint64_t CSR_TICLR;
> +    uint64_t CSR_LLBCTL;
> +    uint64_t CSR_IMPCTL1;
> +    uint64_t CSR_IMPCTL2;
> +    uint64_t CSR_TLBRENTRY;
> +    uint64_t CSR_TLBRBADV;
> +    uint64_t CSR_TLBRERA;
> +    uint64_t CSR_TLBRSAVE;
> +    uint64_t CSR_TLBRELO0;
> +    uint64_t CSR_TLBRELO1;
> +    uint64_t CSR_TLBREHI;
> +    uint64_t CSR_TLBRPRMD;
> +    uint64_t CSR_MERRCTL;
> +    uint64_t CSR_MERRINFO1;
> +    uint64_t CSR_MERRINFO2;
> +    uint64_t CSR_MERRENTRY;
> +    uint64_t CSR_MERRERA;
> +    uint64_t CSR_MERRSAVE;
> +    uint64_t CSR_CTAG;
> +    uint64_t CSR_DMW[4];
> +    uint64_t CSR_DBG;
> +    uint64_t CSR_DERA;
> +    uint64_t CSR_DSAVE;
Field names should be lower-case snake_case form, as is the case for 
overwhelming majority of target CPUState definitions I checked (except 
MIPS, which you might be basing your code on). For sake of consistency, 
please change all of them to snake_case.
>   };
>   
>   /**
diff mbox series

Patch

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
new file mode 100644
index 0000000000..7a57b7ea36
--- /dev/null
+++ b/target/loongarch/cpu-csr.h
@@ -0,0 +1,236 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU CSR registers
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_CSR_H
+#define LOONGARCH_CPU_CSR_H
+
+/* Base on: kernal: arch/loongarch/include/asm/loongarch.h */
+
+/* Basic CSR register */
+#define LOONGARCH_CSR_CRMD           0x0 /* Current mode info */
+FIELD(CSR_CRMD, PLV, 0, 2)
+FIELD(CSR_CRMD, IE, 2, 1)
+FIELD(CSR_CRMD, DA, 3, 1)
+FIELD(CSR_CRMD, PG, 4, 1)
+FIELD(CSR_CRMD, DATF, 5, 2)
+FIELD(CSR_CRMD, DATM, 7, 2)
+FIELD(CSR_CRMD, WE, 9, 1)
+
+#define LOONGARCH_CSR_PRMD           0x1 /* Prev-exception mode info */
+FIELD(CSR_PRMD, PPLV, 0, 2)
+FIELD(CSR_PRMD, PIE, 2, 1)
+FIELD(CSR_PRMD, PWE, 3, 1)
+
+#define LOONGARCH_CSR_EUEN           0x2 /* Extended unit enable */
+FIELD(CSR_EUEN, FPE, 0, 1)
+FIELD(CSR_EUEN, SXE, 1, 1)
+FIELD(CSR_EUEN, ASXE, 2, 1)
+FIELD(CSR_EUEN, BTE, 3, 1)
+
+#define LOONGARCH_CSR_MISC           0x3 /* Misc config */
+
+#define LOONGARCH_CSR_ECFG           0x4 /* Exception config */
+FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, VS, 16, 3)
+
+#define LOONGARCH_CSR_ESTAT          0x5 /* Exception status */
+FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, ECODE, 16, 6)
+FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
+
+#define  EXCCODE_EXTERNAL_INT   64   /* plus external interrupt number */
+#define  EXCCODE_INT                 0
+#define  EXCCODE_PIL                 1
+#define  EXCCODE_PIS                 2
+#define  EXCCODE_PIF                 3
+#define  EXCCODE_PME                 4
+#define  EXCCODE_PNR                 5
+#define  EXCCODE_PNX                 6
+#define  EXCCODE_PPI                 7
+#define  EXCCODE_ADEF                8 /* Have different expsubcode */
+#define  EXCCODE_ADEM                8 /* Have different expsubcode */
+#define  EXCCODE_ALE                 9
+#define  EXCCODE_BCE                 10
+#define  EXCCODE_SYS                 11
+#define  EXCCODE_BRK                 12
+#define  EXCCODE_INE                 13
+#define  EXCCODE_IPE                 14
+#define  EXCCODE_FPD                 15
+#define  EXCCODE_SXD                 16
+#define  EXCCODE_ASXD                17
+#define  EXCCODE_FPE                 18 /* Have different expsubcode */
+#define  EXCCODE_VFPE                18
+#define  EXCCODE_WPEF                19 /* Have different expsubcode */
+#define  EXCCODE_WPEM                19
+#define  EXCCODE_BTD                 20
+#define  EXCCODE_BTE                 21
+#define  EXCCODE_DBP                 26 /* Reserved decode used for debug */
+
+#define LOONGARCH_CSR_ERA            0x6 /* Exception return address */
+
+#define LOONGARCH_CSR_BADV           0x7 /* Bad virtual address */
+
+#define LOONGARCH_CSR_BADI           0x8 /* Bad instruction */
+
+#define LOONGARCH_CSR_EENTRY         0xc /* Exception enter base address */
+
+/* TLB related CSR register */
+#define LOONGARCH_CSR_TLBIDX         0x10 /* TLB Index, EHINV, PageSize, NP */
+FIELD(CSR_TLBIDX, INDEX, 0, 12)
+FIELD(CSR_TLBIDX, PS, 24, 6)
+FIELD(CSR_TLBIDX, NE, 31, 1)
+
+#define LOONGARCH_CSR_TLBEHI         0x11 /* TLB EntryHi without ASID */
+FIELD(CSR_TLBEHI, VPPN, 13, 35)
+
+#define LOONGARCH_CSR_TLBELO0        0x12 /* TLB EntryLo0 */
+#define LOONGARCH_CSR_TLBELO1        0x13 /* TLB EntryLo1 */
+FIELD(TLBENTRY, V, 0, 1)
+FIELD(TLBENTRY, D, 1, 1)
+FIELD(TLBENTRY, PLV, 2, 2)
+FIELD(TLBENTRY, MAT, 4, 2)
+FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, PPN, 12, 36)
+FIELD(TLBENTRY, NR, 61, 1)
+FIELD(TLBENTRY, NX, 62, 1)
+FIELD(TLBENTRY, RPLV, 63, 1)
+
+#define LOONGARCH_CSR_ASID           0x18 /* Address space identifier */
+FIELD(CSR_ASID, ASID, 0, 10)
+FIELD(CSR_ASID, ASIDBITS, 16, 8)
+
+/* Page table base address when badv[47] = 0 */
+#define LOONGARCH_CSR_PGDL           0x19
+/* Page table base address when badv[47] = 1 */
+#define LOONGARCH_CSR_PGDH           0x1a
+
+#define LOONGARCH_CSR_PGD            0x1b /* Page table base */
+
+/* Page walk controller's low addr */
+#define LOONGARCH_CSR_PWCL           0x1c
+FIELD(CSR_PWCL, PTBASE, 0, 5)
+FIELD(CSR_PWCL, PTWIDTH, 5, 5)
+FIELD(CSR_PWCL, DIR1_BASE, 10, 5)
+FIELD(CSR_PWCL, DIR1_WIDTH, 15, 5)
+FIELD(CSR_PWCL, DIR2_BASE, 20, 5)
+FIELD(CSR_PWCL, DIR2_WIDTH, 25, 5)
+FIELD(CSR_PWCL, PTEWIDTH, 30, 2)
+
+/* Page walk controller's high addr */
+#define LOONGARCH_CSR_PWCH           0x1d
+FIELD(CSR_PWCH, DIR3_BASE, 0, 6)
+FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6)
+FIELD(CSR_PWCH, DIR4_BASE, 12, 6)
+FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6)
+
+#define LOONGARCH_CSR_STLBPS         0x1e /*Stlb page size*/
+FIELD(CSR_STLBPS, PS, 0, 5)
+
+#define LOONGARCH_CSR_RVACFG         0x1f /* Reduced virtual address config */
+FIELD(CSR_RVACFG, RBITS, 0, 4)
+
+/* Config CSR registers */
+#define LOONGARCH_CSR_CPUID          0x20 /* CPU core id */
+
+#define LOONGARCH_CSR_PRCFG1         0x21 /* Config1 */
+FIELD(CSR_PRCFG1, SAVE_NUM, 0, 4)
+FIELD(CSR_PRCFG1, TIMER_BITS, 4, 8)
+FIELD(CSR_PRCFG1, VSMAX, 12, 3)
+
+#define LOONGARCH_CSR_PRCFG2         0x22 /* Config2 */
+
+#define LOONGARCH_CSR_PRCFG3         0x23 /* Config3 */
+FIELD(CSR_PRCFG3, TLB_TYPE, 0, 4)
+FIELD(CSR_PRCFG3, MTLB_ENTRY, 4, 8)
+FIELD(CSR_PRCFG3, STLB_WAYS, 12, 8)
+FIELD(CSR_PRCFG3, STLB_SETS, 20, 8)
+
+/*
+ * Save registers count can read from PRCFG1.SAVE_NUM
+ * The Min count is 1. Max count is 15.
+ */
+#define LOONGARCH_CSR_SAVE(N)        (0x30 + N)
+
+/* Timer registers */
+#define LOONGARCH_CSR_TID            0x40 /* Timer ID */
+
+#define LOONGARCH_CSR_TCFG           0x41 /* Timer config */
+FIELD(CSR_TCFG, EN, 0, 1)
+FIELD(CSR_TCFG, PERIODIC, 1, 1)
+FIELD(CSR_TCFG, INIT_VAL, 2, 46)
+
+#define LOONGARCH_CSR_TVAL           0x42 /* Timer ticks remain */
+
+#define LOONGARCH_CSR_CNTC           0x43 /* Timer offset */
+
+#define LOONGARCH_CSR_TICLR          0x44 /* Timer interrupt clear */
+
+/* LLBCTL register */
+#define LOONGARCH_CSR_LLBCTL         0x60 /* LLBit control */
+FIELD(CSR_LLBCTL, ROLLB, 0, 1)
+FIELD(CSR_LLBCTL, WCLLB, 1, 1)
+FIELD(CSR_LLBCTL, KLO, 2, 1)
+
+/* Implement dependent */
+#define LOONGARCH_CSR_IMPCTL1        0x80 /* LoongArch config1 */
+
+#define LOONGARCH_CSR_IMPCTL2        0x81 /* LoongArch config2*/
+
+/* TLB Refill registers */
+#define LOONGARCH_CSR_TLBRENTRY      0x88 /* TLB refill exception address */
+#define LOONGARCH_CSR_TLBRBADV       0x89 /* TLB refill badvaddr */
+#define LOONGARCH_CSR_TLBRERA        0x8a /* TLB refill ERA */
+#define LOONGARCH_CSR_TLBRSAVE       0x8b /* KScratch for TLB refill */
+FIELD(CSR_TLBRERA, ISTLBR, 0, 1)
+FIELD(CSR_TLBRERA, PC, 2, 62)
+#define LOONGARCH_CSR_TLBRELO0       0x8c /* TLB refill entrylo0 */
+#define LOONGARCH_CSR_TLBRELO1       0x8d /* TLB refill entrylo1 */
+#define LOONGARCH_CSR_TLBREHI        0x8e /* TLB refill entryhi */
+FIELD(CSR_TLBREHI, PS, 0, 6)
+FIELD(CSR_TLBREHI, VPPN, 13, 35)
+#define LOONGARCH_CSR_TLBRPRMD       0x8f /* TLB refill mode info */
+FIELD(CSR_TLBRPRMD, PPLV, 0, 2)
+FIELD(CSR_TLBRPRMD, PIE, 2, 1)
+FIELD(CSR_TLBRPRMD, PWE, 4, 1)
+
+/* Machine Error registers */
+#define LOONGARCH_CSR_MERRCTL        0x90 /* ERRCTL */
+FIELD(CSR_MERRCTL, ISMERR, 0, 1)
+#define LOONGARCH_CSR_MERRINFO1      0x91
+#define LOONGARCH_CSR_MERRINFO2      0x92
+#define LOONGARCH_CSR_MERRENTRY      0x93 /* MError exception base */
+#define LOONGARCH_CSR_MERRERA        0x94 /* MError exception PC */
+#define LOONGARCH_CSR_MERRSAVE       0x95 /* KScratch for error exception */
+
+#define LOONGARCH_CSR_CTAG           0x98 /* TagLo + TagHi */
+
+/* Direct map windows */
+#define LOONGARCH_CSR_DMW(N)         (0x180 + N) /* direct map win MEM & IF */
+FIELD(CSR_DMW, PLV0, 0, 1)
+FIELD(CSR_DMW, PLV1, 1, 1)
+FIELD(CSR_DMW, PLV2, 2, 1)
+FIELD(CSR_DMW, PLV3, 3, 1)
+FIELD(CSR_DMW, MAT, 4, 2)
+FIELD(CSR_DMW, VSEG, 60, 4)
+
+#define dmw_va2pa(va) \
+    (va & MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS))
+
+/* Debug registers */
+#define LOONGARCH_CSR_DBG            0x500 /* debug config */
+FIELD(CSR_DBG, DST, 0, 1)
+FIELD(CSR_DBG, DREV, 1, 7)
+FIELD(CSR_DBG, DEI, 8, 1)
+FIELD(CSR_DBG, DCL, 9, 1)
+FIELD(CSR_DBG, DFW, 10, 1)
+FIELD(CSR_DBG, DMW, 11, 1)
+FIELD(CSR_DBG, ECODE, 16, 6)
+
+#define LOONGARCH_CSR_DERA           0x501 /* Debug era */
+#define LOONGARCH_CSR_DSAVE          0x502 /* Debug save */
+
+#endif /* LOONGARCH_CPU_CSR_H */
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 883c6c623f..ed03ec2986 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -156,6 +156,8 @@  static void loongarch_3a5000_initfn(Object *obj)
     data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 0xf00f);
     data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 0x60);
     env->cpucfg[20] = data;
+
+    env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
 }
 
 static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
@@ -179,12 +181,45 @@  static void loongarch_cpu_reset(DeviceState *dev)
     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
     LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu);
     CPULoongArchState *env = &cpu->env;
+    int n;
 
     lacc->parent_reset(dev);
 
     env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
     env->fcsr0 = 0x0;
 
+    /* Set csr registers value after reset */
+    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, 1);
+    env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 1);
+
+    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_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);
+
+    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);
+    }
+
     restore_fp_status(env);
     cs->exception_index = EXCP_NONE;
 }
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index b036cdee5f..cf7fc46f72 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -11,6 +11,7 @@ 
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
+#include "cpu-csr.h"
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -170,6 +171,62 @@  struct CPULoongArchState {
     uint64_t llval;
 
     uint64_t badaddr;
+
+    /* LoongArch CSR registers */
+    uint64_t CSR_CRMD;
+    uint64_t CSR_PRMD;
+    uint64_t CSR_EUEN;
+    uint64_t CSR_MISC;
+    uint64_t CSR_ECFG;
+    uint64_t CSR_ESTAT;
+    uint64_t CSR_ERA;
+    uint64_t CSR_BADV;
+    uint64_t CSR_BADI;
+    uint64_t CSR_EENTRY;
+    uint64_t CSR_TLBIDX;
+    uint64_t CSR_TLBEHI;
+    uint64_t CSR_TLBELO0;
+    uint64_t CSR_TLBELO1;
+    uint64_t CSR_ASID;
+    uint64_t CSR_PGDL;
+    uint64_t CSR_PGDH;
+    uint64_t CSR_PGD;
+    uint64_t CSR_PWCL;
+    uint64_t CSR_PWCH;
+    uint64_t CSR_STLBPS;
+    uint64_t CSR_RVACFG;
+    uint64_t CSR_CPUID;
+    uint64_t CSR_PRCFG1;
+    uint64_t CSR_PRCFG2;
+    uint64_t CSR_PRCFG3;
+    uint64_t CSR_SAVE[16];
+    uint64_t CSR_TID;
+    uint64_t CSR_TCFG;
+    uint64_t CSR_TVAL;
+    uint64_t CSR_CNTC;
+    uint64_t CSR_TICLR;
+    uint64_t CSR_LLBCTL;
+    uint64_t CSR_IMPCTL1;
+    uint64_t CSR_IMPCTL2;
+    uint64_t CSR_TLBRENTRY;
+    uint64_t CSR_TLBRBADV;
+    uint64_t CSR_TLBRERA;
+    uint64_t CSR_TLBRSAVE;
+    uint64_t CSR_TLBRELO0;
+    uint64_t CSR_TLBRELO1;
+    uint64_t CSR_TLBREHI;
+    uint64_t CSR_TLBRPRMD;
+    uint64_t CSR_MERRCTL;
+    uint64_t CSR_MERRINFO1;
+    uint64_t CSR_MERRINFO2;
+    uint64_t CSR_MERRENTRY;
+    uint64_t CSR_MERRERA;
+    uint64_t CSR_MERRSAVE;
+    uint64_t CSR_CTAG;
+    uint64_t CSR_DMW[4];
+    uint64_t CSR_DBG;
+    uint64_t CSR_DERA;
+    uint64_t CSR_DSAVE;
 };
 
 /**