Commit b8c011f1 authored by mbaxter's avatar mbaxter Committed by GitHub

cannon: Simplify futex handling (#13754)

* cannon: Simplify futex handling

* cannon: Cut envar and go ahead and implement new futex behavior directly

* cannon: Cut now unused onWaitComplete() method

* cannon: Update single-threaded mips call to getSyscallArgs

* cannon: Update contracts to match go vm

* cannon: Update solidity tests

* cannon: Reconcile MIPS.sol version with latest release (1.2.1)

* cannon: Update differential tests

* cannon: Cut wakeup field

* cannon: Remove thread futex fields

* cannon: Fix const name

* cannon: Add new cannon state versions

* cannon: Cut wakeup stats

* cannon: Fix ParseStateVersion(), add test

* cannon: Reenable evm validation in tests

* cannon: Temporarily use ad hoc cannon release

* cannon: Run semver lock

* cannon: Fix semver comment, run semver-lock

* cannon: Cut unused constants

* cannon: Use latest cannon release in op-stack-go dockerfile

---------
Co-authored-by: default avatarinphi <mlaw2501@gmail.com>
parent ef6ef6fd
...@@ -152,14 +152,14 @@ cannon-prestate: op-program cannon ## Generates prestate using cannon and op-pro ...@@ -152,14 +152,14 @@ cannon-prestate: op-program cannon ## Generates prestate using cannon and op-pro
mv op-program/bin/0.json op-program/bin/prestate-proof.json mv op-program/bin/0.json op-program/bin/prestate-proof.json
.PHONY: cannon-prestate .PHONY: cannon-prestate
cannon-prestate-mt: op-program cannon ## Generates prestate using cannon and op-program in the multithreaded64-2 cannon format cannon-prestate-mt: op-program cannon ## Generates prestate using cannon and op-program in the latest 64-bit multithreaded cannon format
./cannon/bin/cannon load-elf --type multithreaded64-2 --path op-program/bin/op-program-client64.elf --out op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json ./cannon/bin/cannon load-elf --type multithreaded64-3 --path op-program/bin/op-program-client64.elf --out op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json
./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output "" ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output ""
mv op-program/bin/0-mt.json op-program/bin/prestate-proof-mt.json mv op-program/bin/0-mt.json op-program/bin/prestate-proof-mt.json
.PHONY: cannon-prestate-mt .PHONY: cannon-prestate-mt
cannon-prestate-interop: op-program cannon ## Generates interop prestate using cannon and op-program in the multithreaded64-2 cannon format cannon-prestate-interop: op-program cannon ## Generates interop prestate using cannon and op-program in the latest 64-bit multithreaded cannon format
./cannon/bin/cannon load-elf --type multithreaded64-2 --path op-program/bin/op-program-client-interop.elf --out op-program/bin/prestate-interop.bin.gz --meta op-program/bin/meta-interop.json ./cannon/bin/cannon load-elf --type multithreaded64-3 --path op-program/bin/op-program-client-interop.elf --out op-program/bin/prestate-interop.bin.gz --meta op-program/bin/meta-interop.json
./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-interop.bin.gz --meta op-program/bin/meta-interop.json --proof-fmt 'op-program/bin/%d-interop.json' --output "" ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-interop.bin.gz --meta op-program/bin/meta-interop.json --proof-fmt 'op-program/bin/%d-interop.json' --output ""
mv op-program/bin/0-interop.json op-program/bin/prestate-proof-interop.json mv op-program/bin/0-interop.json op-program/bin/prestate-proof-interop.json
.PHONY: cannon-prestate-interop .PHONY: cannon-prestate-interop
......
...@@ -31,13 +31,14 @@ cannon64-impl: ...@@ -31,13 +31,14 @@ cannon64-impl:
# It should build the individual versions of cannons and copy them into place in hte multicannon/embeds directory # It should build the individual versions of cannons and copy them into place in hte multicannon/embeds directory
# Ideally, preserve backwards compatibility with this behaviour but if it needs to change, build-legacy-cannons.sh will # Ideally, preserve backwards compatibility with this behaviour but if it needs to change, build-legacy-cannons.sh will
# need to be updated to account for different behaviours in different versions. # need to be updated to account for different behaviours in different versions.
# Each embed is suffixed with the latest `StateVersion` number corresponding to the target VM and architecture.
cannon-embeds: cannon32-impl cannon64-impl cannon-embeds: cannon32-impl cannon64-impl
# singlethreaded-v2 # 32-bit singlethreaded vm
@cp bin/cannon32-impl ./multicannon/embeds/cannon-2 @cp bin/cannon32-impl ./multicannon/embeds/cannon-2
# multithreaded # 32-bit multithreaded vm
@cp bin/cannon32-impl ./multicannon/embeds/cannon-1 @cp bin/cannon32-impl ./multicannon/embeds/cannon-5
# 64-bit multithreaded v2 # 64-bit multithreaded vm
@cp bin/cannon64-impl ./multicannon/embeds/cannon-4 @cp bin/cannon64-impl ./multicannon/embeds/cannon-6
cannon: cannon-embeds cannon: cannon-embeds
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon ./multicannon/ env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon ./multicannon/
......
...@@ -80,7 +80,7 @@ func LoadELF(ctx *cli.Context) error { ...@@ -80,7 +80,7 @@ func LoadELF(ctx *cli.Context) error {
} }
return program.PatchStack(state) return program.PatchStack(state)
} }
case versions.VersionMultiThreaded, versions.VersionMultiThreaded64_v2: case versions.VersionMultiThreaded_v2, versions.VersionMultiThreaded64_v3:
createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) { createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) {
return program.LoadELF(f, multithreaded.CreateInitialState) return program.LoadELF(f, multithreaded.CreateInitialState)
} }
......
...@@ -14,6 +14,5 @@ type DebugInfo struct { ...@@ -14,6 +14,5 @@ type DebugInfo struct {
MaxStepsBetweenLLAndSC uint64 `json:"max_steps_between_ll_and_sc"` MaxStepsBetweenLLAndSC uint64 `json:"max_steps_between_ll_and_sc"`
ReservationInvalidationCount uint64 `json:"reservation_invalidation_count"` ReservationInvalidationCount uint64 `json:"reservation_invalidation_count"`
ForcedPreemptionCount uint64 `json:"forced_preemption_count"` ForcedPreemptionCount uint64 `json:"forced_preemption_count"`
FailedWakeupCount uint64 `json:"failed_wakeup_count"`
IdleStepCountThread0 uint64 `json:"idle_step_count_thread_0"` IdleStepCountThread0 uint64 `json:"idle_step_count_thread_0"`
} }
...@@ -23,7 +23,6 @@ func TestDebugInfo_Serialization(t *testing.T) { ...@@ -23,7 +23,6 @@ func TestDebugInfo_Serialization(t *testing.T) {
MaxStepsBetweenLLAndSC: 7, MaxStepsBetweenLLAndSC: 7,
ReservationInvalidationCount: 8, ReservationInvalidationCount: 8,
ForcedPreemptionCount: 9, ForcedPreemptionCount: 9,
FailedWakeupCount: 10,
IdleStepCountThread0: math.MaxUint64, IdleStepCountThread0: math.MaxUint64,
} }
......
...@@ -44,9 +44,6 @@ const ( ...@@ -44,9 +44,6 @@ const (
const ( const (
FutexWaitPrivate = 128 FutexWaitPrivate = 128
FutexWakePrivate = 129 FutexWakePrivate = 129
FutexTimeoutSteps = 10_000
FutexNoTimeout = ^uint64(0)
FutexEmptyAddr = ^Word(0)
) )
// SysClone flags // SysClone flags
...@@ -99,15 +96,14 @@ const ( ...@@ -99,15 +96,14 @@ const (
ClockGettimeMonotonicFlag = 1 ClockGettimeMonotonicFlag = 1
) )
func GetSyscallArgs(registers *[32]Word) (syscallNum, a0, a1, a2, a3 Word) { func GetSyscallArgs(registers *[32]Word) (syscallNum, a0, a1, a2 Word) {
syscallNum = registers[register.RegSyscallNum] // v0 syscallNum = registers[register.RegSyscallNum] // v0
a0 = registers[register.RegSyscallParam1] a0 = registers[register.RegSyscallParam1]
a1 = registers[register.RegSyscallParam2] a1 = registers[register.RegSyscallParam2]
a2 = registers[register.RegSyscallParam3] a2 = registers[register.RegSyscallParam3]
a3 = registers[register.RegSyscallParam4]
return syscallNum, a0, a1, a2, a3 return syscallNum, a0, a1, a2
} }
func HandleSysMmap(a0, a1, heap Word) (v0, v1, newHeap Word) { func HandleSysMmap(a0, a1, heap Word) (v0, v1, newHeap Word) {
......
...@@ -20,7 +20,7 @@ type Word = arch.Word ...@@ -20,7 +20,7 @@ type Word = arch.Word
func (m *InstrumentedState) handleSyscall() error { func (m *InstrumentedState) handleSyscall() error {
thread := m.state.GetCurrentThread() thread := m.state.GetCurrentThread()
syscallNum, a0, a1, a2, a3 := exec.GetSyscallArgs(m.state.GetRegistersRef()) syscallNum, a0, a1, a2 := exec.GetSyscallArgs(m.state.GetRegistersRef())
v0 := Word(0) v0 := Word(0)
v1 := Word(0) v1 := Word(0)
...@@ -46,9 +46,6 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -46,9 +46,6 @@ func (m *InstrumentedState) handleSyscall() error {
ThreadId: m.state.NextThreadId, ThreadId: m.state.NextThreadId,
ExitCode: 0, ExitCode: 0,
Exited: false, Exited: false,
FutexAddr: exec.FutexEmptyAddr,
FutexVal: 0,
FutexTimeoutStep: 0,
Cpu: mipsevm.CpuScalars{ Cpu: mipsevm.CpuScalars{
PC: thread.Cpu.NextPC, PC: thread.Cpu.NextPC,
NextPC: thread.Cpu.NextPC + 4, NextPC: thread.Cpu.NextPC + 4,
...@@ -119,37 +116,18 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -119,37 +116,18 @@ func (m *InstrumentedState) handleSyscall() error {
v0 = exec.SysErrorSignal v0 = exec.SysErrorSignal
v1 = exec.MipsEAGAIN v1 = exec.MipsEAGAIN
} else { } else {
thread.FutexAddr = effFutexAddr m.syscallYield(thread)
thread.FutexVal = targetVal
if a3 == 0 {
thread.FutexTimeoutStep = exec.FutexNoTimeout
} else {
thread.FutexTimeoutStep = m.state.Step + exec.FutexTimeoutSteps
}
// Leave cpu scalars as-is. This instruction will be completed by `onWaitComplete`
return nil return nil
} }
case exec.FutexWakePrivate: case exec.FutexWakePrivate:
// Trigger a wakeup traversal m.syscallYield(thread)
m.state.Wakeup = effFutexAddr
// Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees.
// The woken up thread should indicate this in userspace.
v0 = 0
v1 = 0
exec.HandleSyscallUpdates(&thread.Cpu, &thread.Registers, v0, v1)
m.preemptThread(thread)
m.state.TraverseRight = len(m.state.LeftThreadStack) == 0
m.statsTracker.trackWakeupTraversalStart()
return nil return nil
default: default:
v0 = exec.SysErrorSignal v0 = exec.SysErrorSignal
v1 = exec.MipsEINVAL v1 = exec.MipsEINVAL
} }
case arch.SysSchedYield, arch.SysNanosleep: case arch.SysSchedYield, arch.SysNanosleep:
v0 = 0 m.syscallYield(thread)
v1 = 0
exec.HandleSyscallUpdates(&thread.Cpu, &thread.Registers, v0, v1)
m.preemptThread(thread)
return nil return nil
case arch.SysOpen: case arch.SysOpen:
v0 = exec.SysErrorSignal v0 = exec.SysErrorSignal
...@@ -225,6 +203,13 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -225,6 +203,13 @@ func (m *InstrumentedState) handleSyscall() error {
return nil return nil
} }
func (m *InstrumentedState) syscallYield(thread *ThreadState) {
v0 := Word(0)
v1 := Word(0)
exec.HandleSyscallUpdates(&thread.Cpu, &thread.Registers, v0, v1)
m.preemptThread(thread)
}
func (m *InstrumentedState) mipsStep() error { func (m *InstrumentedState) mipsStep() error {
err := m.doMipsStep() err := m.doMipsStep()
if err != nil { if err != nil {
...@@ -249,56 +234,12 @@ func (m *InstrumentedState) doMipsStep() error { ...@@ -249,56 +234,12 @@ func (m *InstrumentedState) doMipsStep() error {
m.state.Step += 1 m.state.Step += 1
thread := m.state.GetCurrentThread() thread := m.state.GetCurrentThread()
// During wakeup traversal, search for the first thread blocked on the wakeup address.
// Don't allow regular execution until we have found such a thread or else we have visited all threads.
if m.state.Wakeup != exec.FutexEmptyAddr {
// We are currently performing a wakeup traversal
if m.state.Wakeup == thread.FutexAddr {
// We found a target thread, resume normal execution and process this thread
m.state.Wakeup = exec.FutexEmptyAddr
} else {
// This is not the thread we're looking for, move on
traversingRight := m.state.TraverseRight
changedDirections := m.preemptThread(thread)
if traversingRight && changedDirections {
// We started the wakeup traversal walking left and we've now walked all the way right
// We have therefore visited all threads and can resume normal thread execution
m.state.Wakeup = exec.FutexEmptyAddr
}
}
return nil
}
if thread.Exited { if thread.Exited {
m.popThread() m.popThread()
m.stackTracker.DropThread(thread.ThreadId) m.stackTracker.DropThread(thread.ThreadId)
return nil return nil
} }
// check if thread is blocked on a futex
if thread.FutexAddr != exec.FutexEmptyAddr {
// if set, then check futex
// check timeout first
if m.state.Step > thread.FutexTimeoutStep {
// timeout! Allow execution
m.onWaitComplete(thread, true)
return nil
} else {
futexVal := m.getFutexValue(thread.FutexAddr)
if thread.FutexVal == futexVal {
// still got expected value, continue sleeping, try next thread.
m.preemptThread(thread)
m.statsTracker.trackWakeupFail()
return nil
} else {
// wake thread up, the value at its address changed!
// Userspace can turn thread back to sleep if it was too sporadic.
m.onWaitComplete(thread, false)
return nil
}
}
}
if m.state.StepsSinceLastContextSwitch >= exec.SchedQuantum { if m.state.StepsSinceLastContextSwitch >= exec.SchedQuantum {
// Force a context switch as this thread has been active too long // Force a context switch as this thread has been active too long
if m.state.ThreadCount() > 1 { if m.state.ThreadCount() > 1 {
...@@ -412,24 +353,6 @@ func (m *InstrumentedState) handleRMWOps(insn, opcode uint32) error { ...@@ -412,24 +353,6 @@ func (m *InstrumentedState) handleRMWOps(insn, opcode uint32) error {
return exec.HandleRd(m.state.getCpuRef(), m.state.GetRegistersRef(), rtReg, retVal, true) return exec.HandleRd(m.state.getCpuRef(), m.state.GetRegistersRef(), rtReg, retVal, true)
} }
func (m *InstrumentedState) onWaitComplete(thread *ThreadState, isTimedOut bool) {
// Note: no need to reset m.state.Wakeup. If we're here, the Wakeup field has already been reset
// Clear the futex state
thread.FutexAddr = exec.FutexEmptyAddr
thread.FutexVal = 0
thread.FutexTimeoutStep = 0
// Complete the FUTEX_WAIT syscall
v0 := Word(0)
v1 := Word(0)
if isTimedOut {
v0 = exec.SysErrorSignal
v1 = exec.MipsETIMEDOUT
}
exec.HandleSyscallUpdates(&thread.Cpu, &thread.Registers, v0, v1)
m.statsTracker.trackWakeup()
}
func (m *InstrumentedState) preemptThread(thread *ThreadState) bool { func (m *InstrumentedState) preemptThread(thread *ThreadState) bool {
// Pop thread from the current stack and push to the other stack // Pop thread from the current stack and push to the other stack
if m.state.TraverseRight { if m.state.TraverseRight {
......
...@@ -12,7 +12,6 @@ import ( ...@@ -12,7 +12,6 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch" "github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/exec"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
"github.com/ethereum-optimism/optimism/op-service/serialize" "github.com/ethereum-optimism/optimism/op-service/serialize"
) )
...@@ -30,13 +29,12 @@ const ( ...@@ -30,13 +29,12 @@ const (
EXITED_WITNESS_OFFSET = EXITCODE_WITNESS_OFFSET + 1 EXITED_WITNESS_OFFSET = EXITCODE_WITNESS_OFFSET + 1
STEP_WITNESS_OFFSET = EXITED_WITNESS_OFFSET + 1 STEP_WITNESS_OFFSET = EXITED_WITNESS_OFFSET + 1
STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET = STEP_WITNESS_OFFSET + 8 STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET = STEP_WITNESS_OFFSET + 8
WAKEUP_WITNESS_OFFSET = STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET + 8 TRAVERSE_RIGHT_WITNESS_OFFSET = STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET + 8
TRAVERSE_RIGHT_WITNESS_OFFSET = WAKEUP_WITNESS_OFFSET + arch.WordSizeBytes
LEFT_THREADS_ROOT_WITNESS_OFFSET = TRAVERSE_RIGHT_WITNESS_OFFSET + 1 LEFT_THREADS_ROOT_WITNESS_OFFSET = TRAVERSE_RIGHT_WITNESS_OFFSET + 1
RIGHT_THREADS_ROOT_WITNESS_OFFSET = LEFT_THREADS_ROOT_WITNESS_OFFSET + 32 RIGHT_THREADS_ROOT_WITNESS_OFFSET = LEFT_THREADS_ROOT_WITNESS_OFFSET + 32
THREAD_ID_WITNESS_OFFSET = RIGHT_THREADS_ROOT_WITNESS_OFFSET + 32 THREAD_ID_WITNESS_OFFSET = RIGHT_THREADS_ROOT_WITNESS_OFFSET + 32
// 172 and 196 bytes for 32 and 64-bit respectively // 168 and 188 bytes for 32 and 64-bit respectively
STATE_WITNESS_SIZE = THREAD_ID_WITNESS_OFFSET + arch.WordSizeBytes STATE_WITNESS_SIZE = THREAD_ID_WITNESS_OFFSET + arch.WordSizeBytes
) )
...@@ -64,7 +62,6 @@ type State struct { ...@@ -64,7 +62,6 @@ type State struct {
Step uint64 Step uint64
StepsSinceLastContextSwitch uint64 StepsSinceLastContextSwitch uint64
Wakeup Word
TraverseRight bool TraverseRight bool
LeftThreadStack []*ThreadState LeftThreadStack []*ThreadState
...@@ -89,7 +86,6 @@ func CreateEmptyState() *State { ...@@ -89,7 +86,6 @@ func CreateEmptyState() *State {
ExitCode: 0, ExitCode: 0,
Exited: false, Exited: false,
Step: 0, Step: 0,
Wakeup: exec.FutexEmptyAddr,
TraverseRight: false, TraverseRight: false,
LeftThreadStack: []*ThreadState{initThread}, LeftThreadStack: []*ThreadState{initThread},
RightThreadStack: []*ThreadState{}, RightThreadStack: []*ThreadState{},
...@@ -215,7 +211,6 @@ func (s *State) EncodeWitness() ([]byte, common.Hash) { ...@@ -215,7 +211,6 @@ func (s *State) EncodeWitness() ([]byte, common.Hash) {
out = binary.BigEndian.AppendUint64(out, s.Step) out = binary.BigEndian.AppendUint64(out, s.Step)
out = binary.BigEndian.AppendUint64(out, s.StepsSinceLastContextSwitch) out = binary.BigEndian.AppendUint64(out, s.StepsSinceLastContextSwitch)
out = arch.ByteOrderWord.AppendWord(out, s.Wakeup)
leftStackRoot := s.getLeftThreadStackRoot() leftStackRoot := s.getLeftThreadStackRoot()
rightStackRoot := s.getRightThreadStackRoot() rightStackRoot := s.getRightThreadStackRoot()
...@@ -262,7 +257,6 @@ func (s *State) ThreadCount() int { ...@@ -262,7 +257,6 @@ func (s *State) ThreadCount() int {
// Exited uint8 - 0 for false, 1 for true // Exited uint8 - 0 for false, 1 for true
// Step uint64 // Step uint64
// StepsSinceLastContextSwitch uint64 // StepsSinceLastContextSwitch uint64
// Wakeup Word
// TraverseRight uint8 - 0 for false, 1 for true // TraverseRight uint8 - 0 for false, 1 for true
// NextThreadId Word // NextThreadId Word
// len(LeftThreadStack) Word // len(LeftThreadStack) Word
...@@ -307,9 +301,6 @@ func (s *State) Serialize(out io.Writer) error { ...@@ -307,9 +301,6 @@ func (s *State) Serialize(out io.Writer) error {
if err := bout.WriteUInt(s.StepsSinceLastContextSwitch); err != nil { if err := bout.WriteUInt(s.StepsSinceLastContextSwitch); err != nil {
return err return err
} }
if err := bout.WriteUInt(s.Wakeup); err != nil {
return err
}
if err := bout.WriteBool(s.TraverseRight); err != nil { if err := bout.WriteBool(s.TraverseRight); err != nil {
return err return err
} }
...@@ -376,9 +367,6 @@ func (s *State) Deserialize(in io.Reader) error { ...@@ -376,9 +367,6 @@ func (s *State) Deserialize(in io.Reader) error {
if err := bin.ReadUInt(&s.StepsSinceLastContextSwitch); err != nil { if err := bin.ReadUInt(&s.StepsSinceLastContextSwitch); err != nil {
return err return err
} }
if err := bin.ReadUInt(&s.Wakeup); err != nil {
return err
}
if err := bin.ReadBool(&s.TraverseRight); err != nil { if err := bin.ReadBool(&s.TraverseRight); err != nil {
return err return err
} }
......
...@@ -14,7 +14,6 @@ import ( ...@@ -14,7 +14,6 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch" "github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/exec"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program" "github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
) )
...@@ -85,7 +84,6 @@ func TestState_EncodeWitness(t *testing.T) { ...@@ -85,7 +84,6 @@ func TestState_EncodeWitness(t *testing.T) {
} }
setWitnessField(expectedWitness, STEP_WITNESS_OFFSET, []byte{0, 0, 0, 0, 0, 0, 0, byte(step)}) setWitnessField(expectedWitness, STEP_WITNESS_OFFSET, []byte{0, 0, 0, 0, 0, 0, 0, byte(step)})
setWitnessField(expectedWitness, STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET, []byte{0, 0, 0, 0, 0, 0, 0, byte(stepsSinceContextSwitch)}) setWitnessField(expectedWitness, STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET, []byte{0, 0, 0, 0, 0, 0, 0, byte(stepsSinceContextSwitch)})
setWitnessWord(expectedWitness, WAKEUP_WITNESS_OFFSET, ^arch.Word(0))
setWitnessField(expectedWitness, TRAVERSE_RIGHT_WITNESS_OFFSET, []byte{0}) setWitnessField(expectedWitness, TRAVERSE_RIGHT_WITNESS_OFFSET, []byte{0})
setWitnessField(expectedWitness, LEFT_THREADS_ROOT_WITNESS_OFFSET, leftStackRoot[:]) setWitnessField(expectedWitness, LEFT_THREADS_ROOT_WITNESS_OFFSET, leftStackRoot[:])
setWitnessField(expectedWitness, RIGHT_THREADS_ROOT_WITNESS_OFFSET, rightStackRoot[:]) setWitnessField(expectedWitness, RIGHT_THREADS_ROOT_WITNESS_OFFSET, rightStackRoot[:])
...@@ -132,7 +130,6 @@ func TestState_JSONCodec(t *testing.T) { ...@@ -132,7 +130,6 @@ func TestState_JSONCodec(t *testing.T) {
require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot())
require.Equal(t, state.Step, newState.Step) require.Equal(t, state.Step, newState.Step)
require.Equal(t, state.StepsSinceLastContextSwitch, newState.StepsSinceLastContextSwitch) require.Equal(t, state.StepsSinceLastContextSwitch, newState.StepsSinceLastContextSwitch)
require.Equal(t, state.Wakeup, newState.Wakeup)
require.Equal(t, state.TraverseRight, newState.TraverseRight) require.Equal(t, state.TraverseRight, newState.TraverseRight)
require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack) require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack)
require.Equal(t, state.RightThreadStack, newState.RightThreadStack) require.Equal(t, state.RightThreadStack, newState.RightThreadStack)
...@@ -170,7 +167,6 @@ func TestState_Binary(t *testing.T) { ...@@ -170,7 +167,6 @@ func TestState_Binary(t *testing.T) {
require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot())
require.Equal(t, state.Step, newState.Step) require.Equal(t, state.Step, newState.Step)
require.Equal(t, state.StepsSinceLastContextSwitch, newState.StepsSinceLastContextSwitch) require.Equal(t, state.StepsSinceLastContextSwitch, newState.StepsSinceLastContextSwitch)
require.Equal(t, state.Wakeup, newState.Wakeup)
require.Equal(t, state.TraverseRight, newState.TraverseRight) require.Equal(t, state.TraverseRight, newState.TraverseRight)
require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack) require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack)
require.Equal(t, state.RightThreadStack, newState.RightThreadStack) require.Equal(t, state.RightThreadStack, newState.RightThreadStack)
...@@ -196,16 +192,12 @@ func TestSerializeStateRoundTrip(t *testing.T) { ...@@ -196,16 +192,12 @@ func TestSerializeStateRoundTrip(t *testing.T) {
Exited: true, Exited: true,
Step: 0xdeadbeef, Step: 0xdeadbeef,
StepsSinceLastContextSwitch: 334, StepsSinceLastContextSwitch: 334,
Wakeup: 42,
TraverseRight: true, TraverseRight: true,
LeftThreadStack: []*ThreadState{ LeftThreadStack: []*ThreadState{
{ {
ThreadId: 45, ThreadId: 45,
ExitCode: 46, ExitCode: 46,
Exited: true, Exited: true,
FutexAddr: 47,
FutexVal: 48,
FutexTimeoutStep: 49,
Cpu: mipsevm.CpuScalars{ Cpu: mipsevm.CpuScalars{
PC: 0xFF, PC: 0xFF,
NextPC: 0xFF + 4, NextPC: 0xFF + 4,
...@@ -226,9 +218,6 @@ func TestSerializeStateRoundTrip(t *testing.T) { ...@@ -226,9 +218,6 @@ func TestSerializeStateRoundTrip(t *testing.T) {
ThreadId: 55, ThreadId: 55,
ExitCode: 56, ExitCode: 56,
Exited: false, Exited: false,
FutexAddr: 57,
FutexVal: 58,
FutexTimeoutStep: 59,
Cpu: mipsevm.CpuScalars{ Cpu: mipsevm.CpuScalars{
PC: 0xEE, PC: 0xEE,
NextPC: 0xEE + 4, NextPC: 0xEE + 4,
...@@ -246,9 +235,6 @@ func TestSerializeStateRoundTrip(t *testing.T) { ...@@ -246,9 +235,6 @@ func TestSerializeStateRoundTrip(t *testing.T) {
ThreadId: 65, ThreadId: 65,
ExitCode: 66, ExitCode: 66,
Exited: false, Exited: false,
FutexAddr: 67,
FutexVal: 68,
FutexTimeoutStep: 69,
Cpu: mipsevm.CpuScalars{ Cpu: mipsevm.CpuScalars{
PC: 0xdd, PC: 0xdd,
NextPC: 0xdd + 4, NextPC: 0xdd + 4,
...@@ -263,9 +249,6 @@ func TestSerializeStateRoundTrip(t *testing.T) { ...@@ -263,9 +249,6 @@ func TestSerializeStateRoundTrip(t *testing.T) {
ThreadId: 75, ThreadId: 75,
ExitCode: 76, ExitCode: 76,
Exited: true, Exited: true,
FutexAddr: 77,
FutexVal: 78,
FutexTimeoutStep: 79,
Cpu: mipsevm.CpuScalars{ Cpu: mipsevm.CpuScalars{
PC: 0xcc, PC: 0xcc,
NextPC: 0xcc + 4, NextPC: 0xcc + 4,
...@@ -360,20 +343,16 @@ func TestState_EncodeThreadProof_MultipleThreads(t *testing.T) { ...@@ -360,20 +343,16 @@ func TestState_EncodeThreadProof_MultipleThreads(t *testing.T) {
func TestState_EncodeThreadProof_EmptyThreadStackPanic(t *testing.T) { func TestState_EncodeThreadProof_EmptyThreadStackPanic(t *testing.T) {
cases := []struct { cases := []struct {
name string name string
wakeupAddr Word
traverseRight bool traverseRight bool
}{ }{
{"traverse left during wakeup traversal", Word(99), false}, {"traverse left", false},
{"traverse left during normal traversal", exec.FutexEmptyAddr, false}, {"traverse right", true},
{"traverse right during wakeup traversal", Word(99), true},
{"traverse right during normal traversal", exec.FutexEmptyAddr, true},
} }
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
// Set up invalid state where the active stack is empty // Set up invalid state where the active stack is empty
state := CreateEmptyState() state := CreateEmptyState()
state.Wakeup = c.wakeupAddr
state.TraverseRight = c.traverseRight state.TraverseRight = c.traverseRight
if c.traverseRight { if c.traverseRight {
state.LeftThreadStack = []*ThreadState{CreateEmptyThread()} state.LeftThreadStack = []*ThreadState{CreateEmptyThread()}
...@@ -389,17 +368,17 @@ func TestState_EncodeThreadProof_EmptyThreadStackPanic(t *testing.T) { ...@@ -389,17 +368,17 @@ func TestState_EncodeThreadProof_EmptyThreadStackPanic(t *testing.T) {
} }
func TestStateWitnessSize(t *testing.T) { func TestStateWitnessSize(t *testing.T) {
expectedWitnessSize := 172 expectedWitnessSize := 168
if !arch.IsMips32 { if !arch.IsMips32 {
expectedWitnessSize = 196 expectedWitnessSize = 188
} }
require.Equal(t, expectedWitnessSize, STATE_WITNESS_SIZE) require.Equal(t, expectedWitnessSize, STATE_WITNESS_SIZE)
} }
func TestThreadStateWitnessSize(t *testing.T) { func TestThreadStateWitnessSize(t *testing.T) {
expectedWitnessSize := 166 expectedWitnessSize := 150
if !arch.IsMips32 { if !arch.IsMips32 {
expectedWitnessSize = 318 expectedWitnessSize = 298
} }
require.Equal(t, expectedWitnessSize, SERIALIZED_THREAD_SIZE) require.Equal(t, expectedWitnessSize, SERIALIZED_THREAD_SIZE)
} }
...@@ -13,9 +13,6 @@ type StatsTracker interface { ...@@ -13,9 +13,6 @@ type StatsTracker interface {
trackSCFailure(threadId Word, step uint64) trackSCFailure(threadId Word, step uint64)
trackReservationInvalidation() trackReservationInvalidation()
trackForcedPreemption() trackForcedPreemption()
trackWakeupTraversalStart()
trackWakeup()
trackWakeupFail()
trackThreadActivated(tid Word, step uint64) trackThreadActivated(tid Word, step uint64)
populateDebugInfo(debugInfo *mipsevm.DebugInfo) populateDebugInfo(debugInfo *mipsevm.DebugInfo)
} }
...@@ -32,9 +29,6 @@ func (s *noopStatsTracker) trackSCSuccess(threadId Word, step uint64) {} ...@@ -32,9 +29,6 @@ func (s *noopStatsTracker) trackSCSuccess(threadId Word, step uint64) {}
func (s *noopStatsTracker) trackSCFailure(threadId Word, step uint64) {} func (s *noopStatsTracker) trackSCFailure(threadId Word, step uint64) {}
func (s *noopStatsTracker) trackReservationInvalidation() {} func (s *noopStatsTracker) trackReservationInvalidation() {}
func (s *noopStatsTracker) trackForcedPreemption() {} func (s *noopStatsTracker) trackForcedPreemption() {}
func (s *noopStatsTracker) trackWakeupTraversalStart() {}
func (s *noopStatsTracker) trackWakeup() {}
func (s *noopStatsTracker) trackWakeupFail() {}
func (s *noopStatsTracker) trackThreadActivated(tid Word, step uint64) {} func (s *noopStatsTracker) trackThreadActivated(tid Word, step uint64) {}
func (s *noopStatsTracker) populateDebugInfo(debugInfo *mipsevm.DebugInfo) {} func (s *noopStatsTracker) populateDebugInfo(debugInfo *mipsevm.DebugInfo) {}
...@@ -44,7 +38,6 @@ var _ StatsTracker = (*noopStatsTracker)(nil) ...@@ -44,7 +38,6 @@ var _ StatsTracker = (*noopStatsTracker)(nil)
type statsTrackerImpl struct { type statsTrackerImpl struct {
// State // State
lastLLStepByThread *lru.LRU[Word, uint64] lastLLStepByThread *lru.LRU[Word, uint64]
isWakeupTraversal bool
activeThreadId Word activeThreadId Word
lastActiveStepThread0 uint64 lastActiveStepThread0 uint64
// Stats // Stats
...@@ -54,7 +47,6 @@ type statsTrackerImpl struct { ...@@ -54,7 +47,6 @@ type statsTrackerImpl struct {
// Tracks RMW reservation invalidation due to reserved memory being accessed outside of the RMW sequence // Tracks RMW reservation invalidation due to reserved memory being accessed outside of the RMW sequence
reservationInvalidationCount uint64 reservationInvalidationCount uint64
forcedPreemptionCount uint64 forcedPreemptionCount uint64
failedWakeupCount uint64
idleStepCountThread0 uint64 idleStepCountThread0 uint64
} }
...@@ -64,7 +56,6 @@ func (s *statsTrackerImpl) populateDebugInfo(debugInfo *mipsevm.DebugInfo) { ...@@ -64,7 +56,6 @@ func (s *statsTrackerImpl) populateDebugInfo(debugInfo *mipsevm.DebugInfo) {
debugInfo.MaxStepsBetweenLLAndSC = s.maxStepsBetweenLLAndSC debugInfo.MaxStepsBetweenLLAndSC = s.maxStepsBetweenLLAndSC
debugInfo.ReservationInvalidationCount = s.reservationInvalidationCount debugInfo.ReservationInvalidationCount = s.reservationInvalidationCount
debugInfo.ForcedPreemptionCount = s.forcedPreemptionCount debugInfo.ForcedPreemptionCount = s.forcedPreemptionCount
debugInfo.FailedWakeupCount = s.failedWakeupCount
debugInfo.IdleStepCountThread0 = s.idleStepCountThread0 debugInfo.IdleStepCountThread0 = s.idleStepCountThread0
} }
...@@ -102,21 +93,6 @@ func (s *statsTrackerImpl) trackForcedPreemption() { ...@@ -102,21 +93,6 @@ func (s *statsTrackerImpl) trackForcedPreemption() {
s.forcedPreemptionCount += 1 s.forcedPreemptionCount += 1
} }
func (s *statsTrackerImpl) trackWakeupTraversalStart() {
s.isWakeupTraversal = true
}
func (s *statsTrackerImpl) trackWakeup() {
s.isWakeupTraversal = false
}
func (s *statsTrackerImpl) trackWakeupFail() {
if s.isWakeupTraversal {
s.failedWakeupCount += 1
}
s.isWakeupTraversal = false
}
func (s *statsTrackerImpl) trackThreadActivated(tid Word, step uint64) { func (s *statsTrackerImpl) trackThreadActivated(tid Word, step uint64) {
if s.activeThreadId == Word(0) && tid != Word(0) { if s.activeThreadId == Word(0) && tid != Word(0) {
// Thread 0 has been deactivated, start tracking to capture idle steps // Thread 0 has been deactivated, start tracking to capture idle steps
......
...@@ -69,26 +69,6 @@ func TestStatsTracker(t *testing.T) { ...@@ -69,26 +69,6 @@ func TestStatsTracker(t *testing.T) {
operations: []Operation{forcePreempt(), forcePreempt()}, operations: []Operation{forcePreempt(), forcePreempt()},
expected: &mipsevm.DebugInfo{ForcedPreemptionCount: 2}, expected: &mipsevm.DebugInfo{ForcedPreemptionCount: 2},
}, },
{
name: "Successful wakeup traversal",
operations: []Operation{wakeupTraversal(), wakeup(), sleep(), wakeup()},
expected: &mipsevm.DebugInfo{FailedWakeupCount: 0},
},
{
name: "Failed wakeup traversal",
operations: []Operation{wakeupTraversal(), sleep(), wakeup(), sleep()},
expected: &mipsevm.DebugInfo{FailedWakeupCount: 1},
},
{
name: "Multiple failed wakeup traversals",
operations: []Operation{wakeupTraversal(), sleep(), wakeupTraversal(), sleep(), wakeupTraversal(), wakeup()},
expected: &mipsevm.DebugInfo{FailedWakeupCount: 2},
},
{
name: "Wakeups and sleeps outside of wakeup traversal",
operations: []Operation{sleep(), wakeup(), wakeup(), sleep()},
expected: &mipsevm.DebugInfo{FailedWakeupCount: 0},
},
{ {
name: "Preempt thread 0 for thread 0", name: "Preempt thread 0 for thread 0",
operations: []Operation{activateThread(0, 10), activateThread(0, 20), activateThread(0, 21)}, operations: []Operation{activateThread(0, 10), activateThread(0, 20), activateThread(0, 21)},
...@@ -148,24 +128,6 @@ func forcePreempt() Operation { ...@@ -148,24 +128,6 @@ func forcePreempt() Operation {
} }
} }
func wakeupTraversal() Operation {
return func(tracker StatsTracker) {
tracker.trackWakeupTraversalStart()
}
}
func wakeup() Operation {
return func(tracker StatsTracker) {
tracker.trackWakeup()
}
}
func sleep() Operation {
return func(tracker StatsTracker) {
tracker.trackWakeupFail()
}
}
func activateThread(tid Word, step uint64) Operation { func activateThread(tid Word, step uint64) Operation {
return func(tracker StatsTracker) { return func(tracker StatsTracker) {
tracker.trackThreadActivated(tid, step) tracker.trackThreadActivated(tid, step)
......
...@@ -31,7 +31,6 @@ type ExpectedMTState struct { ...@@ -31,7 +31,6 @@ type ExpectedMTState struct {
expectedMemory *memory.Memory expectedMemory *memory.Memory
// Threading-related expectations // Threading-related expectations
StepsSinceLastContextSwitch uint64 StepsSinceLastContextSwitch uint64
Wakeup arch.Word
TraverseRight bool TraverseRight bool
NextThreadId arch.Word NextThreadId arch.Word
ThreadCount int ThreadCount int
...@@ -47,9 +46,6 @@ type ExpectedThreadState struct { ...@@ -47,9 +46,6 @@ type ExpectedThreadState struct {
ThreadId arch.Word ThreadId arch.Word
ExitCode uint8 ExitCode uint8
Exited bool Exited bool
FutexAddr arch.Word
FutexVal uint32
FutexTimeoutStep uint64
PC arch.Word PC arch.Word
NextPC arch.Word NextPC arch.Word
HI arch.Word HI arch.Word
...@@ -81,7 +77,6 @@ func NewExpectedMTState(fromState *multithreaded.State) *ExpectedMTState { ...@@ -81,7 +77,6 @@ func NewExpectedMTState(fromState *multithreaded.State) *ExpectedMTState {
MemoryRoot: fromState.GetMemory().MerkleRoot(), MemoryRoot: fromState.GetMemory().MerkleRoot(),
// Thread-related global fields // Thread-related global fields
StepsSinceLastContextSwitch: fromState.StepsSinceLastContextSwitch, StepsSinceLastContextSwitch: fromState.StepsSinceLastContextSwitch,
Wakeup: fromState.Wakeup,
TraverseRight: fromState.TraverseRight, TraverseRight: fromState.TraverseRight,
NextThreadId: fromState.NextThreadId, NextThreadId: fromState.NextThreadId,
ThreadCount: fromState.ThreadCount(), ThreadCount: fromState.ThreadCount(),
...@@ -101,9 +96,6 @@ func newExpectedThreadState(fromThread *multithreaded.ThreadState) *ExpectedThre ...@@ -101,9 +96,6 @@ func newExpectedThreadState(fromThread *multithreaded.ThreadState) *ExpectedThre
ThreadId: fromThread.ThreadId, ThreadId: fromThread.ThreadId,
ExitCode: fromThread.ExitCode, ExitCode: fromThread.ExitCode,
Exited: fromThread.Exited, Exited: fromThread.Exited,
FutexAddr: fromThread.FutexAddr,
FutexVal: fromThread.FutexVal,
FutexTimeoutStep: fromThread.FutexTimeoutStep,
PC: fromThread.Cpu.PC, PC: fromThread.Cpu.PC,
NextPC: fromThread.Cpu.NextPC, NextPC: fromThread.Cpu.NextPC,
HI: fromThread.Cpu.HI, HI: fromThread.Cpu.HI,
...@@ -193,7 +185,6 @@ func (e *ExpectedMTState) Validate(t require.TestingT, actualState *multithreade ...@@ -193,7 +185,6 @@ func (e *ExpectedMTState) Validate(t require.TestingT, actualState *multithreade
require.Equalf(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), "Expect memory root = %v", e.MemoryRoot) require.Equalf(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), "Expect memory root = %v", e.MemoryRoot)
// Thread-related global fields // Thread-related global fields
require.Equalf(t, e.StepsSinceLastContextSwitch, actualState.StepsSinceLastContextSwitch, "Expect StepsSinceLastContextSwitch = %v", e.StepsSinceLastContextSwitch) require.Equalf(t, e.StepsSinceLastContextSwitch, actualState.StepsSinceLastContextSwitch, "Expect StepsSinceLastContextSwitch = %v", e.StepsSinceLastContextSwitch)
require.Equalf(t, e.Wakeup, actualState.Wakeup, "Expect Wakeup = %v", e.Wakeup)
require.Equalf(t, e.TraverseRight, actualState.TraverseRight, "Expect TraverseRight = %v", e.TraverseRight) require.Equalf(t, e.TraverseRight, actualState.TraverseRight, "Expect TraverseRight = %v", e.TraverseRight)
require.Equalf(t, e.NextThreadId, actualState.NextThreadId, "Expect NextThreadId = %v", e.NextThreadId) require.Equalf(t, e.NextThreadId, actualState.NextThreadId, "Expect NextThreadId = %v", e.NextThreadId)
require.Equalf(t, e.ThreadCount, actualState.ThreadCount(), "Expect thread count = %v", e.ThreadCount) require.Equalf(t, e.ThreadCount, actualState.ThreadCount(), "Expect thread count = %v", e.ThreadCount)
...@@ -229,7 +220,4 @@ func (e *ExpectedMTState) validateThread(t require.TestingT, et *ExpectedThreadS ...@@ -229,7 +220,4 @@ func (e *ExpectedMTState) validateThread(t require.TestingT, et *ExpectedThreadS
require.Equalf(t, et.Registers, actual.Registers, "Expect registers to match (%v)", threadInfo) require.Equalf(t, et.Registers, actual.Registers, "Expect registers to match (%v)", threadInfo)
require.Equalf(t, et.ExitCode, actual.ExitCode, "Expect exitCode = %v (%v)", et.ExitCode, threadInfo) require.Equalf(t, et.ExitCode, actual.ExitCode, "Expect exitCode = %v (%v)", et.ExitCode, threadInfo)
require.Equalf(t, et.Exited, actual.Exited, "Expect exited = %v (%v)", et.Exited, threadInfo) require.Equalf(t, et.Exited, actual.Exited, "Expect exited = %v (%v)", et.Exited, threadInfo)
require.Equalf(t, et.FutexAddr, actual.FutexAddr, "Expect futexAddr = %v (%v)", et.FutexAddr, threadInfo)
require.Equalf(t, et.FutexVal, actual.FutexVal, "Expect futexVal = %v (%v)", et.FutexVal, threadInfo)
require.Equalf(t, et.FutexTimeoutStep, actual.FutexTimeoutStep, "Expect futexTimeoutStep = %v (%v)", et.FutexTimeoutStep, threadInfo)
} }
...@@ -38,7 +38,6 @@ func TestValidate_shouldCatchMutations(t *testing.T) { ...@@ -38,7 +38,6 @@ func TestValidate_shouldCatchMutations(t *testing.T) {
{name: "LastHint", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LastHint = []byte{7, 8, 9, 10} }}, {name: "LastHint", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LastHint = []byte{7, 8, 9, 10} }},
{name: "MemoryRoot", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.MemoryRoot = emptyHash }}, {name: "MemoryRoot", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.MemoryRoot = emptyHash }},
{name: "StepsSinceLastContextSwitch", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.StepsSinceLastContextSwitch += 1 }}, {name: "StepsSinceLastContextSwitch", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.StepsSinceLastContextSwitch += 1 }},
{name: "Wakeup", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Wakeup += 1 }},
{name: "TraverseRight", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.TraverseRight = !e.TraverseRight }}, {name: "TraverseRight", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.TraverseRight = !e.TraverseRight }},
{name: "NextThreadId", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.NextThreadId += 1 }}, {name: "NextThreadId", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.NextThreadId += 1 }},
{name: "ThreadCount", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.ThreadCount += 1 }}, {name: "ThreadCount", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.ThreadCount += 1 }},
...@@ -60,15 +59,6 @@ func TestValidate_shouldCatchMutations(t *testing.T) { ...@@ -60,15 +59,6 @@ func TestValidate_shouldCatchMutations(t *testing.T) {
{name: "Active thread exited", mut: func(e *ExpectedMTState, st *multithreaded.State) { {name: "Active thread exited", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[st.GetCurrentThread().ThreadId].Exited = !st.GetCurrentThread().Exited e.threadExpectations[st.GetCurrentThread().ThreadId].Exited = !st.GetCurrentThread().Exited
}}, }},
{name: "Active thread futexAddr", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[st.GetCurrentThread().ThreadId].FutexAddr += 1
}},
{name: "Active thread futexVal", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[st.GetCurrentThread().ThreadId].FutexVal += 1
}},
{name: "Active thread FutexTimeoutStep", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[st.GetCurrentThread().ThreadId].FutexTimeoutStep += 1
}},
{name: "Active thread PC", mut: func(e *ExpectedMTState, st *multithreaded.State) { {name: "Active thread PC", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[st.GetCurrentThread().ThreadId].PC += 1 e.threadExpectations[st.GetCurrentThread().ThreadId].PC += 1
}}, }},
...@@ -96,15 +86,6 @@ func TestValidate_shouldCatchMutations(t *testing.T) { ...@@ -96,15 +86,6 @@ func TestValidate_shouldCatchMutations(t *testing.T) {
{name: "Inactive thread exited", mut: func(e *ExpectedMTState, st *multithreaded.State) { {name: "Inactive thread exited", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[FindNextThread(st).ThreadId].Exited = !FindNextThread(st).Exited e.threadExpectations[FindNextThread(st).ThreadId].Exited = !FindNextThread(st).Exited
}}, }},
{name: "Inactive thread futexAddr", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[FindNextThread(st).ThreadId].FutexAddr += 1
}},
{name: "Inactive thread futexVal", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[FindNextThread(st).ThreadId].FutexVal += 1
}},
{name: "Inactive thread FutexTimeoutStep", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[FindNextThread(st).ThreadId].FutexTimeoutStep += 1
}},
{name: "Inactive thread PC", mut: func(e *ExpectedMTState, st *multithreaded.State) { {name: "Inactive thread PC", mut: func(e *ExpectedMTState, st *multithreaded.State) {
e.threadExpectations[FindNextThread(st).ThreadId].PC += 1 e.threadExpectations[FindNextThread(st).ThreadId].PC += 1
}}, }},
......
...@@ -9,21 +9,17 @@ import ( ...@@ -9,21 +9,17 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch" "github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/exec"
) )
const ( const (
THREAD_ID_STATE_WITNESS_OFFSET = 0 THREAD_ID_STATE_WITNESS_OFFSET = 0
THREAD_EXIT_CODE_WITNESS_OFFSET = THREAD_ID_STATE_WITNESS_OFFSET + arch.WordSizeBytes THREAD_EXIT_CODE_WITNESS_OFFSET = THREAD_ID_STATE_WITNESS_OFFSET + arch.WordSizeBytes
THREAD_EXITED_WITNESS_OFFSET = THREAD_EXIT_CODE_WITNESS_OFFSET + 1 THREAD_EXITED_WITNESS_OFFSET = THREAD_EXIT_CODE_WITNESS_OFFSET + 1
THREAD_FUTEX_ADDR_WITNESS_OFFSET = THREAD_EXITED_WITNESS_OFFSET + 1 THREAD_CPU_WITNESS_OFFSET = THREAD_EXITED_WITNESS_OFFSET + 1
THREAD_FUTEX_VAL_WITNESS_OFFSET = THREAD_FUTEX_ADDR_WITNESS_OFFSET + arch.WordSizeBytes THREAD_REGISTERS_WITNESS_OFFSET = THREAD_CPU_WITNESS_OFFSET + (4 * arch.WordSizeBytes)
THREAD_FUTEX_TIMEOUT_STEP_WITNESS_OFFSET = THREAD_FUTEX_VAL_WITNESS_OFFSET + 4
THREAD_FUTEX_CPU_WITNESS_OFFSET = THREAD_FUTEX_TIMEOUT_STEP_WITNESS_OFFSET + 8
THREAD_REGISTERS_WITNESS_OFFSET = THREAD_FUTEX_CPU_WITNESS_OFFSET + (4 * arch.WordSizeBytes)
// SERIALIZED_THREAD_SIZE is the size of a serialized ThreadState object // SERIALIZED_THREAD_SIZE is the size of a serialized ThreadState object
// 166 and 318 bytes for 32 and 64-bit respectively // 150 and 298 bytes for 32 and 64-bit respectively
SERIALIZED_THREAD_SIZE = THREAD_REGISTERS_WITNESS_OFFSET + (32 * arch.WordSizeBytes) SERIALIZED_THREAD_SIZE = THREAD_REGISTERS_WITNESS_OFFSET + (32 * arch.WordSizeBytes)
// THREAD_WITNESS_SIZE is the size of a thread witness encoded in bytes. // THREAD_WITNESS_SIZE is the size of a thread witness encoded in bytes.
...@@ -40,9 +36,6 @@ type ThreadState struct { ...@@ -40,9 +36,6 @@ type ThreadState struct {
ThreadId Word `json:"threadId"` ThreadId Word `json:"threadId"`
ExitCode uint8 `json:"exit"` ExitCode uint8 `json:"exit"`
Exited bool `json:"exited"` Exited bool `json:"exited"`
FutexAddr Word `json:"futexAddr"`
FutexVal uint32 `json:"futexVal"`
FutexTimeoutStep uint64 `json:"futexTimeoutStep"`
Cpu mipsevm.CpuScalars `json:"cpu"` Cpu mipsevm.CpuScalars `json:"cpu"`
Registers [32]Word `json:"registers"` Registers [32]Word `json:"registers"`
} }
...@@ -59,9 +52,6 @@ func CreateEmptyThread() *ThreadState { ...@@ -59,9 +52,6 @@ func CreateEmptyThread() *ThreadState {
LO: 0, LO: 0,
HI: 0, HI: 0,
}, },
FutexAddr: exec.FutexEmptyAddr,
FutexVal: 0,
FutexTimeoutStep: 0,
Registers: [32]Word{}, Registers: [32]Word{},
} }
} }
...@@ -72,9 +62,6 @@ func (t *ThreadState) serializeThread() []byte { ...@@ -72,9 +62,6 @@ func (t *ThreadState) serializeThread() []byte {
out = arch.ByteOrderWord.AppendWord(out, t.ThreadId) out = arch.ByteOrderWord.AppendWord(out, t.ThreadId)
out = append(out, t.ExitCode) out = append(out, t.ExitCode)
out = mipsevm.AppendBoolToWitness(out, t.Exited) out = mipsevm.AppendBoolToWitness(out, t.Exited)
out = arch.ByteOrderWord.AppendWord(out, t.FutexAddr)
out = binary.BigEndian.AppendUint32(out, t.FutexVal)
out = binary.BigEndian.AppendUint64(out, t.FutexTimeoutStep)
out = arch.ByteOrderWord.AppendWord(out, t.Cpu.PC) out = arch.ByteOrderWord.AppendWord(out, t.Cpu.PC)
out = arch.ByteOrderWord.AppendWord(out, t.Cpu.NextPC) out = arch.ByteOrderWord.AppendWord(out, t.Cpu.NextPC)
...@@ -107,15 +94,6 @@ func (t *ThreadState) Deserialize(in io.Reader) error { ...@@ -107,15 +94,6 @@ func (t *ThreadState) Deserialize(in io.Reader) error {
return err return err
} }
t.Exited = exited != 0 t.Exited = exited != 0
if err := binary.Read(in, binary.BigEndian, &t.FutexAddr); err != nil {
return err
}
if err := binary.Read(in, binary.BigEndian, &t.FutexVal); err != nil {
return err
}
if err := binary.Read(in, binary.BigEndian, &t.FutexTimeoutStep); err != nil {
return err
}
if err := binary.Read(in, binary.BigEndian, &t.Cpu.PC); err != nil { if err := binary.Read(in, binary.BigEndian, &t.Cpu.PC); err != nil {
return err return err
} }
......
...@@ -25,5 +25,4 @@ const ( ...@@ -25,5 +25,4 @@ const (
RegSyscallParam1 = RegA0 RegSyscallParam1 = RegA0
RegSyscallParam2 = RegA1 RegSyscallParam2 = RegA1
RegSyscallParam3 = RegA2 RegSyscallParam3 = RegA2
RegSyscallParam4 = RegA3
) )
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
type Word = arch.Word type Word = arch.Word
func (m *InstrumentedState) handleSyscall() error { func (m *InstrumentedState) handleSyscall() error {
syscallNum, a0, a1, a2, _ := exec.GetSyscallArgs(&m.state.Registers) syscallNum, a0, a1, a2 := exec.GetSyscallArgs(&m.state.Registers)
v0 := Word(0) v0 := Word(0)
v1 := Word(0) v1 := Word(0)
......
...@@ -964,7 +964,7 @@ func TestEVM_HelloProgram(t *testing.T) { ...@@ -964,7 +964,7 @@ func TestEVM_HelloProgram(t *testing.T) {
break break
} }
insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) insn := testutil.GetInstruction(state.GetMemory(), state.GetPC())
if i%10_000 == 0 { // avoid spamming test logs, we are executing many steps if i%100_000 == 0 { // avoid spamming test logs, we are executing many steps
t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn)
} }
...@@ -1012,7 +1012,7 @@ func TestEVM_ClaimProgram(t *testing.T) { ...@@ -1012,7 +1012,7 @@ func TestEVM_ClaimProgram(t *testing.T) {
} }
insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) insn := testutil.GetInstruction(state.GetMemory(), state.GetPC())
if i%10_000 == 0 { // avoid spamming test logs, we are executing many steps if i%1_000_000 == 0 { // avoid spamming test logs, we are executing many steps
t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn)
} }
...@@ -1020,6 +1020,7 @@ func TestEVM_ClaimProgram(t *testing.T) { ...@@ -1020,6 +1020,7 @@ func TestEVM_ClaimProgram(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
validator.ValidateEVM(t, stepWitness, curStep, goVm) validator.ValidateEVM(t, stepWitness, curStep, goVm)
} }
t.Logf("Completed in %d steps", state.GetStep())
require.True(t, state.GetExited(), "must complete program") require.True(t, state.GetExited(), "must complete program")
require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0")
......
...@@ -27,7 +27,7 @@ func DetectVersion(path string) (StateVersion, error) { ...@@ -27,7 +27,7 @@ func DetectVersion(path string) (StateVersion, error) {
} }
switch ver { switch ver {
case VersionSingleThreaded, VersionMultiThreaded, VersionSingleThreaded2, VersionMultiThreaded64, VersionMultiThreaded64_v2: case VersionSingleThreaded, VersionMultiThreaded, VersionSingleThreaded2, VersionMultiThreaded64, VersionMultiThreaded64_v2, VersionMultiThreaded_v2, VersionMultiThreaded64_v3:
return ver, nil return ver, nil
default: default:
return 0, fmt.Errorf("%w: %d", ErrUnknownVersion, ver) return 0, fmt.Errorf("%w: %d", ErrUnknownVersion, ver)
......
...@@ -64,9 +64,9 @@ func TestDetectVersion_singleThreadedBinary(t *testing.T) { ...@@ -64,9 +64,9 @@ func TestDetectVersion_singleThreadedBinary(t *testing.T) {
} }
func TestDetectVersion_multiThreadedBinary(t *testing.T) { func TestDetectVersion_multiThreadedBinary(t *testing.T) {
targetVersion := VersionMultiThreaded targetVersion := VersionMultiThreaded_v2
if !arch.IsMips32 { if !arch.IsMips32 {
targetVersion = VersionMultiThreaded64_v2 targetVersion = VersionMultiThreaded64_v3
} }
state, err := NewFromState(multithreaded.CreateEmptyState()) state, err := NewFromState(multithreaded.CreateEmptyState())
......
...@@ -19,12 +19,19 @@ type StateVersion uint8 ...@@ -19,12 +19,19 @@ type StateVersion uint8
const ( const (
// VersionSingleThreaded is the version of the Cannon STF found in op-contracts/v1.6.0 - https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.6.0/packages/contracts-bedrock/src/cannon/MIPS.sol // VersionSingleThreaded is the version of the Cannon STF found in op-contracts/v1.6.0 - https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.6.0/packages/contracts-bedrock/src/cannon/MIPS.sol
VersionSingleThreaded StateVersion = iota VersionSingleThreaded StateVersion = iota
// VersionMultiThreaded is the original implementation of 32-bit multithreaded cannon, tagged at cannon/v1.3.0
VersionMultiThreaded VersionMultiThreaded
// VersionSingleThreaded2 is based on VersionSingleThreaded with the addition of support for fcntl(F_GETFD) syscall // VersionSingleThreaded2 is based on VersionSingleThreaded with the addition of support for fcntl(F_GETFD) syscall
// This is the latest 32-bit single-threaded vm
VersionSingleThreaded2 VersionSingleThreaded2
// VersionMultiThreaded64 is the original 64-bit MTCannon implementation (pre-audit), tagged at cannon/v1.2.0 // VersionMultiThreaded64 is the original 64-bit MTCannon implementation (pre-audit), tagged at cannon/v1.2.0
VersionMultiThreaded64 VersionMultiThreaded64
// VersionMultiThreaded64_v2 includes an audit fix to ensure futex values are always 32-bit, tagged at cannon/v1.3.0
VersionMultiThreaded64_v2 VersionMultiThreaded64_v2
// VersionMultiThreaded_v2 is the latest 32-bit multithreaded vm
VersionMultiThreaded_v2
// VersionMultiThreaded64_v3 is the latest 64-bit multithreaded vm
VersionMultiThreaded64_v3
) )
var ( var (
...@@ -33,7 +40,7 @@ var ( ...@@ -33,7 +40,7 @@ var (
ErrUnsupportedMipsArch = errors.New("mips architecture is not supported") ErrUnsupportedMipsArch = errors.New("mips architecture is not supported")
) )
var StateVersionTypes = []StateVersion{VersionSingleThreaded, VersionMultiThreaded, VersionSingleThreaded2, VersionMultiThreaded64, VersionMultiThreaded64_v2} var StateVersionTypes = []StateVersion{VersionSingleThreaded, VersionMultiThreaded, VersionSingleThreaded2, VersionMultiThreaded64, VersionMultiThreaded64_v2, VersionMultiThreaded_v2, VersionMultiThreaded64_v3}
func LoadStateFromFile(path string) (*VersionedState, error) { func LoadStateFromFile(path string) (*VersionedState, error) {
if !serialize.IsBinaryFile(path) { if !serialize.IsBinaryFile(path) {
...@@ -60,12 +67,12 @@ func NewFromState(state mipsevm.FPVMState) (*VersionedState, error) { ...@@ -60,12 +67,12 @@ func NewFromState(state mipsevm.FPVMState) (*VersionedState, error) {
case *multithreaded.State: case *multithreaded.State:
if arch.IsMips32 { if arch.IsMips32 {
return &VersionedState{ return &VersionedState{
Version: VersionMultiThreaded, Version: VersionMultiThreaded_v2,
FPVMState: state, FPVMState: state,
}, nil }, nil
} else { } else {
return &VersionedState{ return &VersionedState{
Version: VersionMultiThreaded64_v2, Version: VersionMultiThreaded64_v3,
FPVMState: state, FPVMState: state,
}, nil }, nil
} }
...@@ -106,7 +113,7 @@ func (s *VersionedState) Deserialize(in io.Reader) error { ...@@ -106,7 +113,7 @@ func (s *VersionedState) Deserialize(in io.Reader) error {
} }
s.FPVMState = state s.FPVMState = state
return nil return nil
case VersionMultiThreaded: case VersionMultiThreaded_v2:
if !arch.IsMips32 { if !arch.IsMips32 {
return ErrUnsupportedMipsArch return ErrUnsupportedMipsArch
} }
...@@ -116,7 +123,7 @@ func (s *VersionedState) Deserialize(in io.Reader) error { ...@@ -116,7 +123,7 @@ func (s *VersionedState) Deserialize(in io.Reader) error {
} }
s.FPVMState = state s.FPVMState = state
return nil return nil
case VersionMultiThreaded64_v2: case VersionMultiThreaded64_v3:
if arch.IsMips32 { if arch.IsMips32 {
return ErrUnsupportedMipsArch return ErrUnsupportedMipsArch
} }
...@@ -155,6 +162,10 @@ func (s StateVersion) String() string { ...@@ -155,6 +162,10 @@ func (s StateVersion) String() string {
return "multithreaded64" return "multithreaded64"
case VersionMultiThreaded64_v2: case VersionMultiThreaded64_v2:
return "multithreaded64-2" return "multithreaded64-2"
case VersionMultiThreaded_v2:
return "multithreaded-2"
case VersionMultiThreaded64_v3:
return "multithreaded64-3"
default: default:
return "unknown" return "unknown"
} }
...@@ -172,6 +183,10 @@ func ParseStateVersion(ver string) (StateVersion, error) { ...@@ -172,6 +183,10 @@ func ParseStateVersion(ver string) (StateVersion, error) {
return VersionMultiThreaded64, nil return VersionMultiThreaded64, nil
case "multithreaded64-2": case "multithreaded64-2":
return VersionMultiThreaded64_v2, nil return VersionMultiThreaded64_v2, nil
case "multithreaded-2":
return VersionMultiThreaded_v2, nil
case "multithreaded64-3":
return VersionMultiThreaded64_v3, nil
default: default:
return StateVersion(0), errors.New("unknown state version") return StateVersion(0), errors.New("unknown state version")
} }
......
...@@ -15,16 +15,16 @@ import ( ...@@ -15,16 +15,16 @@ import (
) )
func TestNewFromState(t *testing.T) { func TestNewFromState(t *testing.T) {
t.Run("multithreaded64-2", func(t *testing.T) { t.Run("multithreaded64-latestVersion", func(t *testing.T) {
actual, err := NewFromState(multithreaded.CreateEmptyState()) actual, err := NewFromState(multithreaded.CreateEmptyState())
require.NoError(t, err) require.NoError(t, err)
require.IsType(t, &multithreaded.State{}, actual.FPVMState) require.IsType(t, &multithreaded.State{}, actual.FPVMState)
require.Equal(t, VersionMultiThreaded64_v2, actual.Version) require.Equal(t, VersionMultiThreaded64_v3, actual.Version)
}) })
} }
func TestLoadStateFromFile(t *testing.T) { func TestLoadStateFromFile(t *testing.T) {
t.Run("Multithreaded64_v2_FromBinary", func(t *testing.T) { t.Run("Multithreaded64_latestVersion_FromBinary", func(t *testing.T) {
expected, err := NewFromState(multithreaded.CreateEmptyState()) expected, err := NewFromState(multithreaded.CreateEmptyState())
require.NoError(t, err) require.NoError(t, err)
...@@ -40,7 +40,7 @@ func TestVersionsOtherThanZeroDoNotSupportJSON(t *testing.T) { ...@@ -40,7 +40,7 @@ func TestVersionsOtherThanZeroDoNotSupportJSON(t *testing.T) {
version StateVersion version StateVersion
createState func() mipsevm.FPVMState createState func() mipsevm.FPVMState
}{ }{
{VersionMultiThreaded64_v2, func() mipsevm.FPVMState { return multithreaded.CreateEmptyState() }}, {VersionMultiThreaded64_v3, func() mipsevm.FPVMState { return multithreaded.CreateEmptyState() }},
} }
for _, test := range tests { for _, test := range tests {
test := test test := test
......
...@@ -16,18 +16,18 @@ import ( ...@@ -16,18 +16,18 @@ import (
) )
func TestNewFromState(t *testing.T) { func TestNewFromState(t *testing.T) {
t.Run("singlethreaded-2", func(t *testing.T) { t.Run("singlethreaded-latestVersion", func(t *testing.T) {
actual, err := NewFromState(singlethreaded.CreateEmptyState()) actual, err := NewFromState(singlethreaded.CreateEmptyState())
require.NoError(t, err) require.NoError(t, err)
require.IsType(t, &singlethreaded.State{}, actual.FPVMState) require.IsType(t, &singlethreaded.State{}, actual.FPVMState)
require.Equal(t, VersionSingleThreaded2, actual.Version) require.Equal(t, VersionSingleThreaded2, actual.Version)
}) })
t.Run("multithreaded", func(t *testing.T) { t.Run("multithreaded-latestVersion", func(t *testing.T) {
actual, err := NewFromState(multithreaded.CreateEmptyState()) actual, err := NewFromState(multithreaded.CreateEmptyState())
require.NoError(t, err) require.NoError(t, err)
require.IsType(t, &multithreaded.State{}, actual.FPVMState) require.IsType(t, &multithreaded.State{}, actual.FPVMState)
require.Equal(t, VersionMultiThreaded, actual.Version) require.Equal(t, VersionMultiThreaded_v2, actual.Version)
}) })
} }
...@@ -59,7 +59,7 @@ func TestVersionsOtherThanZeroDoNotSupportJSON(t *testing.T) { ...@@ -59,7 +59,7 @@ func TestVersionsOtherThanZeroDoNotSupportJSON(t *testing.T) {
createState func() mipsevm.FPVMState createState func() mipsevm.FPVMState
}{ }{
{VersionSingleThreaded2, func() mipsevm.FPVMState { return singlethreaded.CreateEmptyState() }}, {VersionSingleThreaded2, func() mipsevm.FPVMState { return singlethreaded.CreateEmptyState() }},
{VersionMultiThreaded, func() mipsevm.FPVMState { return multithreaded.CreateEmptyState() }}, {VersionMultiThreaded_v2, func() mipsevm.FPVMState { return multithreaded.CreateEmptyState() }},
} }
for _, test := range tests { for _, test := range tests {
test := test test := test
...@@ -75,6 +75,16 @@ func TestVersionsOtherThanZeroDoNotSupportJSON(t *testing.T) { ...@@ -75,6 +75,16 @@ func TestVersionsOtherThanZeroDoNotSupportJSON(t *testing.T) {
} }
} }
func TestParseStateVersion(t *testing.T) {
for _, version := range StateVersionTypes {
t.Run(version.String(), func(t *testing.T) {
result, err := ParseStateVersion(version.String())
require.NoError(t, err)
require.Equal(t, version, result)
})
}
}
func writeToFile(t *testing.T, filename string, data serialize.Serializable) string { func writeToFile(t *testing.T, filename string, data serialize.Serializable) string {
dir := t.TempDir() dir := t.TempDir()
path := filepath.Join(dir, filename) path := filepath.Join(dir, filename)
......
...@@ -198,7 +198,6 @@ func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64 ...@@ -198,7 +198,6 @@ func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64
e.metrics.RecordMaxStepsBetweenLLAndSC(uint64(info.MaxStepsBetweenLLAndSC)) e.metrics.RecordMaxStepsBetweenLLAndSC(uint64(info.MaxStepsBetweenLLAndSC))
e.metrics.RecordReservationInvalidationCount(uint64(info.ReservationInvalidationCount)) e.metrics.RecordReservationInvalidationCount(uint64(info.ReservationInvalidationCount))
e.metrics.RecordForcedPreemptionCount(uint64(info.ForcedPreemptionCount)) e.metrics.RecordForcedPreemptionCount(uint64(info.ForcedPreemptionCount))
e.metrics.RecordFailedWakeupCount(uint64(info.FailedWakeupCount))
e.metrics.RecordIdleStepCountThread0(uint64(info.IdleStepCountThread0)) e.metrics.RecordIdleStepCountThread0(uint64(info.IdleStepCountThread0))
} }
} }
...@@ -214,6 +213,5 @@ type debugInfo struct { ...@@ -214,6 +213,5 @@ type debugInfo struct {
MaxStepsBetweenLLAndSC uint64 `json:"max_steps_between_ll_and_sc"` MaxStepsBetweenLLAndSC uint64 `json:"max_steps_between_ll_and_sc"`
ReservationInvalidationCount uint64 `json:"reservation_invalidation_count"` ReservationInvalidationCount uint64 `json:"reservation_invalidation_count"`
ForcedPreemptionCount uint64 `json:"forced_preemption_count"` ForcedPreemptionCount uint64 `json:"forced_preemption_count"`
FailedWakeupCount uint64 `json:"failed_wakeup_count"`
IdleStepCountThread0 uint64 `json:"idle_step_count_thread_0"` IdleStepCountThread0 uint64 `json:"idle_step_count_thread_0"`
} }
...@@ -53,7 +53,6 @@ func TestGenerateProof(t *testing.T) { ...@@ -53,7 +53,6 @@ func TestGenerateProof(t *testing.T) {
MaxStepsBetweenLLAndSC: 56, MaxStepsBetweenLLAndSC: 56,
ReservationInvalidationCount: 78, ReservationInvalidationCount: 78,
ForcedPreemptionCount: 910, ForcedPreemptionCount: 910,
FailedWakeupCount: 1112,
IdleStepCountThread0: 1314, IdleStepCountThread0: 1314,
} }
...@@ -191,7 +190,6 @@ func validateMetrics(t require.TestingT, m *capturingVmMetrics, expected *mipsev ...@@ -191,7 +190,6 @@ func validateMetrics(t require.TestingT, m *capturingVmMetrics, expected *mipsev
require.Equal(t, expected.MaxStepsBetweenLLAndSC, m.maxStepsBetweenLLAndSC) require.Equal(t, expected.MaxStepsBetweenLLAndSC, m.maxStepsBetweenLLAndSC)
require.Equal(t, expected.ReservationInvalidationCount, m.reservationInvalidations) require.Equal(t, expected.ReservationInvalidationCount, m.reservationInvalidations)
require.Equal(t, expected.ForcedPreemptionCount, m.forcedPreemptions) require.Equal(t, expected.ForcedPreemptionCount, m.forcedPreemptions)
require.Equal(t, expected.FailedWakeupCount, m.failedWakeup)
require.Equal(t, expected.IdleStepCountThread0, m.idleStepsThread0) require.Equal(t, expected.IdleStepCountThread0, m.idleStepsThread0)
} else { } else {
// If debugInfo is disabled, json file should not be written and metrics should be zeroed out // If debugInfo is disabled, json file should not be written and metrics should be zeroed out
...@@ -202,7 +200,6 @@ func validateMetrics(t require.TestingT, m *capturingVmMetrics, expected *mipsev ...@@ -202,7 +200,6 @@ func validateMetrics(t require.TestingT, m *capturingVmMetrics, expected *mipsev
require.Equal(t, uint64(0), m.maxStepsBetweenLLAndSC) require.Equal(t, uint64(0), m.maxStepsBetweenLLAndSC)
require.Equal(t, uint64(0), m.reservationInvalidations) require.Equal(t, uint64(0), m.reservationInvalidations)
require.Equal(t, uint64(0), m.forcedPreemptions) require.Equal(t, uint64(0), m.forcedPreemptions)
require.Equal(t, uint64(0), m.failedWakeup)
require.Equal(t, uint64(0), m.idleStepsThread0) require.Equal(t, uint64(0), m.idleStepsThread0)
} }
} }
...@@ -220,7 +217,6 @@ type capturingVmMetrics struct { ...@@ -220,7 +217,6 @@ type capturingVmMetrics struct {
maxStepsBetweenLLAndSC uint64 maxStepsBetweenLLAndSC uint64
reservationInvalidations uint64 reservationInvalidations uint64
forcedPreemptions uint64 forcedPreemptions uint64
failedWakeup uint64
idleStepsThread0 uint64 idleStepsThread0 uint64
} }
...@@ -256,10 +252,6 @@ func (c *capturingVmMetrics) RecordForcedPreemptionCount(val uint64) { ...@@ -256,10 +252,6 @@ func (c *capturingVmMetrics) RecordForcedPreemptionCount(val uint64) {
c.forcedPreemptions = val c.forcedPreemptions = val
} }
func (c *capturingVmMetrics) RecordFailedWakeupCount(val uint64) {
c.failedWakeup = val
}
func (c *capturingVmMetrics) RecordIdleStepCountThread0(val uint64) { func (c *capturingVmMetrics) RecordIdleStepCountThread0(val uint64) {
c.idleStepsThread0 = val c.idleStepsThread0 = val
} }
......
...@@ -17,7 +17,6 @@ type VmMetricer interface { ...@@ -17,7 +17,6 @@ type VmMetricer interface {
RecordVmMaxStepsBetweenLLAndSC(vmType string, val uint64) RecordVmMaxStepsBetweenLLAndSC(vmType string, val uint64)
RecordVmReservationInvalidationCount(vmType string, val uint64) RecordVmReservationInvalidationCount(vmType string, val uint64)
RecordVmForcedPreemptionCount(vmType string, val uint64) RecordVmForcedPreemptionCount(vmType string, val uint64)
RecordVmFailedWakeupCount(vmType string, val uint64)
RecordVmIdleStepCountThread0(vmType string, val uint64) RecordVmIdleStepCountThread0(vmType string, val uint64)
} }
...@@ -31,7 +30,6 @@ type TypedVmMetricer interface { ...@@ -31,7 +30,6 @@ type TypedVmMetricer interface {
RecordMaxStepsBetweenLLAndSC(val uint64) RecordMaxStepsBetweenLLAndSC(val uint64)
RecordReservationInvalidationCount(val uint64) RecordReservationInvalidationCount(val uint64)
RecordForcedPreemptionCount(val uint64) RecordForcedPreemptionCount(val uint64)
RecordFailedWakeupCount(val uint64)
RecordIdleStepCountThread0(val uint64) RecordIdleStepCountThread0(val uint64)
} }
...@@ -44,7 +42,6 @@ type VmMetrics struct { ...@@ -44,7 +42,6 @@ type VmMetrics struct {
vmMaxStepsBetweenLLAndSC *prometheus.GaugeVec vmMaxStepsBetweenLLAndSC *prometheus.GaugeVec
vmReservationInvalidations *prometheus.GaugeVec vmReservationInvalidations *prometheus.GaugeVec
vmForcedPreemptions *prometheus.GaugeVec vmForcedPreemptions *prometheus.GaugeVec
vmFailedWakeup *prometheus.GaugeVec
vmIdleStepsThread0 *prometheus.GaugeVec vmIdleStepsThread0 *prometheus.GaugeVec
} }
...@@ -82,10 +79,6 @@ func (m *VmMetrics) RecordVmForcedPreemptionCount(vmType string, val uint64) { ...@@ -82,10 +79,6 @@ func (m *VmMetrics) RecordVmForcedPreemptionCount(vmType string, val uint64) {
m.vmForcedPreemptions.WithLabelValues(vmType).Set(float64(val)) m.vmForcedPreemptions.WithLabelValues(vmType).Set(float64(val))
} }
func (m *VmMetrics) RecordVmFailedWakeupCount(vmType string, val uint64) {
m.vmFailedWakeup.WithLabelValues(vmType).Set(float64(val))
}
func (m *VmMetrics) RecordVmIdleStepCountThread0(vmType string, val uint64) { func (m *VmMetrics) RecordVmIdleStepCountThread0(vmType string, val uint64) {
m.vmIdleStepsThread0.WithLabelValues(vmType).Set(float64(val)) m.vmIdleStepsThread0.WithLabelValues(vmType).Set(float64(val))
} }
...@@ -137,11 +130,6 @@ func NewVmMetrics(namespace string, factory metrics.Factory) *VmMetrics { ...@@ -137,11 +130,6 @@ func NewVmMetrics(namespace string, factory metrics.Factory) *VmMetrics {
Name: "vm_forced_preemptions", Name: "vm_forced_preemptions",
Help: "Number of forced preemptions during vm run", Help: "Number of forced preemptions during vm run",
}, []string{"vm"}), }, []string{"vm"}),
vmFailedWakeup: factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Name: "vm_failed_wakeup",
Help: "Number of failed wakesups during vm run",
}, []string{"vm"}),
vmIdleStepsThread0: factory.NewGaugeVec(prometheus.GaugeOpts{ vmIdleStepsThread0: factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace, Namespace: namespace,
Name: "vm_idle_steps_thread0", Name: "vm_idle_steps_thread0",
...@@ -162,7 +150,6 @@ func (n NoopVmMetrics) RecordVmRmwFailCount(vmType string, val uint64) ...@@ -162,7 +150,6 @@ func (n NoopVmMetrics) RecordVmRmwFailCount(vmType string, val uint64)
func (n NoopVmMetrics) RecordVmMaxStepsBetweenLLAndSC(vmType string, val uint64) {} func (n NoopVmMetrics) RecordVmMaxStepsBetweenLLAndSC(vmType string, val uint64) {}
func (n NoopVmMetrics) RecordVmReservationInvalidationCount(vmType string, val uint64) {} func (n NoopVmMetrics) RecordVmReservationInvalidationCount(vmType string, val uint64) {}
func (n NoopVmMetrics) RecordVmForcedPreemptionCount(vmType string, val uint64) {} func (n NoopVmMetrics) RecordVmForcedPreemptionCount(vmType string, val uint64) {}
func (n NoopVmMetrics) RecordVmFailedWakeupCount(vmType string, val uint64) {}
func (n NoopVmMetrics) RecordVmIdleStepCountThread0(vmType string, val uint64) {} func (n NoopVmMetrics) RecordVmIdleStepCountThread0(vmType string, val uint64) {}
type typedVmMetricsImpl struct { type typedVmMetricsImpl struct {
...@@ -204,10 +191,6 @@ func (m *typedVmMetricsImpl) RecordForcedPreemptionCount(val uint64) { ...@@ -204,10 +191,6 @@ func (m *typedVmMetricsImpl) RecordForcedPreemptionCount(val uint64) {
m.m.RecordVmForcedPreemptionCount(m.vmType, val) m.m.RecordVmForcedPreemptionCount(m.vmType, val)
} }
func (m *typedVmMetricsImpl) RecordFailedWakeupCount(val uint64) {
m.m.RecordVmFailedWakeupCount(m.vmType, val)
}
func (m *typedVmMetricsImpl) RecordIdleStepCountThread0(val uint64) { func (m *typedVmMetricsImpl) RecordIdleStepCountThread0(val uint64) {
m.m.RecordVmIdleStepCountThread0(m.vmType, val) m.m.RecordVmIdleStepCountThread0(m.vmType, val)
} }
......
...@@ -34,9 +34,9 @@ RUN --mount=type=cache,target=/root/.cache/go-build cd op-program && make op-pro ...@@ -34,9 +34,9 @@ RUN --mount=type=cache,target=/root/.cache/go-build cd op-program && make op-pro
# Run the op-program-client.elf binary directly through cannon's load-elf subcommand. # Run the op-program-client.elf binary directly through cannon's load-elf subcommand.
RUN /app/cannon/bin/cannon load-elf --type singlethreaded-2 --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.bin.gz --meta "/app/op-program/bin/meta.json" RUN /app/cannon/bin/cannon load-elf --type singlethreaded-2 --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.bin.gz --meta "/app/op-program/bin/meta.json"
RUN /app/cannon/bin/cannon load-elf --type multithreaded --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate-mt.bin.gz --meta "/app/op-program/bin/meta-mt.json" RUN /app/cannon/bin/cannon load-elf --type multithreaded-2 --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate-mt.bin.gz --meta "/app/op-program/bin/meta-mt.json"
RUN /app/cannon/bin/cannon load-elf --type multithreaded64-2 --path /app/op-program/bin/op-program-client64.elf --out /app/op-program/bin/prestate-mt64.bin.gz --meta "/app/op-program/bin/meta-mt64.json" RUN /app/cannon/bin/cannon load-elf --type multithreaded64-3 --path /app/op-program/bin/op-program-client64.elf --out /app/op-program/bin/prestate-mt64.bin.gz --meta "/app/op-program/bin/meta-mt64.json"
RUN /app/cannon/bin/cannon load-elf --type multithreaded64-2 --path /app/op-program/bin/op-program-client-interop.elf --out /app/op-program/bin/prestate-interop.bin.gz --meta "/app/op-program/bin/meta-interop.json" RUN /app/cannon/bin/cannon load-elf --type multithreaded64-3 --path /app/op-program/bin/op-program-client-interop.elf --out /app/op-program/bin/prestate-interop.bin.gz --meta "/app/op-program/bin/meta-interop.json"
# Generate the prestate proof containing the absolute pre-state hash. # Generate the prestate proof containing the absolute pre-state hash.
RUN /app/cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input /app/op-program/bin/prestate.bin.gz --meta "" --proof-fmt '/app/op-program/bin/%d.json' --output "" RUN /app/cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input /app/op-program/bin/prestate.bin.gz --meta "" --proof-fmt '/app/op-program/bin/%d.json' --output ""
......
...@@ -65,12 +65,15 @@ ARG TARGETARCH ...@@ -65,12 +65,15 @@ ARG TARGETARCH
FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/cannon:v1.0.0 AS cannon-builder-v1-0-0 FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/cannon:v1.0.0 AS cannon-builder-v1-0-0
FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/cannon:v1.2.0 AS cannon-builder-v1-2-0 FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/cannon:v1.2.0 AS cannon-builder-v1-2-0
FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/cannon:v1.3.0 AS cannon-builder-v1-3-0
FROM --platform=$BUILDPLATFORM builder AS cannon-builder FROM --platform=$BUILDPLATFORM builder AS cannon-builder
ARG CANNON_VERSION=v0.0.0 ARG CANNON_VERSION=v0.0.0
# Copy cannon binaries from previous versions # Copy cannon binaries from previous versions
COPY --from=cannon-builder-v1-0-0 /usr/local/bin/cannon ./cannon/multicannon/embeds/cannon-0 COPY --from=cannon-builder-v1-0-0 /usr/local/bin/cannon ./cannon/multicannon/embeds/cannon-0
COPY --from=cannon-builder-v1-2-0 /usr/local/bin/cannon-3 ./cannon/multicannon/embeds/cannon-3 COPY --from=cannon-builder-v1-2-0 /usr/local/bin/cannon-3 ./cannon/multicannon/embeds/cannon-3
COPY --from=cannon-builder-v1-3-0 /usr/local/bin/cannon-1 ./cannon/multicannon/embeds/cannon-1
COPY --from=cannon-builder-v1-3-0 /usr/local/bin/cannon-4 ./cannon/multicannon/embeds/cannon-4
# Build current binaries # Build current binaries
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd cannon && make cannon \ RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd cannon && make cannon \
GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$CANNON_VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$CANNON_VERSION"
......
...@@ -11,9 +11,6 @@ interface IMIPS2 is ISemver { ...@@ -11,9 +11,6 @@ interface IMIPS2 is ISemver {
uint32 threadID; uint32 threadID;
uint8 exitCode; uint8 exitCode;
bool exited; bool exited;
uint32 futexAddr;
uint32 futexVal;
uint64 futexTimeoutStep;
uint32 pc; uint32 pc;
uint32 nextPC; uint32 nextPC;
uint32 lo; uint32 lo;
...@@ -33,7 +30,6 @@ interface IMIPS2 is ISemver { ...@@ -33,7 +30,6 @@ interface IMIPS2 is ISemver {
bool exited; bool exited;
uint64 step; uint64 step;
uint64 stepsSinceLastContextSwitch; uint64 stepsSinceLastContextSwitch;
uint32 wakeup;
bool traverseRight; bool traverseRight;
bytes32 leftThreadStack; bytes32 leftThreadStack;
bytes32 rightThreadStack; bytes32 rightThreadStack;
......
...@@ -140,16 +140,16 @@ ...@@ -140,16 +140,16 @@
"sourceCodeHash": "0xe9964aa66db1dfc86772958b4c9276697e67f7055529a43e6a49a055009bc995" "sourceCodeHash": "0xe9964aa66db1dfc86772958b4c9276697e67f7055529a43e6a49a055009bc995"
}, },
"src/cannon/MIPS.sol": { "src/cannon/MIPS.sol": {
"initCodeHash": "0xc10654f0e6498f424f7a5095bac36005dc7062d3813cc8f805a15005fc37406b", "initCodeHash": "0x7d0fc7c7b51b74fa2611aaa8cc1a5967e2e48f0726ea894eb2c43f36b0ff2ab7",
"sourceCodeHash": "0x6c45dd23cb0d6f9bf4f84855ad0caf70e53dee3fe6c41454f7bf8df52ec3a9af" "sourceCodeHash": "0xc18f51210c9d75f9bc33e55f879e8f0ab2514924718022264c0a2993134821e0"
}, },
"src/cannon/MIPS2.sol": { "src/cannon/MIPS2.sol": {
"initCodeHash": "0x70ecbb2327fadd6205312aa93279a6340242dfeb44a00b98caa7b56688c46bdc", "initCodeHash": "0x4e1dbd0a6ac84873622af9234aca42e6e7b2bfda1186bbfd3ff83081f141ef86",
"sourceCodeHash": "0x84506539c40b72b1d40c9d07418650b30c27d2b219b40e55f61edcd31365157f" "sourceCodeHash": "0x62c820b22c72399efd7688dcf713c34a6ee6821835ec66d5e7b98f33bbbfb209"
}, },
"src/cannon/MIPS64.sol": { "src/cannon/MIPS64.sol": {
"initCodeHash": "0xa2a42c50d2fac71d93e44ad4871e5d838f1c630b9d1abc4c89971d36b0ae44bb", "initCodeHash": "0xd15808bd3a9f0779dfc662dd75fb11fe5f2ff15c3a6e9f699d05dad49e064afb",
"sourceCodeHash": "0xdb771f1b92c7612b120e0bce31967f0c8a7ce332dbb426bc9cfc52b47be21c4d" "sourceCodeHash": "0x84609ac875a282e8a0675bcd8558635dcd7d054cc23395691d87922a15a815ba"
}, },
"src/cannon/PreimageOracle.sol": { "src/cannon/PreimageOracle.sol": {
"initCodeHash": "0x17d3b3df1aaaf7a705b8d48de8a05e6511b910fdafdbe5eb7f7f95ec944fba9a", "initCodeHash": "0x17d3b3df1aaaf7a705b8d48de8a05e6511b910fdafdbe5eb7f7f95ec944fba9a",
......
...@@ -47,8 +47,8 @@ contract MIPS is ISemver { ...@@ -47,8 +47,8 @@ contract MIPS is ISemver {
} }
/// @notice The semantic version of the MIPS contract. /// @notice The semantic version of the MIPS contract.
/// @custom:semver 1.2.1-beta.10 /// @custom:semver 1.3.0-beta.1
string public constant version = "1.2.1-beta.10"; string public constant version = "1.3.0-beta.1";
/// @notice The preimage oracle contract. /// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE; IPreimageOracle internal immutable ORACLE;
...@@ -151,7 +151,7 @@ contract MIPS is ISemver { ...@@ -151,7 +151,7 @@ contract MIPS is ISemver {
} }
// Load the syscall numbers and args from the registers // Load the syscall numbers and args from the registers
(uint32 syscall_no, uint32 a0, uint32 a1, uint32 a2,) = sys.getSyscallArgs(state.registers); (uint32 syscall_no, uint32 a0, uint32 a1, uint32 a2) = sys.getSyscallArgs(state.registers);
uint32 v0 = 0; uint32 v0 = 0;
uint32 v1 = 0; uint32 v1 = 0;
......
...@@ -119,9 +119,6 @@ library MIPS64Syscalls { ...@@ -119,9 +119,6 @@ library MIPS64Syscalls {
uint64 internal constant FUTEX_WAIT_PRIVATE = 128; uint64 internal constant FUTEX_WAIT_PRIVATE = 128;
uint64 internal constant FUTEX_WAKE_PRIVATE = 129; uint64 internal constant FUTEX_WAKE_PRIVATE = 129;
uint64 internal constant FUTEX_TIMEOUT_STEPS = 10000;
uint64 internal constant FUTEX_NO_TIMEOUT = type(uint64).max;
uint64 internal constant FUTEX_EMPTY_ADDR = U64_MASK;
uint64 internal constant SCHED_QUANTUM = 100_000; uint64 internal constant SCHED_QUANTUM = 100_000;
uint64 internal constant HZ = 10_000_000; uint64 internal constant HZ = 10_000_000;
...@@ -168,7 +165,6 @@ library MIPS64Syscalls { ...@@ -168,7 +165,6 @@ library MIPS64Syscalls {
uint32 internal constant REG_SYSCALL_PARAM1 = REG_A0; uint32 internal constant REG_SYSCALL_PARAM1 = REG_A0;
uint32 internal constant REG_SYSCALL_PARAM2 = REG_A1; uint32 internal constant REG_SYSCALL_PARAM2 = REG_A1;
uint32 internal constant REG_SYSCALL_PARAM3 = REG_A2; uint32 internal constant REG_SYSCALL_PARAM3 = REG_A2;
uint32 internal constant REG_SYSCALL_PARAM4 = REG_A3;
// Constants copied from MIPS64Arch for use in Yul // Constants copied from MIPS64Arch for use in Yul
uint64 internal constant WORD_SIZE_BYTES = 8; uint64 internal constant WORD_SIZE_BYTES = 8;
...@@ -180,11 +176,10 @@ library MIPS64Syscalls { ...@@ -180,11 +176,10 @@ library MIPS64Syscalls {
/// @return a0_ The first argument available to the syscall operation. /// @return a0_ The first argument available to the syscall operation.
/// @return a1_ The second argument available to the syscall operation. /// @return a1_ The second argument available to the syscall operation.
/// @return a2_ The third argument available to the syscall operation. /// @return a2_ The third argument available to the syscall operation.
/// @return a3_ The fourth argument available to the syscall operation.
function getSyscallArgs(uint64[32] memory _registers) function getSyscallArgs(uint64[32] memory _registers)
internal internal
pure pure
returns (uint64 sysCallNum_, uint64 a0_, uint64 a1_, uint64 a2_, uint64 a3_) returns (uint64 sysCallNum_, uint64 a0_, uint64 a1_, uint64 a2_)
{ {
unchecked { unchecked {
sysCallNum_ = _registers[REG_SYSCALL_NUM]; sysCallNum_ = _registers[REG_SYSCALL_NUM];
...@@ -192,9 +187,8 @@ library MIPS64Syscalls { ...@@ -192,9 +187,8 @@ library MIPS64Syscalls {
a0_ = _registers[REG_SYSCALL_PARAM1]; a0_ = _registers[REG_SYSCALL_PARAM1];
a1_ = _registers[REG_SYSCALL_PARAM2]; a1_ = _registers[REG_SYSCALL_PARAM2];
a2_ = _registers[REG_SYSCALL_PARAM3]; a2_ = _registers[REG_SYSCALL_PARAM3];
a3_ = _registers[REG_SYSCALL_PARAM4];
return (sysCallNum_, a0_, a1_, a2_, a3_); return (sysCallNum_, a0_, a1_, a2_);
} }
} }
......
...@@ -115,9 +115,6 @@ library MIPSSyscalls { ...@@ -115,9 +115,6 @@ library MIPSSyscalls {
uint32 internal constant FUTEX_WAIT_PRIVATE = 128; uint32 internal constant FUTEX_WAIT_PRIVATE = 128;
uint32 internal constant FUTEX_WAKE_PRIVATE = 129; uint32 internal constant FUTEX_WAKE_PRIVATE = 129;
uint32 internal constant FUTEX_TIMEOUT_STEPS = 10000;
uint64 internal constant FUTEX_NO_TIMEOUT = type(uint64).max;
uint32 internal constant FUTEX_EMPTY_ADDR = 0xFF_FF_FF_FF;
uint32 internal constant SCHED_QUANTUM = 100_000; uint32 internal constant SCHED_QUANTUM = 100_000;
uint32 internal constant HZ = 10_000_000; uint32 internal constant HZ = 10_000_000;
...@@ -165,7 +162,6 @@ library MIPSSyscalls { ...@@ -165,7 +162,6 @@ library MIPSSyscalls {
uint32 internal constant REG_SYSCALL_PARAM1 = REG_A0; uint32 internal constant REG_SYSCALL_PARAM1 = REG_A0;
uint32 internal constant REG_SYSCALL_PARAM2 = REG_A1; uint32 internal constant REG_SYSCALL_PARAM2 = REG_A1;
uint32 internal constant REG_SYSCALL_PARAM3 = REG_A2; uint32 internal constant REG_SYSCALL_PARAM3 = REG_A2;
uint32 internal constant REG_SYSCALL_PARAM4 = REG_A3;
/// @notice Extract syscall num and arguments from registers. /// @notice Extract syscall num and arguments from registers.
/// @param _registers The cpu registers. /// @param _registers The cpu registers.
...@@ -173,11 +169,10 @@ library MIPSSyscalls { ...@@ -173,11 +169,10 @@ library MIPSSyscalls {
/// @return a0_ The first argument available to the syscall operation. /// @return a0_ The first argument available to the syscall operation.
/// @return a1_ The second argument available to the syscall operation. /// @return a1_ The second argument available to the syscall operation.
/// @return a2_ The third argument available to the syscall operation. /// @return a2_ The third argument available to the syscall operation.
/// @return a3_ The fourth argument available to the syscall operation.
function getSyscallArgs(uint32[32] memory _registers) function getSyscallArgs(uint32[32] memory _registers)
internal internal
pure pure
returns (uint32 sysCallNum_, uint32 a0_, uint32 a1_, uint32 a2_, uint32 a3_) returns (uint32 sysCallNum_, uint32 a0_, uint32 a1_, uint32 a2_)
{ {
unchecked { unchecked {
sysCallNum_ = _registers[REG_SYSCALL_NUM]; sysCallNum_ = _registers[REG_SYSCALL_NUM];
...@@ -185,9 +180,8 @@ library MIPSSyscalls { ...@@ -185,9 +180,8 @@ library MIPSSyscalls {
a0_ = _registers[REG_SYSCALL_PARAM1]; a0_ = _registers[REG_SYSCALL_PARAM1];
a1_ = _registers[REG_SYSCALL_PARAM2]; a1_ = _registers[REG_SYSCALL_PARAM2];
a2_ = _registers[REG_SYSCALL_PARAM3]; a2_ = _registers[REG_SYSCALL_PARAM3];
a3_ = _registers[REG_SYSCALL_PARAM4];
return (sysCallNum_, a0_, a1_, a2_, a3_); return (sysCallNum_, a0_, a1_, a2_);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment