Skip to content

Commit

Permalink
refactor: PVM transition everything to bit 64 (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielvladco authored Feb 19, 2025
1 parent 3976be1 commit ccec214
Show file tree
Hide file tree
Showing 24 changed files with 535 additions and 721 deletions.
2 changes: 1 addition & 1 deletion internal/authorization/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (a *Authorization) InvokePVM(

// F ∈ Ω⟨{}⟩∶ (n, ϱ, ω, µ)
hostCall := func(
hostCall uint32,
hostCall uint64,
gasCounter polkavm.Gas,
regs polkavm.Registers,
mem polkavm.Memory,
Expand Down
262 changes: 138 additions & 124 deletions internal/polkavm/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,74 +27,88 @@ type Memory struct {
}

type memorySegment struct {
address uint32
address uint64
data []byte
access MemoryAccess
}

// Read reads from the set of readable indices (Vμ) (implements eq. A.8)
func (m *Memory) Read(address uint32, data []byte) error {
func (m *Memory) Read(address uint64, data []byte) error {
// ☇ if min(x) mod 2^32 < 2^16
if address < 1<<16 {
return ErrPanicf("forbidden memory access")
}
var memoryData []byte
access := Inaccessible
if address >= m.stack.address && address+uint32(len(data)) <= m.stack.address+uint32(len(m.stack.data)) {
memoryData = m.stack.data[address-m.stack.address : address-m.stack.address+uint32(len(data))]
if address >= m.stack.address && address+uint64(len(data)) <= m.stack.address+uint64(len(m.stack.data)) {
memoryData = m.stack.data[address-m.stack.address : address-m.stack.address+uint64(len(data))]
access = m.stack.access
} else if address >= m.rw.address && address+uint32(len(data)) <= m.rw.address+uint32(len(m.rw.data)) {
memoryData = m.rw.data[address-m.rw.address : address-m.rw.address+uint32(len(data))]
} else if address >= m.rw.address && address+uint64(len(data)) <= m.rw.address+uint64(len(m.rw.data)) {
memoryData = m.rw.data[address-m.rw.address : address-m.rw.address+uint64(len(data))]
access = m.rw.access
} else if address >= m.ro.address && address+uint32(len(data)) <= m.ro.address+uint32(len(m.ro.data)) {
memoryData = m.ro.data[address-m.ro.address : address-m.ro.address+uint32(len(data))]
} else if address >= m.ro.address && address+uint64(len(data)) <= m.ro.address+uint64(len(m.ro.data)) {
memoryData = m.ro.data[address-m.ro.address : address-m.ro.address+uint64(len(data))]
access = m.ro.access
} else if address >= m.args.address && address+uint32(len(data)) <= m.args.address+uint32(len(m.args.data)) {
memoryData = m.args.data[address-m.args.address : address-m.args.address+uint32(len(data))]
} else if address >= m.args.address && address+uint64(len(data)) <= m.args.address+uint64(len(m.args.data)) {
memoryData = m.args.data[address-m.args.address : address-m.args.address+uint64(len(data))]
access = m.args.access
}

// F × ZP ⌊ min(x) mod 2^32 ÷ ZP ⌋
if access == Inaccessible {
return &ErrPageFault{Reason: "inaccessible memory", Address: alignToPage(address)}
// find the minimum page that is not readable
for i := address / PageSize; i <= (address+uint64(len(data)))/PageSize; i++ {
access := m.GetAccess(i)
if access == Inaccessible {
return &ErrPageFault{Reason: "inaccessible memory", Address: i * PageSize}
}
}
return ErrPanicf("inaccessible memory; unable to find the bad memory page")
}
copy(data, memoryData)
return nil
}

// Write writes to the set of writeable indices (Vμ*) (implements eq. A.8)
func (m *Memory) Write(address uint32, data []byte) error {
func (m *Memory) Write(address uint64, data []byte) error {
// ☇ if min(x) mod 2^32 < 2^16
if address < 1<<16 {
return ErrPanicf("forbidden memory access")
}

var memoryData []byte
access := Inaccessible
if address >= m.stack.address && address+uint32(len(data)) <= m.stack.address+uint32(len(m.stack.data)) {
memoryData = m.stack.data[address-m.stack.address : address-m.stack.address+uint32(len(data))]
if address >= m.stack.address && address+uint64(len(data)) <= m.stack.address+uint64(len(m.stack.data)) {
memoryData = m.stack.data[address-m.stack.address : address-m.stack.address+uint64(len(data))]
access = m.stack.access
} else if address >= m.rw.address && address+uint32(len(data)) <= m.rw.address+uint32(len(m.rw.data)) {
memoryData = m.rw.data[address-m.rw.address : address-m.rw.address+uint32(len(data))]
} else if address >= m.rw.address && address+uint64(len(data)) <= m.rw.address+uint64(len(m.rw.data)) {
memoryData = m.rw.data[address-m.rw.address : address-m.rw.address+uint64(len(data))]
access = m.rw.access
} else if address >= m.ro.address && address+uint32(len(data)) <= m.ro.address+uint32(len(m.ro.data)) {
memoryData = m.ro.data[address-m.ro.address : address-m.ro.address+uint32(len(data))]
} else if address >= m.ro.address && address+uint64(len(data)) <= m.ro.address+uint64(len(m.ro.data)) {
memoryData = m.ro.data[address-m.ro.address : address-m.ro.address+uint64(len(data))]
access = m.ro.access
} else if address >= m.args.address && address+uint32(len(data)) <= m.args.address+uint32(len(m.args.data)) {
memoryData = m.args.data[address-m.args.address : address-m.args.address+uint32(len(data))]
} else if address >= m.args.address && address+uint64(len(data)) <= m.args.address+uint64(len(m.args.data)) {
memoryData = m.args.data[address-m.args.address : address-m.args.address+uint64(len(data))]
access = m.args.access
}

// F × ZP ⌊ min(x) mod 2^32 ÷ ZP ⌋
if access != ReadWrite {
return &ErrPageFault{Reason: "memory at address is not writeable", Address: alignToPage(address)}
// find the minimum page that is not writeable
for i := address / PageSize; i <= (address+uint64(len(data)))/PageSize; i++ {
access := m.GetAccess(i)
if access != ReadWrite { // return min(page) where the issue was found
return &ErrPageFault{Reason: "memory at address is not writeable", Address: i * PageSize}
}
}
return ErrPanicf("inaccessible memory; unable to find the bad memory page")
}
copy(memoryData, data)
return nil
}

func (m *Memory) Sbrk(size uint32) (uint32, error) {
currentHeapPointer := m.rw.address + uint32(len(m.rw.data)) // h
func (m *Memory) Sbrk(size uint64) (uint64, error) {
currentHeapPointer := m.rw.address + uint64(len(m.rw.data)) // h
if size == 0 {
return currentHeapPointer, nil
}
Expand All @@ -108,40 +122,40 @@ func (m *Memory) Sbrk(size uint32) (uint32, error) {
m.rw.data = make([]byte, alignToPage(newHeapPointer))
}

return m.rw.address + uint32(len(m.rw.data)), nil
return m.rw.address + uint64(len(m.rw.data)), nil
}

// SetAccess updates the access mode
func (m *Memory) SetAccess(pageIndex uint32, access MemoryAccess) error {
func (m *Memory) SetAccess(pageIndex uint64, access MemoryAccess) error {
address := pageIndex * PageSize

if address >= m.stack.address && address <= m.stack.address+uint32(len(m.stack.data)) {
if address >= m.stack.address && address < m.stack.address+uint64(len(m.stack.data)) {
m.stack.access = access
return nil
} else if address >= m.rw.address && address <= m.rw.address+uint32(len(m.rw.data)) {
} else if address >= m.rw.address && address < m.rw.address+uint64(len(m.rw.data)) {
m.rw.access = access
return nil
} else if address >= m.ro.address && address <= m.ro.address+uint32(len(m.ro.data)) {
} else if address >= m.ro.address && address < m.ro.address+uint64(len(m.ro.data)) {
m.ro.access = access
return nil
} else if address >= m.args.address && address <= m.args.address+uint32(len(m.args.data)) {
} else if address >= m.args.address && address < m.args.address+uint64(len(m.args.data)) {
m.args.access = access
return nil
}

return &ErrPageFault{Reason: "page out of valid range", Address: address}
}

func (m *Memory) GetAccess(pageIndex uint32) MemoryAccess {
func (m *Memory) GetAccess(pageIndex uint64) MemoryAccess {
address := pageIndex * PageSize

if address >= m.stack.address && address <= m.stack.address+uint32(len(m.stack.data)) {
if address >= m.stack.address && address < m.stack.address+uint64(len(m.stack.data)) {
return m.stack.access
} else if address >= m.rw.address && address <= m.rw.address+uint32(len(m.rw.data)) {
} else if address >= m.rw.address && address < m.rw.address+uint64(len(m.rw.data)) {
return m.rw.access
} else if address >= m.ro.address && address <= m.ro.address+uint32(len(m.ro.data)) {
} else if address >= m.ro.address && address < m.ro.address+uint64(len(m.ro.data)) {
return m.ro.access
} else if address >= m.args.address && address <= m.args.address+uint32(len(m.args.data)) {
} else if address >= m.args.address && address < m.args.address+uint64(len(m.args.data)) {
return m.args.access
}

Expand All @@ -153,51 +167,51 @@ type Registers [13]uint64
type Gas int64

// HostCall the generic Ω function definition Ωx(n, ϱ, ω, μ, x) defined in section A.6
type HostCall[X any] func(hostCall uint32, gasCounter Gas, regs Registers, mem Memory, x X) (Gas, Registers, Memory, X, error)
type HostCall[X any] func(hostCall uint64, gasCounter Gas, regs Registers, mem Memory, x X) (Gas, Registers, Memory, X, error)

type Mutator interface {
Trap() error
Fallthrough()

LoadImm64(Reg, uint64)

StoreImmU8(uint32, uint32) error
StoreImmU16(uint32, uint32) error
StoreImmU32(uint32, uint32) error
StoreImmU64(uint32, uint32) error

Jump(uint32) error

JumpIndirect(Reg, uint32) error
LoadImm(Reg, uint32)
LoadU8(Reg, uint32) error
LoadI8(Reg, uint32) error
LoadU16(Reg, uint32) error
LoadI16(Reg, uint32) error
LoadU32(Reg, uint32) error
LoadI32(Reg, uint32) error
LoadU64(Reg, uint32) error
StoreU8(Reg, uint32) error
StoreU16(Reg, uint32) error
StoreU32(Reg, uint32) error
StoreU64(Reg, uint32) error

StoreImmIndirectU8(Reg, uint32, uint32) error
StoreImmIndirectU16(Reg, uint32, uint32) error
StoreImmIndirectU32(Reg, uint32, uint32) error
StoreImmIndirectU64(Reg, uint32, uint32) error

LoadImmAndJump(Reg, uint32, uint32) error
BranchEqImm(Reg, uint32, uint32) error
BranchNotEqImm(Reg, uint32, uint32) error
BranchLessUnsignedImm(Reg, uint32, uint32) error
BranchLessOrEqualUnsignedImm(Reg, uint32, uint32) error
BranchGreaterOrEqualUnsignedImm(Reg, uint32, uint32) error
BranchGreaterUnsignedImm(Reg, uint32, uint32) error
BranchLessSignedImm(Reg, uint32, uint32) error
BranchLessOrEqualSignedImm(Reg, uint32, uint32) error
BranchGreaterOrEqualSignedImm(Reg, uint32, uint32) error
BranchGreaterSignedImm(Reg, uint32, uint32) error
StoreImmU8(uint64, uint64) error
StoreImmU16(uint64, uint64) error
StoreImmU32(uint64, uint64) error
StoreImmU64(uint64, uint64) error

Jump(uint64) error

JumpIndirect(Reg, uint64) error
LoadImm(Reg, uint64)
LoadU8(Reg, uint64) error
LoadI8(Reg, uint64) error
LoadU16(Reg, uint64) error
LoadI16(Reg, uint64) error
LoadU32(Reg, uint64) error
LoadI32(Reg, uint64) error
LoadU64(Reg, uint64) error
StoreU8(Reg, uint64) error
StoreU16(Reg, uint64) error
StoreU32(Reg, uint64) error
StoreU64(Reg, uint64) error

StoreImmIndirectU8(Reg, uint64, uint64) error
StoreImmIndirectU16(Reg, uint64, uint64) error
StoreImmIndirectU32(Reg, uint64, uint64) error
StoreImmIndirectU64(Reg, uint64, uint64) error

LoadImmAndJump(Reg, uint64, uint64) error
BranchEqImm(Reg, uint64, uint64) error
BranchNotEqImm(Reg, uint64, uint64) error
BranchLessUnsignedImm(Reg, uint64, uint64) error
BranchLessOrEqualUnsignedImm(Reg, uint64, uint64) error
BranchGreaterOrEqualUnsignedImm(Reg, uint64, uint64) error
BranchGreaterUnsignedImm(Reg, uint64, uint64) error
BranchLessSignedImm(Reg, uint64, uint64) error
BranchLessOrEqualSignedImm(Reg, uint64, uint64) error
BranchGreaterOrEqualSignedImm(Reg, uint64, uint64) error
BranchGreaterSignedImm(Reg, uint64, uint64) error

MoveReg(Reg, Reg)
Sbrk(Reg, Reg) error
Expand All @@ -212,57 +226,57 @@ type Mutator interface {
ZeroExtend16(Reg, Reg)
ReverseBytes(Reg, Reg)

StoreIndirectU8(Reg, Reg, uint32) error
StoreIndirectU16(Reg, Reg, uint32) error
StoreIndirectU32(Reg, Reg, uint32) error
StoreIndirectU64(Reg, Reg, uint32) error
LoadIndirectU8(Reg, Reg, uint32) error
LoadIndirectI8(Reg, Reg, uint32) error
LoadIndirectU16(Reg, Reg, uint32) error
LoadIndirectI16(Reg, Reg, uint32) error
LoadIndirectU32(Reg, Reg, uint32) error
LoadIndirectI32(Reg, Reg, uint32) error
LoadIndirectU64(Reg, Reg, uint32) error
AddImm32(Reg, Reg, uint32)
AndImm(Reg, Reg, uint32)
XorImm(Reg, Reg, uint32)
OrImm(Reg, Reg, uint32)
MulImm32(Reg, Reg, uint32)
SetLessThanUnsignedImm(Reg, Reg, uint32)
SetLessThanSignedImm(Reg, Reg, uint32)
ShiftLogicalLeftImm32(Reg, Reg, uint32)
ShiftLogicalRightImm32(Reg, Reg, uint32)
ShiftArithmeticRightImm32(Reg, Reg, uint32)
NegateAndAddImm32(Reg, Reg, uint32)
SetGreaterThanUnsignedImm(Reg, Reg, uint32)
SetGreaterThanSignedImm(Reg, Reg, uint32)
ShiftLogicalLeftImmAlt32(Reg, Reg, uint32)
ShiftLogicalRightImmAlt32(Reg, Reg, uint32)
ShiftArithmeticRightImmAlt32(Reg, Reg, uint32)
CmovIfZeroImm(Reg, Reg, uint32)
CmovIfNotZeroImm(Reg, Reg, uint32)
AddImm64(Reg, Reg, uint32)
MulImm64(Reg, Reg, uint32)
ShiftLogicalLeftImm64(Reg, Reg, uint32)
ShiftLogicalRightImm64(Reg, Reg, uint32)
ShiftArithmeticRightImm64(Reg, Reg, uint32)
NegateAndAddImm64(Reg, Reg, uint32)
ShiftLogicalLeftImmAlt64(Reg, Reg, uint32)
ShiftLogicalRightImmAlt64(Reg, Reg, uint32)
ShiftArithmeticRightImmAlt64(Reg, Reg, uint32)
RotateRight64Imm(Reg, Reg, uint32)
RotateRight64ImmAlt(Reg, Reg, uint32)
RotateRight32Imm(Reg, Reg, uint32)
RotateRight32ImmAlt(Reg, Reg, uint32)

BranchEq(Reg, Reg, uint32) error
BranchNotEq(Reg, Reg, uint32) error
BranchLessUnsigned(Reg, Reg, uint32) error
BranchLessSigned(Reg, Reg, uint32) error
BranchGreaterOrEqualUnsigned(Reg, Reg, uint32) error
BranchGreaterOrEqualSigned(Reg, Reg, uint32) error

LoadImmAndJumpIndirect(Reg, Reg, uint32, uint32) error
StoreIndirectU8(Reg, Reg, uint64) error
StoreIndirectU16(Reg, Reg, uint64) error
StoreIndirectU32(Reg, Reg, uint64) error
StoreIndirectU64(Reg, Reg, uint64) error
LoadIndirectU8(Reg, Reg, uint64) error
LoadIndirectI8(Reg, Reg, uint64) error
LoadIndirectU16(Reg, Reg, uint64) error
LoadIndirectI16(Reg, Reg, uint64) error
LoadIndirectU32(Reg, Reg, uint64) error
LoadIndirectI32(Reg, Reg, uint64) error
LoadIndirectU64(Reg, Reg, uint64) error
AddImm32(Reg, Reg, uint64)
AndImm(Reg, Reg, uint64)
XorImm(Reg, Reg, uint64)
OrImm(Reg, Reg, uint64)
MulImm32(Reg, Reg, uint64)
SetLessThanUnsignedImm(Reg, Reg, uint64)
SetLessThanSignedImm(Reg, Reg, uint64)
ShiftLogicalLeftImm32(Reg, Reg, uint64)
ShiftLogicalRightImm32(Reg, Reg, uint64)
ShiftArithmeticRightImm32(Reg, Reg, uint64)
NegateAndAddImm32(Reg, Reg, uint64)
SetGreaterThanUnsignedImm(Reg, Reg, uint64)
SetGreaterThanSignedImm(Reg, Reg, uint64)
ShiftLogicalLeftImmAlt32(Reg, Reg, uint64)
ShiftLogicalRightImmAlt32(Reg, Reg, uint64)
ShiftArithmeticRightImmAlt32(Reg, Reg, uint64)
CmovIfZeroImm(Reg, Reg, uint64)
CmovIfNotZeroImm(Reg, Reg, uint64)
AddImm64(Reg, Reg, uint64)
MulImm64(Reg, Reg, uint64)
ShiftLogicalLeftImm64(Reg, Reg, uint64)
ShiftLogicalRightImm64(Reg, Reg, uint64)
ShiftArithmeticRightImm64(Reg, Reg, uint64)
NegateAndAddImm64(Reg, Reg, uint64)
ShiftLogicalLeftImmAlt64(Reg, Reg, uint64)
ShiftLogicalRightImmAlt64(Reg, Reg, uint64)
ShiftArithmeticRightImmAlt64(Reg, Reg, uint64)
RotateRight64Imm(Reg, Reg, uint64)
RotateRight64ImmAlt(Reg, Reg, uint64)
RotateRight32Imm(Reg, Reg, uint64)
RotateRight32ImmAlt(Reg, Reg, uint64)

BranchEq(Reg, Reg, uint64) error
BranchNotEq(Reg, Reg, uint64) error
BranchLessUnsigned(Reg, Reg, uint64) error
BranchLessSigned(Reg, Reg, uint64) error
BranchGreaterOrEqualUnsigned(Reg, Reg, uint64) error
BranchGreaterOrEqualSigned(Reg, Reg, uint64) error

LoadImmAndJumpIndirect(Reg, Reg, uint64, uint64) error

Add32(Reg, Reg, Reg)
Sub32(Reg, Reg, Reg)
Expand Down Expand Up @@ -329,7 +343,7 @@ type AccumulateContextPair struct {
type IntegratedPVM struct {
Code []byte //p program code
Ram Memory //u RAM
InstructionCounter uint32 //i instruction counter
InstructionCounter uint64 //i instruction counter
}

type RefineContextPair struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/polkavm/exit_reason.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var ErrOutOfGas = fmt.Errorf("out of gas")
// ErrPageFault a page fault (attempt to data some address in RAM which is not accessible). This includes the address at fault. (F)
type ErrPageFault struct {
Reason string
Address uint32
Address uint64
}

func (e *ErrPageFault) Error() string {
Expand Down
Loading

0 comments on commit ccec214

Please sign in to comment.