Add the LVZ CPU property and initialize the host and guest state banks for the LA464 model. Reset always returns to the host CSR and TLB bank and initializes the implemented guest ID width.
Signed-off-by: SignKirigami <[email protected]> Signed-off-by: Hengyu Yu <[email protected]> --- target/loongarch/cpu.c | 145 +++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 55 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 0f6a211949..c5c7f3e0e3 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -114,12 +114,12 @@ 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); + CPUSysState *host = get_sys(env, LOONGARCH_VM_LEVEL_HOST); int i, num; if (!initialized) { initialized = true; - num = FIELD_EX64(sys->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM); + num = FIELD_EX64(host->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM); for (i = num; i < 16; i++) { set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED); } @@ -251,11 +251,32 @@ static void loongarch_set_ptw(Object *obj, bool value, Error **errp) cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, HPTW, value); } +static bool loongarch_get_lvz(Object *obj, Error **errp) +{ + return LOONGARCH_CPU(obj)->lvz != ON_OFF_AUTO_OFF; +} + +static void loongarch_set_lvz(Object *obj, bool value, Error **errp) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(obj); + + cpu->lvz = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + + if (kvm_enabled()) { + return; + } + + cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LVZ, value); + cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LVZ_VER, + value ? 1 : 0); +} + static void loongarch_cpu_post_init(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); cpu->lbt = ON_OFF_AUTO_OFF; + cpu->lvz = ON_OFF_AUTO_AUTO; cpu->pmu = ON_OFF_AUTO_OFF; cpu->lsx = ON_OFF_AUTO_AUTO; cpu->lasx = ON_OFF_AUTO_AUTO; @@ -267,6 +288,8 @@ static void loongarch_cpu_post_init(Object *obj) loongarch_set_msgint); object_property_add_bool(obj, "ptw", loongarch_get_ptw, loongarch_set_ptw); + object_property_add_bool(obj, "lvz", loongarch_get_lvz, + loongarch_set_lvz); /* lbt is enabled only in kvm mode, not supported in tcg mode */ if (kvm_enabled()) { @@ -278,7 +301,8 @@ static void loongarch_la464_initfn(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); CPULoongArchState *env = &cpu->env; - CPUSysState *sys; + CPUSysState *host = get_sys(env, LOONGARCH_VM_LEVEL_HOST); + CPUSysState *guest = get_sys(env, LOONGARCH_VM_LEVEL_GUEST); uint32_t data = 0, field; int i; @@ -322,6 +346,8 @@ static void loongarch_la464_initfn(Object *obj) data = FIELD_DP32(data, CPUCFG2, FP_VER, 1); data = FIELD_DP32(data, CPUCFG2, LSX, 1), data = FIELD_DP32(data, CPUCFG2, LASX, 1), + data = FIELD_DP32(data, CPUCFG2, LVZ, 1); + data = FIELD_DP32(data, CPUCFG2, LVZ_VER, 1); data = FIELD_DP32(data, CPUCFG2, LLFTP, 1); data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1); data = FIELD_DP32(data, CPUCFG2, LSPW, 1); @@ -386,19 +412,19 @@ static void loongarch_la464_initfn(Object *obj) data = FIELD_DP32(data, CPUCFG20, L3IU_SIZE, 6); env->cpucfg[20] = data; - sys = env_sys(env); - sys->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa); + host->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa); + guest->CSR_ASID = host->CSR_ASID; - 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); + host->CSR_PRCFG1 = FIELD_DP64(host->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM, 8); + host->CSR_PRCFG1 = FIELD_DP64(host->CSR_PRCFG1, CSR_PRCFG1, TIMER_BITS, 0x2f); + host->CSR_PRCFG1 = FIELD_DP64(host->CSR_PRCFG1, CSR_PRCFG1, VSMAX, 7); - sys->CSR_PRCFG2 = 0x3ffff000; + host->CSR_PRCFG2 = 0x3ffff000; - 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); + host->CSR_PRCFG3 = FIELD_DP64(host->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2); + host->CSR_PRCFG3 = FIELD_DP64(host->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63); + host->CSR_PRCFG3 = FIELD_DP64(host->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7); + host->CSR_PRCFG3 = FIELD_DP64(host->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); cpu->msgint = ON_OFF_AUTO_OFF; cpu->ptw = ON_OFF_AUTO_OFF; @@ -439,6 +465,7 @@ static void loongarch_la132_initfn(Object *obj) data = FIELD_DP32(data, CPUCFG1, CRC, 1); env->cpucfg[1] = data; cpu->msgint = ON_OFF_AUTO_OFF; + cpu->lvz = ON_OFF_AUTO_OFF; cpu->ptw = ON_OFF_AUTO_OFF; } @@ -600,7 +627,7 @@ 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); + CPUSysState *host = get_sys(env, LOONGARCH_VM_LEVEL_HOST); if (lacc->parent_phases.hold) { lacc->parent_phases.hold(obj, type); @@ -624,61 +651,69 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type) int n; /* Set csr registers value after reset, see the manual 6.4. */ - 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; + host->CSR_CRMD = FIELD_DP64(host->CSR_CRMD, CSR_CRMD, PLV, 0); + host->CSR_CRMD = FIELD_DP64(host->CSR_CRMD, CSR_CRMD, IE, 0); + host->CSR_CRMD = FIELD_DP64(host->CSR_CRMD, CSR_CRMD, DA, 1); + host->CSR_CRMD = FIELD_DP64(host->CSR_CRMD, CSR_CRMD, PG, 0); + host->CSR_CRMD = FIELD_DP64(host->CSR_CRMD, CSR_CRMD, DATF, 0); + host->CSR_CRMD = FIELD_DP64(host->CSR_CRMD, CSR_CRMD, DATM, 0); + + host->CSR_EUEN = FIELD_DP64(host->CSR_EUEN, CSR_EUEN, FPE, 0); + host->CSR_EUEN = FIELD_DP64(host->CSR_EUEN, CSR_EUEN, SXE, 0); + host->CSR_EUEN = FIELD_DP64(host->CSR_EUEN, CSR_EUEN, ASXE, 0); + host->CSR_EUEN = FIELD_DP64(host->CSR_EUEN, CSR_EUEN, BTE, 0); + + host->CSR_MISC = 0; + + host->CSR_ECFG = FIELD_DP64(host->CSR_ECFG, CSR_ECFG, VS, 0); + host->CSR_ECFG = FIELD_DP64(host->CSR_ECFG, CSR_ECFG, LIE, 0); + + host->CSR_ESTAT = host->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2)); + host->CSR_RVACFG = FIELD_DP64(host->CSR_RVACFG, CSR_RVACFG, RBITS, 0); + host->CSR_CPUID = cs->cpu_index; + host->CSR_TCFG = FIELD_DP64(host->CSR_TCFG, CSR_TCFG, EN, 0); + host->CSR_LLBCTL = FIELD_DP64(host->CSR_LLBCTL, CSR_LLBCTL, KLO, 0); + host->CSR_TLBRERA = FIELD_DP64(host->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0); + host->CSR_MERRCTL = FIELD_DP64(host->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0); + host->CSR_TID = cs->cpu_index; + host->CSR_GSTAT = 0; + host->CSR_GCFG = 0; + host->CSR_GINTC = 0; + host->CSR_GCNTC = 0; + host->CSR_GTLBC = 0; /* * 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. */ - sys->CSR_PGDH = 0; - sys->CSR_PGDL = 0; - sys->CSR_PWCH = 0; - sys->CSR_EENTRY = 0; - sys->CSR_TLBRENTRY = 0; - sys->CSR_MERRENTRY = 0; + host->CSR_PGDH = 0; + host->CSR_PGDL = 0; + host->CSR_PWCH = 0; + host->CSR_EENTRY = 0; + host->CSR_TLBRENTRY = 0; + host->CSR_MERRENTRY = 0; /* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */ - if (sys->CSR_PRCFG2 == 0) { - sys->CSR_PRCFG2 = 0x3fffff000; + if (host->CSR_PRCFG2 == 0) { + host->CSR_PRCFG2 = 0x3fffff000; } - 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); + tlb_ps = ctz32(host->CSR_PRCFG2); + host->CSR_STLBPS = FIELD_DP64(host->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps); + host->CSR_PWCL = FIELD_DP64(host->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps); for (n = 0; n < 4; n++) { - 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); + host->CSR_DMW[n] = FIELD_DP64(host->CSR_DMW[n], CSR_DMW, PLV0, 0); + host->CSR_DMW[n] = FIELD_DP64(host->CSR_DMW[n], CSR_DMW, PLV1, 0); + host->CSR_DMW[n] = FIELD_DP64(host->CSR_DMW[n], CSR_DMW, PLV2, 0); + host->CSR_DMW[n] = FIELD_DP64(host->CSR_DMW[n], CSR_DMW, PLV3, 0); + } + if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LVZ)) { + host->CSR_GSTAT = FIELD_DP64(host->CSR_GSTAT, CSR_GSTAT, GIDBIT, 8); } #ifndef CONFIG_USER_ONLY env->pc = 0x1c000000; #ifdef CONFIG_TCG - memset(env->tlb, 0, sizeof(env->tlb)); + memset(host->tlb, 0, sizeof(host->tlb)); #endif if (kvm_enabled()) { kvm_arch_reset_vcpu(cs); -- 2.55.0
