target/mips: Only update MVPControl.EVP bit if executed by master VPE
According to the 'MIPS MT Application-Specific Extension' manual:
If the VPE executing the instruction is not a Master VPE,
with the MVP bit of the VPEConf0 register set, the EVP bit
is unchanged by the instruction.
Modify the DVPE/EVPE opcodes to only update the MVPControl.EVP bit
if executed on a master VPE.
Cc: qemu-stable@nongnu.org
Reported-by: Hansni Bu
Buglink: https://bugs.launchpad.net/qemu/+bug/1926277
Fixes: f249412c74 ("mips: Add MT halting and waking of VPEs")
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Message-ID: <20210427133343.159718-1-f4bug@amsat.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
parent
c017386f28
commit
e895095c78
1 changed files with 18 additions and 14 deletions
|
|
@ -1562,12 +1562,14 @@ target_ulong helper_dvpe(CPUMIPSState *env)
|
|||
CPUState *other_cs = first_cpu;
|
||||
target_ulong prev = env->mvp->CP0_MVPControl;
|
||||
|
||||
CPU_FOREACH(other_cs) {
|
||||
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
|
||||
/* Turn off all VPEs except the one executing the dvpe. */
|
||||
if (&other_cpu->env != env) {
|
||||
other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
|
||||
mips_vpe_sleep(other_cpu);
|
||||
if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
|
||||
CPU_FOREACH(other_cs) {
|
||||
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
|
||||
/* Turn off all VPEs except the one executing the dvpe. */
|
||||
if (&other_cpu->env != env) {
|
||||
other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
|
||||
mips_vpe_sleep(other_cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
|
|
@ -1578,15 +1580,17 @@ target_ulong helper_evpe(CPUMIPSState *env)
|
|||
CPUState *other_cs = first_cpu;
|
||||
target_ulong prev = env->mvp->CP0_MVPControl;
|
||||
|
||||
CPU_FOREACH(other_cs) {
|
||||
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
|
||||
if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
|
||||
CPU_FOREACH(other_cs) {
|
||||
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
|
||||
|
||||
if (&other_cpu->env != env
|
||||
/* If the VPE is WFI, don't disturb its sleep. */
|
||||
&& !mips_vpe_is_wfi(other_cpu)) {
|
||||
/* Enable the VPE. */
|
||||
other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
|
||||
mips_vpe_wake(other_cpu); /* And wake it up. */
|
||||
if (&other_cpu->env != env
|
||||
/* If the VPE is WFI, don't disturb its sleep. */
|
||||
&& !mips_vpe_is_wfi(other_cpu)) {
|
||||
/* Enable the VPE. */
|
||||
other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
|
||||
mips_vpe_wake(other_cpu); /* And wake it up. */
|
||||
}
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue