MIPS MT dvpe does not regard VPEConf0.MVP
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
QEMU |
Invalid
|
Undecided
|
Unassigned |
Bug Description
Hi,
According to MIPS32® Architecture for Programmers VolumeIV-f: The MIPS® MT Application-Specific Extension to the MIPS32® Architecture, for instruction: dvpe, evpe:
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.
The pseudo code is:
data ← MVPControl
GPR[rt] ← data
if(VPEConf0.MVP = 1) then
MVPControl.EVP ← sc
endif
However the helper functions of dvpe, evpe does not regard the VPEConf0.MVP bit, namely, it does not check if the VPE is a master VPE. Code is copied below as:
target_ulong helper_
{
CPUState *other_cs = first_cpu;
target_ulong prev = env->mvp-
CPU_
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
/* Turn off all VPEs except the one executing the dvpe. */
if (&other_cpu->env != env) {
}
}
return prev;
}
Is this a bug?
QEMU head commit: 0cef06d18762374
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.
Add the VPEConf0.MVP bit and modify the DVPE/EVPE opcodes to only
update the MVPControl.EVP bit if executed on a master VPE.
Reported-by: Hansni Bu /bugs.launchpad .net/qemu/ +bug/1926277 mips/cp0_ helper. c | 32 +++++++ +++++++ ++++--- ------- ----
Buglink: https:/
Fixes: f249412c749 ("mips: Add MT halting and waking of VPEs")
Signed-off-by: Philippe Mathieu-Daudé <email address hidden>
---
target/mips/cpu.h | 1 +
target/
2 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h .bd22fac6959 100644 mips/cp0_ helper. c b/target/ mips/cp0_ helper. c .1e39e28808a 100644 mips/cp0_ helper. c mips/cp0_ helper. c dvpe(CPUMIPSSta te *env) >CP0_MVPControl ;
index 075c24abdad.
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -114,6 +114,7 @@ struct CPUMIPSMVPContext {
#define CP0MVPC0_PTLBE 16
#define CP0MVPC0_TCA 15
#define CP0MVPC0_PVPE 10
+#define CP0MVPC0_MVP 1
#define CP0MVPC0_PTC 0
int32_t CP0_MVPConf1;
#define CP0MVPC1_CIM 31
diff --git a/target/
index aae2af6eccc.
--- a/target/
+++ b/target/
@@ -1635,12 +1635,14 @@ target_ulong helper_
CPUState *other_cs = first_cpu;
target_ulong prev = env->mvp-
- CPU_FOREACH( other_cs) { >env.mvp- >CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); sleep(other_ cpu); >CP0_MVPConf0 & (1 << CP0MVPC0_MVP)) { other_cs) { >env.mvp- >CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); sleep(other_ cpu); evpe(CPUMIPSSta te *env) >CP0_MVPControl ;
- MIPSCPU *other_cpu = MIPS_CPU(other_cs);
- /* Turn off all VPEs except the one executing the dvpe. */
- if (&other_cpu->env != env) {
- other_cpu-
- mips_vpe_
+ if (env->mvp-
+ CPU_FOREACH(
+ MIPSCPU *other_cpu = MIPS_CPU(other_cs);
+ /* Turn off all VPEs except the one executing the dvpe. */
+ if (&other_cpu->env != env) {
+ other_cpu-
+ mips_vpe_
+ }
}
}
return prev;
@@ -1651,15 +1653,17 @@ target_ulong helper_
CPUState *other_cs = first_cpu;
target_ulong prev = env->mvp-
- CPU_FOREACH( other_cs) { >CP0_MVPConf0 & (1 << CP0MVPC0_MVP)) { other_cs) {
- MIPSCPU *other_cpu = MIPS_CPU(other_cs);
+ if (env->mvp-
+ CPU_FOREACH(
+ MIPSCPU *other_cpu = MIPS_CPU(other_cs);
- if (&other_cpu->env != env is_wfi( other_cpu) ) { >env.mvp- >CP0_MVPControl |= (1 << CP0MVPCo_EVP); wake(other_ cpu); /* And wake it up. */ is_wfi( other_cpu) ) { >env.mvp- >CP0_MVPControl |= (1 << CP0MVPCo_EVP); wake(other_ cpu); /* And wake it up. */
- /* If the VPE is WFI, don't disturb its sleep. */
- && !mips_vpe_
- /* Enable the VPE. */
- other_cpu-
- mips_vpe_
+ if (&other_cpu->env != env
+ /* If the VPE is WFI, don't disturb its sleep. */
+ && !mips_vpe_
+ /* Enable the VPE. */
+ other_cpu-
+ mips_vpe_
+ }
}
...