mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-30 23:10:38 +00:00
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:
commit
aa14de0866
2
.mailmap
2
.mailmap
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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'))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
#include "cpu.h"
|
||||
|
||||
static int mips_um_ksegs;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user