diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-12-14 18:53:30 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-12-14 18:53:30 +0000 |
commit | aa14de086675280206dbc1849da6f85b75f62f1b (patch) | |
tree | 39640303cb223ea8e72474b27d375cdb14131609 /target/mips | |
parent | 37f04b71a9cd62ca0f2d24a70fe843619ad45cd0 (diff) | |
parent | 3533ee301c46620fd5699cb97f2d4bd194fe0c24 (diff) |
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/mips-20201213' into staging
MIPS patches queue
. Allow executing MSA instructions on Loongson-3A4000
. Update Huacai Chen email address
. Various cleanups:
- unused headers removal
- use definitions instead of magic values
- remove dead code
- avoid calling unused code
. Various code movements
CI jobs results:
https://gitlab.com/philmd/qemu/-/pipelines/229120169
https://cirrus-ci.com/build/4857731557359616
# gpg: Signature made Sun 13 Dec 2020 20:18:52 GMT
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* remotes/philmd-gitlab/tags/mips-20201213: (26 commits)
target/mips: Use FloatRoundMode enum for FCR31 modes conversion
target/mips: Remove unused headers from fpu_helper.c
target/mips: Inline cpu_mips_realize_env() in mips_cpu_realizefn()
target/mips: Move cpu definitions, reset() and realize() to cpu.c
target/mips: Move mips_cpu_add_definition() from helper.c to cpu.c
target/mips: Extract cpu_supports*/cpu_set* translate.c
hw/mips/malta: Rewrite CP0_MVPConf0 access using deposit()
hw/mips/malta: Do not initialize MT registers if MT ASE absent
target/mips: Do not initialize MT registers if MT ASE absent
target/mips: Introduce ase_mt_available() helper
target/mips: Remove mips_def_t unused argument from mvp_init()
target/mips: Remove unused headers from op_helper.c
target/mips: Remove unused headers from translate.c
hw/mips: Move address translation helpers to target/mips/
target/mips: Introduce cpu_supports_isa() taking CPUMIPSState argument
target/mips: Rename cpu_supports_FEAT() as cpu_type_supports_FEAT()
target/mips: Explicit Release 6 MMU types
target/mips: Allow executing MSA instructions on Loongson-3A4000
target/mips: Also display exception names in user-mode
target/mips: Remove unused headers from cp0_helper.c
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/mips')
-rw-r--r-- | target/mips/addr.c | 51 | ||||
-rw-r--r-- | target/mips/cp0_helper.c | 15 | ||||
-rw-r--r-- | target/mips/cpu.c | 299 | ||||
-rw-r--r-- | target/mips/cpu.h | 20 | ||||
-rw-r--r-- | target/mips/fpu_helper.c | 6 | ||||
-rw-r--r-- | target/mips/helper.c | 64 | ||||
-rw-r--r-- | target/mips/internal.h | 17 | ||||
-rw-r--r-- | target/mips/kvm.c | 11 | ||||
-rw-r--r-- | target/mips/meson.build | 3 | ||||
-rw-r--r-- | target/mips/op_helper.c | 4 | ||||
-rw-r--r-- | target/mips/translate.c | 262 | ||||
-rw-r--r-- | target/mips/translate_init.c.inc | 10 |
12 files changed, 408 insertions, 354 deletions
diff --git a/target/mips/addr.c b/target/mips/addr.c new file mode 100644 index 0000000000..27a6036c45 --- /dev/null +++ b/target/mips/addr.c @@ -0,0 +1,51 @@ +/* + * QEMU MIPS address translation support + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "cpu.h" + +static int mips_um_ksegs; + +uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr) +{ + return addr & 0x1fffffffll; +} + +uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr) +{ + return addr | ~0x7fffffffll; +} + +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr) +{ + return addr | 0x40000000ll; +} + +bool mips_um_ksegs_enabled(void) +{ + return mips_um_ksegs; +} + +void mips_um_ksegs_enable(void) +{ + mips_um_ksegs = 1; +} diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c index a1b5140cca..36a92857bf 100644 --- a/target/mips/cp0_helper.c +++ b/target/mips/cp0_helper.c @@ -21,18 +21,15 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "qemu/main-loop.h" #include "cpu.h" #include "internal.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" -#include "exec/cpu_ldst.h" -#include "exec/memop.h" -#include "sysemu/kvm.h" -#ifndef CONFIG_USER_ONLY /* SMP helpers. */ static bool mips_vpe_is_wfi(MIPSCPU *c) { @@ -904,7 +901,7 @@ void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask) goto invalid; } /* We don't support VTLB entry smaller than target page */ - if ((maskbits + 12) < TARGET_PAGE_BITS) { + if ((maskbits + TARGET_PAGE_BITS_MIN) < TARGET_PAGE_BITS) { goto invalid; } env->CP0_PageMask = mask << CP0PM_MASK; @@ -913,7 +910,8 @@ void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask) invalid: /* When invalid, set to default target page size. */ - env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK; + mask = (~TARGET_PAGE_MASK >> TARGET_PAGE_BITS_MIN); + env->CP0_PageMask = mask << CP0PM_MASK; } void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1) @@ -1166,7 +1164,7 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) old = env->CP0_EntryHi; val = (arg1 & mask) | (old & ~mask); env->CP0_EntryHi = val; - if (env->CP0_Config3 & (1 << CP0C3_MT)) { + if (ase_mt_available(env)) { sync_c0_entryhi(env, env->current_tc); } /* If the ASID changes, flush qemu's TLB. */ @@ -1666,10 +1664,8 @@ target_ulong helper_evpe(CPUMIPSState *env) } return prev; } -#endif /* !CONFIG_USER_ONLY */ /* R6 Multi-threading */ -#ifndef CONFIG_USER_ONLY target_ulong helper_dvp(CPUMIPSState *env) { CPUState *other_cs = first_cpu; @@ -1708,4 +1704,3 @@ target_ulong helper_evp(CPUMIPSState *env) } return prev; } -#endif /* !CONFIG_USER_ONLY */ diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 76d50b00b4..aadc6f8e74 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" +#include "qemu/qemu-print.h" #include "qapi/error.h" #include "cpu.h" #include "internal.h" @@ -30,6 +31,8 @@ #include "exec/exec-all.h" #include "hw/qdev-properties.h" #include "hw/qdev-clock.h" +#include "hw/semihosting/semihost.h" +#include "qapi/qapi-commands-machine-target.h" static void mips_cpu_set_pc(CPUState *cs, vaddr value) { @@ -74,7 +77,7 @@ static bool mips_cpu_has_work(CPUState *cs) } /* MIPS-MT has the ability to halt the CPU. */ - if (env->CP0_Config3 & (1 << CP0C3_MT)) { + if (ase_mt_available(env)) { /* * The QEMU model will issue an _WAKE request whenever the CPUs * should be woken up. @@ -99,6 +102,236 @@ static bool mips_cpu_has_work(CPUState *cs) return has_work; } +#include "translate_init.c.inc" + +/* TODO QOM'ify CPU reset and remove */ +static void cpu_state_reset(CPUMIPSState *env) +{ + CPUState *cs = env_cpu(env); + + /* Reset registers to their default values */ + env->CP0_PRid = env->cpu_model->CP0_PRid; + env->CP0_Config0 = env->cpu_model->CP0_Config0; +#ifdef TARGET_WORDS_BIGENDIAN + env->CP0_Config0 |= (1 << CP0C0_BE); +#endif + env->CP0_Config1 = env->cpu_model->CP0_Config1; + env->CP0_Config2 = env->cpu_model->CP0_Config2; + env->CP0_Config3 = env->cpu_model->CP0_Config3; + env->CP0_Config4 = env->cpu_model->CP0_Config4; + env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask; + env->CP0_Config5 = env->cpu_model->CP0_Config5; + env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask; + env->CP0_Config6 = env->cpu_model->CP0_Config6; + env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask; + env->CP0_Config7 = env->cpu_model->CP0_Config7; + env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask; + env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask + << env->cpu_model->CP0_LLAddr_shift; + env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift; + env->SYNCI_Step = env->cpu_model->SYNCI_Step; + env->CCRes = env->cpu_model->CCRes; + env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask; + env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask; + env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl; + env->current_tc = 0; + env->SEGBITS = env->cpu_model->SEGBITS; + env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1); +#if defined(TARGET_MIPS64) + if (env->cpu_model->insn_flags & ISA_MIPS3) { + env->SEGMask |= 3ULL << 62; + } +#endif + env->PABITS = env->cpu_model->PABITS; + env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask; + env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0; + env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask; + env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1; + env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask; + env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2; + env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask; + env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3; + env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask; + env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4; + env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; + env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; + env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; + env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; + env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; + env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; + env->msair = env->cpu_model->MSAIR; + env->insn_flags = env->cpu_model->insn_flags; + +#if defined(CONFIG_USER_ONLY) + env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU); +# ifdef TARGET_MIPS64 + /* Enable 64-bit register mode. */ + env->CP0_Status |= (1 << CP0St_PX); +# endif +# ifdef TARGET_ABI_MIPSN64 + /* Enable 64-bit address mode. */ + env->CP0_Status |= (1 << CP0St_UX); +# endif + /* + * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR + * hardware registers. + */ + env->CP0_HWREna |= 0x0000000F; + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + env->CP0_Status |= (1 << CP0St_CU1); + } + if (env->CP0_Config3 & (1 << CP0C3_DSPP)) { + env->CP0_Status |= (1 << CP0St_MX); + } +# if defined(TARGET_MIPS64) + /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */ + if ((env->CP0_Config1 & (1 << CP0C1_FP)) && + (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { + env->CP0_Status |= (1 << CP0St_FR); + } +# endif +#else /* !CONFIG_USER_ONLY */ + if (env->hflags & MIPS_HFLAG_BMASK) { + /* + * If the exception was raised from a delay slot, + * come back to the jump. + */ + env->CP0_ErrorEPC = (env->active_tc.PC + - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4)); + } else { + env->CP0_ErrorEPC = env->active_tc.PC; + } + env->active_tc.PC = env->exception_base; + env->CP0_Random = env->tlb->nb_tlb - 1; + env->tlb->tlb_in_use = env->tlb->nb_tlb; + env->CP0_Wired = 0; + env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; + env->CP0_EBase = (cs->cpu_index & 0x3FF); + if (mips_um_ksegs_enabled()) { + env->CP0_EBase |= 0x40000000; + } else { + env->CP0_EBase |= (int32_t)0x80000000; + } + if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { + env->CP0_CMGCRBase = 0x1fbf8000 >> 4; + } + env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ? + 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff; + env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); + /* + * Vectored interrupts not implemented, timer on int 7, + * no performance counters. + */ + env->CP0_IntCtl = 0xe0000000; + { + int i; + + for (i = 0; i < 7; i++) { + env->CP0_WatchLo[i] = 0; + env->CP0_WatchHi[i] = 0x80000000; + } + env->CP0_WatchLo[7] = 0; + env->CP0_WatchHi[7] = 0; + } + /* Count register increments in debug mode, EJTAG version 1 */ + env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); + + cpu_mips_store_count(env, 1); + + if (ase_mt_available(env)) { + int i; + + /* Only TC0 on VPE 0 starts as active. */ + for (i = 0; i < ARRAY_SIZE(env->tcs); i++) { + env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE; + env->tcs[i].CP0_TCHalt = 1; + } + env->active_tc.CP0_TCHalt = 1; + cs->halted = 1; + + if (cs->cpu_index == 0) { + /* VPE0 starts up enabled. */ + env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); + env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); + + /* TC0 starts up unhalted. */ + cs->halted = 0; + env->active_tc.CP0_TCHalt = 0; + env->tcs[0].CP0_TCHalt = 0; + /* With thread 0 active. */ + env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A); + env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A); + } + } + + /* + * Configure default legacy segmentation control. We use this regardless of + * whether segmentation control is presented to the guest. + */ + /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */ + env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM); + /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */ + env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16; + /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */ + env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) | + (2 << CP0SC_C); + /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */ + env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) | + (3 << CP0SC_C)) << 16; + /* USeg (seg4 0x40000000..0x7FFFFFFF) */ + env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) | + (1 << CP0SC_EU) | (2 << CP0SC_C); + /* USeg (seg5 0x00000000..0x3FFFFFFF) */ + env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) | + (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16; + /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */ + env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM); +#endif /* !CONFIG_USER_ONLY */ + if ((env->insn_flags & ISA_MIPS32R6) && + (env->active_fpu.fcr0 & (1 << FCR0_F64))) { + /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */ + env->CP0_Status |= (1 << CP0St_FR); + } + + if (env->insn_flags & ISA_MIPS32R6) { + /* PTW = 1 */ + env->CP0_PWSize = 0x40; + /* GDI = 12 */ + /* UDI = 12 */ + /* MDI = 12 */ + /* PRI = 12 */ + /* PTEI = 2 */ + env->CP0_PWField = 0x0C30C302; + } else { + /* GDI = 0 */ + /* UDI = 0 */ + /* MDI = 0 */ + /* PRI = 0 */ + /* PTEI = 2 */ + env->CP0_PWField = 0x02; + } + + if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) { + /* microMIPS on reset when Config3.ISA is 3 */ + env->hflags |= MIPS_HFLAG_M16; + } + + /* MSA */ + if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { + msa_reset(env); + } + + compute_hflags(env); + restore_fp_status(env); + restore_pamask(env); + cs->exception_index = EXCP_NONE; + + if (semihosting_get_argc()) { + /* UHI interface can be used to obtain argc and argv */ + env->active_tc.gpr[4] = -1; + } +} + static void mips_cpu_reset(DeviceState *dev) { CPUState *s = CPU(dev); @@ -156,6 +389,7 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); MIPSCPU *cpu = MIPS_CPU(dev); + CPUMIPSState *env = &cpu->env; MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); Error *local_err = NULL; @@ -179,7 +413,13 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) return; } - cpu_mips_realize_env(&cpu->env); + env->exception_base = (int32_t)0xBFC00000; + +#ifndef CONFIG_USER_ONLY + mmu_init(env, env->cpu_model); +#endif + fpu_init(env, env->cpu_model); + mvp_init(env); cpu_reset(cs); qemu_init_vcpu(cs); @@ -299,6 +539,38 @@ static void mips_cpu_register_types(void) type_init(mips_cpu_register_types) +static void mips_cpu_add_definition(gpointer data, gpointer user_data) +{ + ObjectClass *oc = data; + CpuDefinitionInfoList **cpu_list = user_data; + CpuDefinitionInfoList *entry; + CpuDefinitionInfo *info; + const char *typename; + + typename = object_class_get_name(oc); + info = g_malloc0(sizeof(*info)); + info->name = g_strndup(typename, + strlen(typename) - strlen("-" TYPE_MIPS_CPU)); + info->q_typename = g_strdup(typename); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = *cpu_list; + *cpu_list = entry; +} + +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + CpuDefinitionInfoList *cpu_list = NULL; + GSList *list; + + list = object_class_get_list(TYPE_MIPS_CPU, false); + g_slist_foreach(list, mips_cpu_add_definition, &cpu_list); + g_slist_free(list); + + return cpu_list; +} + /* Could be used by generic CPU object */ MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) { @@ -310,3 +582,26 @@ MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) return MIPS_CPU(cpu); } + +bool cpu_supports_isa(const CPUMIPSState *env, uint64_t isa_mask) +{ + return (env->cpu_model->insn_flags & isa_mask) != 0; +} + +bool cpu_type_supports_isa(const char *cpu_type, uint64_t isa) +{ + const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); + return (mcc->cpu_def->insn_flags & isa) != 0; +} + +bool cpu_type_supports_cps_smp(const char *cpu_type) +{ + const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); + return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0; +} + +void cpu_set_exception_base(int vp_index, target_ulong address) +{ + MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index)); + vp->env.exception_base = address; +} diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 23f8c6f96c..3ac21d0e9c 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1286,10 +1286,26 @@ int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc); #define MIPS_CPU_TYPE_NAME(model) model MIPS_CPU_TYPE_SUFFIX #define CPU_RESOLVING_TYPE TYPE_MIPS_CPU -bool cpu_supports_cps_smp(const char *cpu_type); -bool cpu_supports_isa(const char *cpu_type, uint64_t isa); +bool cpu_type_supports_cps_smp(const char *cpu_type); +bool cpu_supports_isa(const CPUMIPSState *env, uint64_t isa_mask); +bool cpu_type_supports_isa(const char *cpu_type, uint64_t isa); + +/* Check presence of multi-threading ASE implementation */ +static inline bool ase_mt_available(CPUMIPSState *env) +{ + return env->CP0_Config3 & (1 << CP0C3_MT); +} + void cpu_set_exception_base(int vp_index, target_ulong address); +/* addr.c */ +uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr); +uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr); + +uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); +bool mips_um_ksegs_enabled(void); +void mips_um_ksegs_enable(void); + /* mips_int.c */ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index 020b768e87..bdb65065ee 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -21,15 +21,11 @@ */ #include "qemu/osdep.h" -#include "qemu/main-loop.h" #include "cpu.h" #include "internal.h" -#include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" -#include "exec/memop.h" -#include "sysemu/kvm.h" #include "fpu/softfloat.h" @@ -42,7 +38,7 @@ #define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL /* convert MIPS rounding mode in FCR31 to IEEE library */ -unsigned int ieee_rm[] = { +const FloatRoundMode ieee_rm[4] = { float_round_nearest_even, float_round_to_zero, float_round_up, diff --git a/target/mips/helper.c b/target/mips/helper.c index 063b65c052..87296fbad6 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -24,7 +24,6 @@ #include "exec/cpu_ldst.h" #include "exec/log.h" #include "hw/mips/cpudevs.h" -#include "qapi/qapi-commands-machine-target.h" enum { TLBRET_XI = -6, @@ -419,7 +418,7 @@ void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) tlb_flush(env_cpu(env)); } #endif - if (env->CP0_Config3 & (1 << CP0C3_MT)) { + if (ase_mt_available(env)) { sync_c0_status(env, env, env->current_tc); } else { compute_hflags(env); @@ -858,8 +857,8 @@ refill: break; } } - pw_pagemask = m >> 12; - update_pagemask(env, pw_pagemask << 13, &pw_pagemask); + pw_pagemask = m >> TARGET_PAGE_BITS_MIN; + update_pagemask(env, pw_pagemask << CP0PM_MASK, &pw_pagemask); pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF); { target_ulong tmp_entryhi = env->CP0_EntryHi; @@ -978,6 +977,7 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, return physical; } } +#endif /* !CONFIG_USER_ONLY */ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_RESET] = "reset", @@ -1018,7 +1018,14 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_MSADIS] = "MSA disabled", [EXCP_MSAFPE] = "MSA floating point", }; -#endif + +static const char *mips_exception_name(int32_t exception) +{ + if (exception < 0 || exception > EXCP_LAST) { + return "unknown"; + } + return excp_names[exception]; +} target_ulong exception_resume_pc(CPUMIPSState *env) { @@ -1091,19 +1098,13 @@ void mips_cpu_do_interrupt(CPUState *cs) bool update_badinstr = 0; target_ulong offset; int cause = -1; - const char *name; if (qemu_loglevel_mask(CPU_LOG_INT) && cs->exception_index != EXCP_EXT_INTERRUPT) { - if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) { - name = "unknown"; - } else { - name = excp_names[cs->exception_index]; - } - qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", - __func__, env->active_tc.PC, env->CP0_EPC, name); + __func__, env->active_tc.PC, env->CP0_EPC, + mips_exception_name(cs->exception_index)); } if (cs->exception_index == EXCP_EXT_INTERRUPT && (env->hflags & MIPS_HFLAG_DM)) { @@ -1490,42 +1491,11 @@ void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, { CPUState *cs = env_cpu(env); - qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", - __func__, exception, error_code); + qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n", + __func__, exception, mips_exception_name(exception), + error_code); cs->exception_index = exception; env->error_code = error_code; cpu_loop_exit_restore(cs, pc); } - -static void mips_cpu_add_definition(gpointer data, gpointer user_data) -{ - ObjectClass *oc = data; - CpuDefinitionInfoList **cpu_list = user_data; - CpuDefinitionInfoList *entry; - CpuDefinitionInfo *info; - const char *typename; - - typename = object_class_get_name(oc); - info = g_malloc0(sizeof(*info)); - info->name = g_strndup(typename, - strlen(typename) - strlen("-" TYPE_MIPS_CPU)); - info->q_typename = g_strdup(typename); - - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = *cpu_list; - *cpu_list = entry; -} - -CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) -{ - CpuDefinitionInfoList *cpu_list = NULL; - GSList *list; - - list = object_class_get_list(TYPE_MIPS_CPU, false); - g_slist_foreach(list, mips_cpu_add_definition, &cpu_list); - g_slist_free(list); - - return cpu_list; -} diff --git a/target/mips/internal.h b/target/mips/internal.h index dd8a7809b6..e4d2d9f44f 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -8,6 +8,7 @@ #ifndef MIPS_INTERNAL_H #define MIPS_INTERNAL_H +#include "exec/memattrs.h" #include "fpu/softfloat-helpers.h" /* @@ -15,10 +16,11 @@ * CP0C0_MT field. */ enum mips_mmu_types { - MMU_TYPE_NONE, - MMU_TYPE_R4000, - MMU_TYPE_RESERVED, - MMU_TYPE_FMT, + MMU_TYPE_NONE = 0, + MMU_TYPE_R4000 = 1, /* Standard TLB */ + MMU_TYPE_BAT = 2, /* Block Address Translation */ + MMU_TYPE_FMT = 3, /* Fixed Mapping */ + MMU_TYPE_DVF = 4, /* Dual VTLB and FTLB */ MMU_TYPE_R3000, MMU_TYPE_R6000, MMU_TYPE_R8000 @@ -205,10 +207,6 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) void mips_tcg_init(void); -/* TODO QOM'ify CPU reset and remove */ -void cpu_state_reset(CPUMIPSState *s); -void cpu_mips_realize_env(CPUMIPSState *env); - /* cp0_timer.c */ uint32_t cpu_mips_get_count(CPUMIPSState *env); void cpu_mips_store_count(CPUMIPSState *env, uint32_t value); @@ -225,7 +223,8 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, uint32_t float_class_s(uint32_t arg, float_status *fst); uint64_t float_class_d(uint64_t arg, float_status *fst); -extern unsigned int ieee_rm[]; +extern const FloatRoundMode ieee_rm[4]; + void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask); static inline void restore_rounding_mode(CPUMIPSState *env) diff --git a/target/mips/kvm.c b/target/mips/kvm.c index 72637a1e02..477692566a 100644 --- a/target/mips/kvm.c +++ b/target/mips/kvm.c @@ -19,13 +19,10 @@ #include "internal.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" -#include "qemu/timer.h" #include "sysemu/kvm.h" #include "sysemu/kvm_int.h" #include "sysemu/runstate.h" -#include "sysemu/cpus.h" #include "kvm_mips.h" -#include "exec/memattrs.h" #include "hw/boards.h" #define DEBUG_KVM 0 @@ -198,9 +195,7 @@ int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level) CPUState *cs = CPU(cpu); struct kvm_mips_interrupt intr; - if (!kvm_enabled()) { - return 0; - } + assert(kvm_enabled()); intr.cpu = -1; @@ -221,9 +216,7 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level) CPUState *dest_cs = CPU(cpu); struct kvm_mips_interrupt intr; - if (!kvm_enabled()) { - return 0; - } + assert(kvm_enabled()); intr.cpu = dest_cs->cpu_index; diff --git a/target/mips/meson.build b/target/mips/meson.build index fa1f024e78..4179395a8e 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -1,6 +1,5 @@ mips_ss = ss.source_set() mips_ss.add(files( - 'cp0_helper.c', 'cpu.c', 'dsp_helper.c', 'fpu_helper.c', @@ -15,6 +14,8 @@ mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) mips_softmmu_ss = ss.source_set() mips_softmmu_ss.add(files( + 'addr.c', + 'cp0_helper.c', 'cp0_timer.c', 'machine.c', 'mips-semi.c', diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 5184a1838b..5aa97902e9 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -19,15 +19,11 @@ */ #include "qemu/osdep.h" -#include "qemu/main-loop.h" #include "cpu.h" #include "internal.h" -#include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" -#include "exec/cpu_ldst.h" #include "exec/memop.h" -#include "sysemu/kvm.h" /*****************************************************************************/ diff --git a/target/mips/translate.c b/target/mips/translate.c index c64a1bc42e..19933b7868 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -24,12 +24,8 @@ #include "qemu/osdep.h" #include "cpu.h" #include "internal.h" -#include "disas/disas.h" -#include "exec/exec-all.h" #include "tcg/tcg-op.h" #include "exec/cpu_ldst.h" -#include "hw/mips/cpudevs.h" - #include "exec/helper-proto.h" #include "exec/helper-gen.h" #include "hw/semihosting/semihost.h" @@ -31757,264 +31753,6 @@ void mips_tcg_init(void) #endif } -#include "translate_init.c.inc" - -void cpu_mips_realize_env(CPUMIPSState *env) -{ - env->exception_base = (int32_t)0xBFC00000; - -#ifndef CONFIG_USER_ONLY - mmu_init(env, env->cpu_model); -#endif - fpu_init(env, env->cpu_model); - mvp_init(env, env->cpu_model); -} - -bool cpu_supports_cps_smp(const char *cpu_type) -{ - const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); - return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0; -} - -bool cpu_supports_isa(const char *cpu_type, uint64_t isa) -{ - const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); - return (mcc->cpu_def->insn_flags & isa) != 0; -} - -void cpu_set_exception_base(int vp_index, target_ulong address) -{ - MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index)); - vp->env.exception_base = address; -} - -void cpu_state_reset(CPUMIPSState *env) -{ - CPUState *cs = env_cpu(env); - - /* Reset registers to their default values */ - env->CP0_PRid = env->cpu_model->CP0_PRid; - env->CP0_Config0 = env->cpu_model->CP0_Config0; -#ifdef TARGET_WORDS_BIGENDIAN - env->CP0_Config0 |= (1 << CP0C0_BE); -#endif - env->CP0_Config1 = env->cpu_model->CP0_Config1; - env->CP0_Config2 = env->cpu_model->CP0_Config2; - env->CP0_Config3 = env->cpu_model->CP0_Config3; - env->CP0_Config4 = env->cpu_model->CP0_Config4; - env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask; - env->CP0_Config5 = env->cpu_model->CP0_Config5; - env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask; - env->CP0_Config6 = env->cpu_model->CP0_Config6; - env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask; - env->CP0_Config7 = env->cpu_model->CP0_Config7; - env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask; - env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask - << env->cpu_model->CP0_LLAddr_shift; - env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift; - env->SYNCI_Step = env->cpu_model->SYNCI_Step; - env->CCRes = env->cpu_model->CCRes; - env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask; - env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask; - env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl; - env->current_tc = 0; - env->SEGBITS = env->cpu_model->SEGBITS; - env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1); -#if defined(TARGET_MIPS64) - if (env->cpu_model->insn_flags & ISA_MIPS3) { - env->SEGMask |= 3ULL << 62; - } -#endif - env->PABITS = env->cpu_model->PABITS; - env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask; - env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0; - env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask; - env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1; - env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask; - env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2; - env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask; - env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3; - env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask; - env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4; - env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; - env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; - env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; - env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; - env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; - env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; - env->msair = env->cpu_model->MSAIR; - env->insn_flags = env->cpu_model->insn_flags; - -#if defined(CONFIG_USER_ONLY) - env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU); -# ifdef TARGET_MIPS64 - /* Enable 64-bit register mode. */ - env->CP0_Status |= (1 << CP0St_PX); -# endif -# ifdef TARGET_ABI_MIPSN64 - /* Enable 64-bit address mode. */ - env->CP0_Status |= (1 << CP0St_UX); -# endif - /* - * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR - * hardware registers. - */ - env->CP0_HWREna |= 0x0000000F; - if (env->CP0_Config1 & (1 << CP0C1_FP)) { - env->CP0_Status |= (1 << CP0St_CU1); - } - if (env->CP0_Config3 & (1 << CP0C3_DSPP)) { - env->CP0_Status |= (1 << CP0St_MX); - } -# if defined(TARGET_MIPS64) - /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */ - if ((env->CP0_Config1 & (1 << CP0C1_FP)) && - (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { - env->CP0_Status |= (1 << CP0St_FR); - } -# endif -#else - if (env->hflags & MIPS_HFLAG_BMASK) { - /* - * If the exception was raised from a delay slot, - * come back to the jump. - */ - env->CP0_ErrorEPC = (env->active_tc.PC - - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4)); - } else { - env->CP0_ErrorEPC = env->active_tc.PC; - } - env->active_tc.PC = env->exception_base; - env->CP0_Random = env->tlb->nb_tlb - 1; - env->tlb->tlb_in_use = env->tlb->nb_tlb; - env->CP0_Wired = 0; - env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; - env->CP0_EBase = (cs->cpu_index & 0x3FF); - if (mips_um_ksegs_enabled()) { - env->CP0_EBase |= 0x40000000; - } else { - env->CP0_EBase |= (int32_t)0x80000000; - } - if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { - env->CP0_CMGCRBase = 0x1fbf8000 >> 4; - } - env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ? - 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff; - env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); - /* - * Vectored interrupts not implemented, timer on int 7, - * no performance counters. - */ - env->CP0_IntCtl = 0xe0000000; - { - int i; - - for (i = 0; i < 7; i++) { - env->CP0_WatchLo[i] = 0; - env->CP0_WatchHi[i] = 0x80000000; - } - env->CP0_WatchLo[7] = 0; - env->CP0_WatchHi[7] = 0; - } - /* Count register increments in debug mode, EJTAG version 1 */ - env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); - - cpu_mips_store_count(env, 1); - - if (env->CP0_Config3 & (1 << CP0C3_MT)) { - int i; - - /* Only TC0 on VPE 0 starts as active. */ - for (i = 0; i < ARRAY_SIZE(env->tcs); i++) { - env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE; - env->tcs[i].CP0_TCHalt = 1; - } - env->active_tc.CP0_TCHalt = 1; - cs->halted = 1; - - if (cs->cpu_index == 0) { - /* VPE0 starts up enabled. */ - env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); - env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); - - /* TC0 starts up unhalted. */ - cs->halted = 0; - env->active_tc.CP0_TCHalt = 0; - env->tcs[0].CP0_TCHalt = 0; - /* With thread 0 active. */ - env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A); - env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A); - } - } - - /* - * Configure default legacy segmentation control. We use this regardless of - * whether segmentation control is presented to the guest. - */ - /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */ - env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM); - /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */ - env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16; - /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */ - env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) | - (2 << CP0SC_C); - /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */ - env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) | - (3 << CP0SC_C)) << 16; - /* USeg (seg4 0x40000000..0x7FFFFFFF) */ - env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) | - (1 << CP0SC_EU) | (2 << CP0SC_C); - /* USeg (seg5 0x00000000..0x3FFFFFFF) */ - env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) | - (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16; - /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */ - env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM); -#endif - if ((env->insn_flags & ISA_MIPS32R6) && - (env->active_fpu.fcr0 & (1 << FCR0_F64))) { - /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */ - env->CP0_Status |= (1 << CP0St_FR); - } - - if (env->insn_flags & ISA_MIPS32R6) { - /* PTW = 1 */ - env->CP0_PWSize = 0x40; - /* GDI = 12 */ - /* UDI = 12 */ - /* MDI = 12 */ - /* PRI = 12 */ - /* PTEI = 2 */ - env->CP0_PWField = 0x0C30C302; - } else { - /* GDI = 0 */ - /* UDI = 0 */ - /* MDI = 0 */ - /* PRI = 0 */ - /* PTEI = 2 */ - env->CP0_PWField = 0x02; - } - - if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) { - /* microMIPS on reset when Config3.ISA is 3 */ - env->hflags |= MIPS_HFLAG_M16; - } - - /* MSA */ - if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { - msa_reset(env); - } - - compute_hflags(env); - restore_fp_status(env); - restore_pamask(env); - cs->exception_index = EXCP_NONE; - - if (semihosting_get_argc()) { - /* UHI interface can be used to obtain argc and argv */ - env->active_tc.gpr[4] = -1; - } -} - void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, target_ulong *data) { diff --git a/target/mips/translate_init.c.inc b/target/mips/translate_init.c.inc index ea85d5c6a7..f72fee3b40 100644 --- a/target/mips/translate_init.c.inc +++ b/target/mips/translate_init.c.inc @@ -832,7 +832,7 @@ const mips_def_t mips_defs[] = .mmu_type = MMU_TYPE_R4000, }, { - .name = "Loongson-3A4000", + .name = "Loongson-3A4000", /* GS464V-based */ .CP0_PRid = 0x14C000, /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) | @@ -885,7 +885,7 @@ const mips_def_t mips_defs[] = .CP1_fcr31_rw_bitmask = 0xFF83FFFF, .SEGBITS = 48, .PABITS = 48, - .insn_flags = CPU_LOONGSON3A, + .insn_flags = CPU_LOONGSON3A | ASE_MSA, .mmu_type = MMU_TYPE_R4000, }, { @@ -989,10 +989,14 @@ static void fpu_init (CPUMIPSState *env, const mips_def_t *def) memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu)); } -static void mvp_init (CPUMIPSState *env, const mips_def_t *def) +static void mvp_init(CPUMIPSState *env) { env->mvp = g_malloc0(sizeof(CPUMIPSMVPContext)); + if (!ase_mt_available(env)) { + return; + } + /* MVPConf1 implemented, TLB sharable, no gating storage support, programmable cache partitioning implemented, number of allocatable and shareable TLB entries, MVP has allocatable TCs, 2 VPEs |