Skip to content

Commit

Permalink
Remove page size param (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
pantrif authored Dec 2, 2024
1 parent ba5eca1 commit a87254f
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 90 deletions.
71 changes: 29 additions & 42 deletions internal/polkavm/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,58 @@ import (

const (
AddressSpaceSize = 0x100000000 // 2^32
VmMinPageSize = 0x1000 // The minimum page size of the VM
VmMaxPageSize = 0x10000 // The maximum page size of the VM.
VMPageSize = uint32(1 << 12) // ZP: 4096 (2^12) The pvm memory page size.
VmAddressReturnToHost = 0xffff0000 // The address which, when jumped to, will return to the host.
VmAddressSpaceTop = AddressSpaceSize - VmMaxPageSize // The address at which the program's stackData starts inside of the VM.
VmAddressSpaceBottom = VmMaxPageSize // The bottom of the accessible address space inside the VM (ZQ?)
)

var (
ErrPageValueTooLarge = errors.New("page value too large")
ErrPageSizeNotPowerOfTwo = errors.New("page size is not a power of two")
ErrPageValueTooLarge = errors.New("page value too large")
)

func NewMemoryMap(pageSize, roDataSize, rwDataSize, stackSize, argsDataSize uint) (*MemoryMap, error) {
if pageSize < VmMinPageSize {
return nil, fmt.Errorf("invalid page size: page size is too small")
}

if pageSize > VmMaxPageSize {
return nil, fmt.Errorf("invalid page size: page size is too big")
}
roDataAddressSpace, err := AlignToNextPage(VmMaxPageSize, roDataSize)
func NewMemoryMap(roDataSize, rwDataSize, stackSize, argsDataSize uint32) (*MemoryMap, error) {
roDataAddressSpace, err := AlignToNextPage(roDataSize)
if err != nil {
return nil, fmt.Errorf("failed to instantiate memory map ro data address space: %w", err)
}

roDataSize, err = AlignToNextPage(pageSize, roDataSize)
roDataSize, err = AlignToNextPage(roDataSize)
if err != nil {
return nil, fmt.Errorf("failed to instantiate memory map ro data size: %w", err)
}

rwDataAddressSpace, err := AlignToNextPage(VmMaxPageSize, rwDataSize)
rwDataAddressSpace, err := AlignToNextPage(rwDataSize)
if err != nil {
return nil, fmt.Errorf("failed to instantiate memory map rw data address space: %w", err)
}

originalRwDataSize := rwDataSize
rwDataSize, err = AlignToNextPage(pageSize, rwDataSize)
rwDataSize, err = AlignToNextPage(rwDataSize)
if err != nil {
return nil, fmt.Errorf("failed to instantiate memory map rw data size: %w", err)
}

stackAddressSpace, err := AlignToNextPage(VmMaxPageSize, stackSize)
stackAddressSpace, err := AlignToNextPage(stackSize)
if err != nil {
return nil, fmt.Errorf("failed to instantiate memory map stackData address space: %w", err)
}

stackSize, err = AlignToNextPage(pageSize, stackSize)
stackSize, err = AlignToNextPage(stackSize)
if err != nil {
return nil, fmt.Errorf("failed to instantiate memory map stackData size: %w", err)
}
argsDataAddressSpace, err := AlignToNextPage(VmMaxPageSize, argsDataSize)
argsDataAddressSpace, err := AlignToNextPage(argsDataSize)
if err != nil {
return nil, fmt.Errorf("the size of the arguments data is too big %w", err)
}

argsDataSize, err = AlignToNextPage(pageSize, argsDataSize)
argsDataSize, err = AlignToNextPage(argsDataSize)
if err != nil {
return nil, fmt.Errorf("the size of the arguments data is too big %w", err)
}
var addressLow uint
var addressLow uint32
addressLow += VmAddressSpaceBottom
addressLow += roDataAddressSpace
addressLow += VmMaxPageSize
Expand All @@ -84,7 +76,7 @@ func NewMemoryMap(pageSize, roDataSize, rwDataSize, stackSize, argsDataSize uint
heapSlack := addressLow - heapBase
addressLow += VmMaxPageSize

var addressHigh uint = VmAddressSpaceTop
var addressHigh uint32 = VmAddressSpaceTop
addressHigh -= argsDataAddressSpace
argsDataAddress := addressHigh
addressHigh -= VmMaxPageSize
Expand All @@ -98,23 +90,21 @@ func NewMemoryMap(pageSize, roDataSize, rwDataSize, stackSize, argsDataSize uint
maxHeapSize := addressHigh - addressLow + heapSlack

return &MemoryMap{
PageSize: uint32(pageSize),
RODataSize: uint32(roDataSize),
RWDataAddress: uint32(rwDataAddress),
RWDataSize: uint32(rwDataSize),
StackAddressHigh: uint32(stackAddressHigh),
StackAddressLow: uint32(stackAddressHigh - stackSize),
StackSize: uint32(stackSize),
HeapBase: uint32(heapBase),
MaxHeapSize: uint32(maxHeapSize),
RODataSize: roDataSize,
RWDataAddress: rwDataAddress,
RWDataSize: rwDataSize,
StackAddressHigh: stackAddressHigh,
StackAddressLow: stackAddressHigh - stackSize,
StackSize: stackSize,
HeapBase: heapBase,
MaxHeapSize: maxHeapSize,
RODataAddress: VmMaxPageSize,
ArgsDataAddress: uint32(argsDataAddress),
ArgsDataSize: uint32(argsDataSize),
ArgsDataAddress: argsDataAddress,
ArgsDataSize: argsDataSize,
}, nil
}

type MemoryMap struct {
PageSize uint32
RODataSize uint32
RWDataSize uint32
StackSize uint32
Expand Down Expand Up @@ -146,16 +136,13 @@ func copySized(data []byte, size uint32) []byte {
return dst
}

func AlignToNextPage(pageSize uint, value uint) (uint, error) {
if !(pageSize != 0 && (pageSize&(pageSize-1)) == 0) {
return 0, ErrPageSizeNotPowerOfTwo
}
if value&(pageSize-1) == 0 {
func AlignToNextPage(value uint32) (uint32, error) {
if value&(VMPageSize-1) == 0 {
return value, nil
} else {
if value <= math.MaxUint-pageSize {
return (value + pageSize) & ^(pageSize - 1), nil
}
}
if value <= (math.MaxUint32 - VmMaxPageSize) {
return (value + VMPageSize) & ^(VMPageSize - 1), nil
}

return 0, ErrPageValueTooLarge
}
68 changes: 37 additions & 31 deletions internal/polkavm/abi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,30 @@ import (
func Test_memoryMap(t *testing.T) {
maxSize := uint32(AddressSpaceSize - uint64(VmMaxPageSize)*5)
tests := []struct {
expectError bool
pageSize, roDataSize, rwDataSize, stackSize uint32
expectError bool
roDataSize, rwDataSize, stackSize uint32
expectedRODataAddress, expectedRODataSize, expectedRWDataSize, expectedRWDataAddress,
expectedStackSize, expectedStackAddressHigh, expectedStackAddressLow, expectedHeapBase uint32
expectedMaxHeapSize uint64
}{{
pageSize: 0x4000, roDataSize: 1, rwDataSize: 1, stackSize: 1,
roDataSize: 1, rwDataSize: 1, stackSize: 1,
expectedRODataAddress: 0x10000,
expectedRODataSize: 0x4000,
expectedRWDataSize: 0x4000,
expectedStackSize: 0x4000,
expectedRWDataAddress: 0x30000,
expectedStackAddressHigh: 0xfffe0000,
expectedStackAddressLow: 0xfffdc000,
expectedHeapBase: 0x30001,
expectedMaxHeapSize: AddressSpaceSize - uint64(VmMaxPageSize)*4 - uint64(0x30001),
expectedRODataSize: 0x1000,
expectedRWDataSize: 0x1000,
expectedStackSize: 0x1000,
expectedRWDataAddress: VmAddressSpaceBottom + 0x1000 + VmMaxPageSize,
expectedStackAddressHigh: VmAddressSpaceTop - VmMaxPageSize,
expectedStackAddressLow: VmAddressSpaceTop - VmMaxPageSize - 0x1000,
expectedHeapBase: VmAddressSpaceBottom + 0x1000 + VmMaxPageSize + 1,
expectedMaxHeapSize: func() uint64 {
addressLow := VmAddressSpaceBottom + uint32(0x1000) + VmMaxPageSize + uint32(0x1000) + VmMaxPageSize
heapSlack := uint32(0x1000) - 1
addressHigh := VmAddressSpaceTop - VmMaxPageSize - uint32(0x1000)

return uint64(addressHigh - addressLow + heapSlack)
}(),
}, {
pageSize: 0x4000, roDataSize: maxSize, rwDataSize: 0, stackSize: 0,
roDataSize: maxSize, rwDataSize: 0, stackSize: 0,
expectedRODataAddress: 0x10000,
expectedRODataSize: maxSize,
expectedRWDataAddress: 0x10000 + VmMaxPageSize + maxSize,
Expand All @@ -38,16 +44,16 @@ func Test_memoryMap(t *testing.T) {
expectedHeapBase: 0x10000 + VmMaxPageSize + maxSize,
expectedMaxHeapSize: 0,
}, {
pageSize: 0x4000, roDataSize: maxSize + 1, rwDataSize: 0, stackSize: 0,
roDataSize: maxSize + 1, rwDataSize: 0, stackSize: 0,
expectError: true,
}, {
pageSize: 0x4000, roDataSize: maxSize, rwDataSize: 1, stackSize: 0,
roDataSize: maxSize, rwDataSize: 1, stackSize: 0,
expectError: true,
}, {
pageSize: 0x4000, roDataSize: maxSize, rwDataSize: 0, stackSize: 1,
roDataSize: maxSize, rwDataSize: 0, stackSize: 1,
expectError: true,
}, {
pageSize: 0x4000, roDataSize: 0, rwDataSize: maxSize, stackSize: 0,
roDataSize: 0, rwDataSize: maxSize, stackSize: 0,
expectedRODataAddress: VmMaxPageSize,
expectedRODataSize: 0,
expectedRWDataAddress: VmMaxPageSize * 2,
Expand All @@ -58,7 +64,7 @@ func Test_memoryMap(t *testing.T) {
expectedHeapBase: VmMaxPageSize*2 + maxSize,
expectedMaxHeapSize: 0,
}, {
pageSize: 0x4000, roDataSize: 0, rwDataSize: 0, stackSize: maxSize,
roDataSize: 0, rwDataSize: 0, stackSize: maxSize,
expectedRODataAddress: VmMaxPageSize,
expectedRODataSize: 0,
expectedRWDataAddress: VmMaxPageSize * 2,
Expand All @@ -71,7 +77,7 @@ func Test_memoryMap(t *testing.T) {
}}
for _, tc := range tests {
t.Run("", func(t *testing.T) {
m, err := NewMemoryMap(uint(tc.pageSize), uint(tc.roDataSize), uint(tc.rwDataSize), uint(tc.stackSize), 0)
m, err := NewMemoryMap(tc.roDataSize, tc.rwDataSize, tc.stackSize, 0)
if err != nil {
if tc.expectError {
return
Expand All @@ -91,19 +97,19 @@ func Test_memoryMap(t *testing.T) {
}

func Test_alignToNextPageUint32(t *testing.T) {
v, _ := AlignToNextPage(4096, 0)
assert.Equal(t, uint(0), v)
v, _ = AlignToNextPage(4096, 1)
assert.Equal(t, uint(4096), v)
v, _ = AlignToNextPage(4096, 4095)
assert.Equal(t, uint(4096), v)
v, _ = AlignToNextPage(4096, 4096)
assert.Equal(t, uint(4096), v)
v, _ = AlignToNextPage(4096, 4097)
assert.Equal(t, uint(8192), v)
var maxVal uint = math.MaxUint + 1 - 4096
v, _ = AlignToNextPage(4096, maxVal)
v, _ := AlignToNextPage(0)
assert.Equal(t, uint32(0), v)
v, _ = AlignToNextPage(1)
assert.Equal(t, uint32(4096), v)
v, _ = AlignToNextPage(4095)
assert.Equal(t, uint32(4096), v)
v, _ = AlignToNextPage(uint32(4096))
assert.Equal(t, uint32(4096), v)
v, _ = AlignToNextPage(4097)
assert.Equal(t, uint32(8192), v)
var maxVal uint32 = math.MaxUint32 + 1 - 4096
v, _ = AlignToNextPage(maxVal)
assert.Equal(t, maxVal, v)
_, err := AlignToNextPage(4096, maxVal+1)
_, err := AlignToNextPage(maxVal + 1)
assert.Error(t, err)
}
6 changes: 3 additions & 3 deletions internal/polkavm/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ func (m *Memory) inRange(address uint32) *memorySegment {
return nil
}

func (m *Memory) Sbrk(pageSize, heapTop uint32) error {
func (m *Memory) Sbrk(heapTop uint32) error {
if heapTop > m.data[2].end {
nextPage, err := AlignToNextPage(uint(pageSize), uint(heapTop))
nextPage, err := AlignToNextPage(heapTop)
if err != nil {
return err
}

m.data[2].end += uint32(nextPage)
m.data[2].end += nextPage
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion internal/polkavm/host_call/accumulate_functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ func TestAccumulate(t *testing.T) {
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
memoryMap, err := NewMemoryMap(VmMinPageSize, 0, 0, 1<<19, 0)
memoryMap, err := NewMemoryMap(0, 0, 1<<19, 0)
require.NoError(t, err)

mem := memoryMap.NewMemory(nil, nil, nil)
Expand Down
10 changes: 5 additions & 5 deletions internal/polkavm/host_call/general_functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestGasRemaining(t *testing.T) {
},
}

memoryMap, err := polkavm.NewMemoryMap(polkavm.VmMaxPageSize, 0, 0, 4096, 0)
memoryMap, err := polkavm.NewMemoryMap(0, 0, 4096, 0)
require.NoError(t, err)

mem := memoryMap.NewMemory(nil, nil, nil)
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestLookup(t *testing.T) {
Exports: []polkavm.ProgramExport{{TargetCodeOffset: 0, Symbol: "test_lookup"}},
}

memoryMap, err := polkavm.NewMemoryMap(polkavm.VmMinPageSize, 0, 256, 512, 0)
memoryMap, err := polkavm.NewMemoryMap(0, 256, 512, 0)
require.NoError(t, err)
t.Run("service_not_found", func(t *testing.T) {
initialRegs := polkavm.Registers{
Expand Down Expand Up @@ -137,7 +137,7 @@ func TestRead(t *testing.T) {
},
}

memoryMap, err := polkavm.NewMemoryMap(polkavm.VmMinPageSize, 0, 256, 512, 0)
memoryMap, err := polkavm.NewMemoryMap(0, 256, 512, 0)
require.NoError(t, err)

serviceId := block.ServiceId(1)
Expand Down Expand Up @@ -208,7 +208,7 @@ func TestWrite(t *testing.T) {
},
}

memoryMap, err := polkavm.NewMemoryMap(polkavm.VmMinPageSize, 0, 256, 512, 0)
memoryMap, err := polkavm.NewMemoryMap(0, 256, 512, 0)
require.NoError(t, err)

serviceId := block.ServiceId(1)
Expand Down Expand Up @@ -290,7 +290,7 @@ func TestInfo(t *testing.T) {
Exports: []polkavm.ProgramExport{{TargetCodeOffset: 0, Symbol: "test_info"}},
}

memoryMap, err := polkavm.NewMemoryMap(polkavm.VmMinPageSize, 0, 256, 512, 0)
memoryMap, err := polkavm.NewMemoryMap(0, 256, 512, 0)
require.NoError(t, err)

serviceId := block.ServiceId(1)
Expand Down
5 changes: 3 additions & 2 deletions internal/polkavm/interpreter/interpreter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"slices"
"testing"

"github.com/eigerco/strawberry/internal/polkavm"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/eigerco/strawberry/internal/polkavm"
)

func TestInstance_Execute(t *testing.T) {
Expand All @@ -30,7 +31,7 @@ func TestInstance_Execute(t *testing.T) {
Exports: []polkavm.ProgramExport{{TargetCodeOffset: 0, Symbol: "add_numbers"}},
}

memoryMap, err := polkavm.NewMemoryMap(0x1000, uint(pp.RODataSize), uint(pp.RWDataSize), uint(pp.StackSize), 0)
memoryMap, err := polkavm.NewMemoryMap(pp.RODataSize, pp.RWDataSize, pp.StackSize, 0)
require.NoError(t, err)

memory := memoryMap.NewMemory(pp.RWData, pp.ROData, nil)
Expand Down
6 changes: 3 additions & 3 deletions internal/polkavm/interpreter/mutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,17 @@ func (m *Mutator) Sbrk(dst polkavm.Reg, sizeReg polkavm.Reg) error {
}

newHeapSize := m.instance.heapSize + size
if newHeapSize > uint32(m.memoryMap.MaxHeapSize) {
if newHeapSize > m.memoryMap.MaxHeapSize {
return polkavm.ErrPanicf("max heap size exceeded")
}

m.instance.heapSize = newHeapSize
heapTop := m.memoryMap.HeapBase + newHeapSize
if err := m.instance.memory.Sbrk(m.memoryMap.PageSize, heapTop); err != nil {
if err := m.instance.memory.Sbrk(heapTop); err != nil {
return polkavm.ErrPanicf(err.Error())
}

m.setNext32(dst, uint32(heapTop))
m.setNext32(dst, heapTop)
return nil
}

Expand Down
5 changes: 3 additions & 2 deletions internal/polkavm/interpreter/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package interpreter
import (
"bytes"
"errors"
"github.com/eigerco/strawberry/internal/polkavm"
"slices"

"github.com/eigerco/strawberry/internal/polkavm"
)

// InvokeWholeProgram the marshalling whole-program pvm machine state-transition function: (ΨM)
Expand All @@ -19,7 +20,7 @@ func InvokeWholeProgram[X any](p []byte, entryPoint uint32, gas uint64, args []b
if err != nil {
return 0, nil, x, polkavm.ErrPanicf(err.Error())
}
memMap, err := polkavm.NewMemoryMap(polkavm.VmMinPageSize, uint(program.RODataSize), uint(program.RWDataSize), uint(program.StackSize), uint(len(args)))
memMap, err := polkavm.NewMemoryMap(program.RODataSize, program.RWDataSize, program.StackSize, uint32(len(args)))
if err != nil {
return 0, nil, x, polkavm.ErrPanicf(err.Error())
}
Expand Down
Loading

0 comments on commit a87254f

Please sign in to comment.