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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAl/WdywACgkQ4+MsLN6t
 wN4uTBAAzixGUFev/av6nKdy1gGY/ZUfA5wC+FwZDIbdiEB2gYrxwcKGWoq5bu4V
 5oGVR/de5NgJRY+cX/YKdI4sYdu19a4uj8ntZZnBNM/GmQ+4CpLuykWRbzwlSnDf
 bDKvxNXtVdVmIf/8TkQ9vARWh9KvvRPxGt5HE6XFxws+Ky859Zf/YOdDTCefjCmQ
 GO0QaBOssGhs5LdFDOUCTBJ9C+J657nKU+0SIJbAlkB3LWq5cND3cZk+g3VFUdER
 ZnK+gJiDaTomo0F6HT9xbVy+lDoMqtJ7PV6QENpjTYU/bq67ddbGY3/wZL22XBLX
 penGD+MqMJhQBqVhsQE3NPn+K8GwlP/7Cg5w0xWW3h5mz5o98hBuqsTUqe2IPeVv
 wdx8e/OGAfTn9Qx0DE1iHd0V1VgV/Iq9/GShQDXulMBUHr2AcbgiYI5GEwuKLsrB
 uTUA6x6V8VlAz4U+34FMFIViJmrPv+8kF4S22kTfV7U20X06ralGBkx8wq6HqMwJ
 LSYPiglzrMfiWUKyPr2HixbqicWotyYq2+++pSrvy3xsrQDfy9OHCOoCj4z0VGn7
 YPkX/4UfIoxhOo+37QN5uAkZMFA/z9fij01YYd70yuNJqulD2Hwn25oeo90WVO98
 pPExXE2ABw02hcHHAV0iYZpYK34k65Ewii57xLA+CE081ezdqyc=
 =tGmL
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2020-12-14 18:53:30 +00:00
commit aa14de0866
19 changed files with 378 additions and 376 deletions

View File

@ -49,6 +49,8 @@ Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@linaro.org>

View File

@ -389,7 +389,7 @@ S: Maintained
F: target/arm/kvm.c
MIPS KVM CPUs
M: Huacai Chen <chenhc@lemote.com>
M: Huacai Chen <chenhuacai@kernel.org>
S: Odd Fixes
F: target/mips/kvm.c
@ -1151,7 +1151,7 @@ F: hw/mips/mipssim.c
F: hw/net/mipsnet.c
Fuloong 2E
M: Huacai Chen <chenhc@lemote.com>
M: Huacai Chen <chenhuacai@kernel.org>
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Odd Fixes
@ -1161,7 +1161,7 @@ F: hw/pci-host/bonito.c
F: include/hw/isa/vt82c686.h
Loongson-3 virtual platforms
M: Huacai Chen <chenhc@lemote.com>
M: Huacai Chen <chenhuacai@kernel.org>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Maintained
F: hw/intc/loongson_liointc.c
@ -2876,7 +2876,7 @@ F: disas/i386.c
MIPS TCG target
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
R: Aurelien Jarno <aurelien@aurel32.net>
R: Huacai Chen <chenhc@lemote.com>
R: Huacai Chen <chenhuacai@kernel.org>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Odd Fixes

View File

@ -28,7 +28,6 @@
#include "hw/loader.h"
#include "hw/loader-fit.h"
#include "hw/mips/cps.h"
#include "hw/mips/cpudevs.h"
#include "hw/pci-host/xilinx-pcie.h"
#include "hw/qdev-clock.h"
#include "hw/qdev-properties.h"
@ -459,12 +458,12 @@ static void boston_mach_init(MachineState *machine)
s = BOSTON(dev);
s->mach = machine;
if (!cpu_supports_cps_smp(machine->cpu_type)) {
if (!cpu_type_supports_cps_smp(machine->cpu_type)) {
error_report("Boston requires CPUs which support CPS");
exit(1);
}
is_64b = cpu_supports_isa(machine->cpu_type, ISA_MIPS64);
is_64b = cpu_type_supports_isa(machine->cpu_type, ISA_MIPS64);
object_initialize_child(OBJECT(machine), "cps", &s->cps, TYPE_MIPS_CPS);
object_property_set_str(OBJECT(&s->cps), "cpu-type", machine->cpu_type,

View File

@ -58,8 +58,7 @@ static void main_cpu_reset(void *opaque)
static bool cpu_mips_itu_supported(CPUMIPSState *env)
{
bool is_mt = (env->CP0_Config5 & (1 << CP0C5_VP)) ||
(env->CP0_Config3 & (1 << CP0C3_MT));
bool is_mt = (env->CP0_Config5 & (1 << CP0C5_VP)) || ase_mt_available(env);
return is_mt && !kvm_enabled();
}

View File

@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/bitops.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "cpu.h"
@ -1135,8 +1136,13 @@ static void malta_mips_config(MIPSCPU *cpu)
CPUMIPSState *env = &cpu->env;
CPUState *cs = CPU(cpu);
env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
if (ase_mt_available(env)) {
env->mvp->CP0_MVPConf0 = deposit32(env->mvp->CP0_MVPConf0,
CP0MVPC0_PTC, 8,
smp_cpus * cs->nr_threads - 1);
env->mvp->CP0_MVPConf0 = deposit32(env->mvp->CP0_MVPConf0,
CP0MVPC0_PVPE, 4, smp_cpus - 1);
}
}
static void main_cpu_reset(void *opaque)
@ -1205,7 +1211,7 @@ static void create_cps(MachineState *ms, MaltaState *s,
static void mips_create_cpu(MachineState *ms, MaltaState *s,
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
{
if ((ms->smp.cpus > 1) && cpu_supports_cps_smp(ms->cpu_type)) {
if ((ms->smp.cpus > 1) && cpu_type_supports_cps_smp(ms->cpu_type)) {
create_cps(ms, s, cbus_irq, i8259_irq);
} else {
create_cpu_without_cps(ms, s, cbus_irq, i8259_irq);
@ -1309,7 +1315,7 @@ void mips_malta_init(MachineState *machine)
loaderparams.initrd_filename = initrd_filename;
kernel_entry = load_kernel();
if (!cpu_supports_isa(machine->cpu_type, ISA_NANOMIPS32)) {
if (!cpu_type_supports_isa(machine->cpu_type, ISA_NANOMIPS32)) {
write_bootloader(memory_region_get_ram_ptr(bios),
bootloader_run_addr, kernel_entry);
} else {

View File

@ -1,5 +1,5 @@
mips_ss = ss.source_set()
mips_ss.add(files('addr.c', 'mips_int.c'))
mips_ss.add(files('mips_int.c'))
mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))

View File

@ -5,13 +5,6 @@
/* Definitions for MIPS CPU internal devices. */
/* 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_irq_init_cpu(MIPSCPU *cpu);

View File

@ -21,7 +21,7 @@
*/
#include "qemu/osdep.h"
#include "hw/mips/cpudevs.h"
#include "cpu.h"
static int mips_um_ksegs;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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',

View File

@ -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"
/*****************************************************************************/

View File

@ -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)
{

View File

@ -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