summaryrefslogtreecommitdiffhomepage
path: root/pkg/usermem
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/usermem')
-rw-r--r--pkg/usermem/access_type.go126
-rw-r--r--pkg/usermem/addr.go125
-rw-r--r--pkg/usermem/addr_range.go76
-rw-r--r--pkg/usermem/addr_range_seq_unsafe.go280
-rw-r--r--pkg/usermem/bytes_io.go21
-rw-r--r--pkg/usermem/bytes_io_unsafe.go7
-rw-r--r--pkg/usermem/usermem.go52
-rw-r--r--pkg/usermem/usermem_arm64.go54
-rw-r--r--pkg/usermem/usermem_arm64_state_autogen.go5
-rw-r--r--pkg/usermem/usermem_state_autogen.go77
-rw-r--r--pkg/usermem/usermem_x86.go38
-rw-r--r--pkg/usermem/usermem_x86_state_autogen.go5
12 files changed, 42 insertions, 824 deletions
diff --git a/pkg/usermem/access_type.go b/pkg/usermem/access_type.go
deleted file mode 100644
index 2cfca29af..000000000
--- a/pkg/usermem/access_type.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package usermem
-
-import "golang.org/x/sys/unix"
-
-// AccessType specifies memory access types. This is used for
-// setting mapping permissions, as well as communicating faults.
-//
-// +stateify savable
-type AccessType struct {
- // Read is read access.
- Read bool
-
- // Write is write access.
- Write bool
-
- // Execute is executable access.
- Execute bool
-}
-
-// String returns a pretty representation of access. This looks like the
-// familiar r-x, rw-, etc. and can be relied on as such.
-func (a AccessType) String() string {
- bits := [3]byte{'-', '-', '-'}
- if a.Read {
- bits[0] = 'r'
- }
- if a.Write {
- bits[1] = 'w'
- }
- if a.Execute {
- bits[2] = 'x'
- }
- return string(bits[:])
-}
-
-// Any returns true iff at least one of Read, Write or Execute is true.
-func (a AccessType) Any() bool {
- return a.Read || a.Write || a.Execute
-}
-
-// Prot returns the system prot (unix.PROT_READ, etc.) for this access.
-func (a AccessType) Prot() int {
- var prot int
- if a.Read {
- prot |= unix.PROT_READ
- }
- if a.Write {
- prot |= unix.PROT_WRITE
- }
- if a.Execute {
- prot |= unix.PROT_EXEC
- }
- return prot
-}
-
-// SupersetOf returns true iff the access types in a are a superset of the
-// access types in other.
-func (a AccessType) SupersetOf(other AccessType) bool {
- if !a.Read && other.Read {
- return false
- }
- if !a.Write && other.Write {
- return false
- }
- if !a.Execute && other.Execute {
- return false
- }
- return true
-}
-
-// Intersect returns the access types set in both a and other.
-func (a AccessType) Intersect(other AccessType) AccessType {
- return AccessType{
- Read: a.Read && other.Read,
- Write: a.Write && other.Write,
- Execute: a.Execute && other.Execute,
- }
-}
-
-// Union returns the access types set in either a or other.
-func (a AccessType) Union(other AccessType) AccessType {
- return AccessType{
- Read: a.Read || other.Read,
- Write: a.Write || other.Write,
- Execute: a.Execute || other.Execute,
- }
-}
-
-// Effective returns the set of effective access types allowed by a, even if
-// some types are not explicitly allowed.
-func (a AccessType) Effective() AccessType {
- // In Linux, Write and Execute access generally imply Read access. See
- // mm/mmap.c:protection_map.
- //
- // The notable exception is get_user_pages, which only checks against
- // the original vma flags. That said, most user memory accesses do not
- // use GUP.
- if a.Write || a.Execute {
- a.Read = true
- }
- return a
-}
-
-// Convenient access types.
-var (
- NoAccess = AccessType{}
- Read = AccessType{Read: true}
- Write = AccessType{Write: true}
- Execute = AccessType{Execute: true}
- ReadWrite = AccessType{Read: true, Write: true}
- AnyAccess = AccessType{Read: true, Write: true, Execute: true}
-)
diff --git a/pkg/usermem/addr.go b/pkg/usermem/addr.go
deleted file mode 100644
index c4100481e..000000000
--- a/pkg/usermem/addr.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package usermem
-
-import (
- "fmt"
-)
-
-// Addr represents a generic virtual address.
-//
-// +stateify savable
-type Addr uintptr
-
-// AddLength adds the given length to start and returns the result. ok is true
-// iff adding the length did not overflow the range of Addr.
-//
-// Note: This function is usually used to get the end of an address range
-// defined by its start address and length. Since the resulting end is
-// exclusive, end == 0 is technically valid, and corresponds to a range that
-// extends to the end of the address space, but ok will be false. This isn't
-// expected to ever come up in practice.
-func (v Addr) AddLength(length uint64) (end Addr, ok bool) {
- end = v + Addr(length)
- // The second half of the following check is needed in case uintptr is
- // smaller than 64 bits.
- ok = end >= v && length <= uint64(^Addr(0))
- return
-}
-
-// RoundDown returns the address rounded down to the nearest page boundary.
-func (v Addr) RoundDown() Addr {
- return v & ^Addr(PageSize-1)
-}
-
-// RoundUp returns the address rounded up to the nearest page boundary. ok is
-// true iff rounding up did not wrap around.
-func (v Addr) RoundUp() (addr Addr, ok bool) {
- addr = Addr(v + PageSize - 1).RoundDown()
- ok = addr >= v
- return
-}
-
-// MustRoundUp is equivalent to RoundUp, but panics if rounding up wraps
-// around.
-func (v Addr) MustRoundUp() Addr {
- addr, ok := v.RoundUp()
- if !ok {
- panic(fmt.Sprintf("usermem.Addr(%d).RoundUp() wraps", v))
- }
- return addr
-}
-
-// HugeRoundDown returns the address rounded down to the nearest huge page
-// boundary.
-func (v Addr) HugeRoundDown() Addr {
- return v & ^Addr(HugePageSize-1)
-}
-
-// HugeRoundUp returns the address rounded up to the nearest huge page boundary.
-// ok is true iff rounding up did not wrap around.
-func (v Addr) HugeRoundUp() (addr Addr, ok bool) {
- addr = Addr(v + HugePageSize - 1).HugeRoundDown()
- ok = addr >= v
- return
-}
-
-// PageOffset returns the offset of v into the current page.
-func (v Addr) PageOffset() uint64 {
- return uint64(v & Addr(PageSize-1))
-}
-
-// IsPageAligned returns true if v.PageOffset() == 0.
-func (v Addr) IsPageAligned() bool {
- return v.PageOffset() == 0
-}
-
-// AddrRange is a range of Addrs.
-//
-// type AddrRange <generated by go_generics>
-
-// ToRange returns [v, v+length).
-func (v Addr) ToRange(length uint64) (AddrRange, bool) {
- end, ok := v.AddLength(length)
- return AddrRange{v, end}, ok
-}
-
-// IsPageAligned returns true if ar.Start.IsPageAligned() and
-// ar.End.IsPageAligned().
-func (ar AddrRange) IsPageAligned() bool {
- return ar.Start.IsPageAligned() && ar.End.IsPageAligned()
-}
-
-// String implements fmt.Stringer.String.
-func (ar AddrRange) String() string {
- return fmt.Sprintf("[%#x, %#x)", ar.Start, ar.End)
-}
-
-// PageRoundDown/Up are equivalent to Addr.RoundDown/Up, but without the
-// potentially truncating conversion from uint64 to Addr. This is necessary
-// because there is no way to define generic "PageRoundDown/Up" functions in Go.
-
-// PageRoundDown returns x rounded down to the nearest page boundary.
-func PageRoundDown(x uint64) uint64 {
- return x &^ (PageSize - 1)
-}
-
-// PageRoundUp returns x rounded up to the nearest page boundary.
-// ok is true iff rounding up did not wrap around.
-func PageRoundUp(x uint64) (addr uint64, ok bool) {
- addr = PageRoundDown(x + PageSize - 1)
- ok = addr >= x
- return
-}
diff --git a/pkg/usermem/addr_range.go b/pkg/usermem/addr_range.go
deleted file mode 100644
index 6e030127b..000000000
--- a/pkg/usermem/addr_range.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package usermem
-
-// A Range represents a contiguous range of T.
-//
-// +stateify savable
-type AddrRange struct {
- // Start is the inclusive start of the range.
- Start Addr
-
- // End is the exclusive end of the range.
- End Addr
-}
-
-// WellFormed returns true if r.Start <= r.End. All other methods on a Range
-// require that the Range is well-formed.
-//
-//go:nosplit
-func (r AddrRange) WellFormed() bool {
- return r.Start <= r.End
-}
-
-// Length returns the length of the range.
-//
-//go:nosplit
-func (r AddrRange) Length() Addr {
- return r.End - r.Start
-}
-
-// Contains returns true if r contains x.
-//
-//go:nosplit
-func (r AddrRange) Contains(x Addr) bool {
- return r.Start <= x && x < r.End
-}
-
-// Overlaps returns true if r and r2 overlap.
-//
-//go:nosplit
-func (r AddrRange) Overlaps(r2 AddrRange) bool {
- return r.Start < r2.End && r2.Start < r.End
-}
-
-// IsSupersetOf returns true if r is a superset of r2; that is, the range r2 is
-// contained within r.
-//
-//go:nosplit
-func (r AddrRange) IsSupersetOf(r2 AddrRange) bool {
- return r.Start <= r2.Start && r.End >= r2.End
-}
-
-// Intersect returns a range consisting of the intersection between r and r2.
-// If r and r2 do not overlap, Intersect returns a range with unspecified
-// bounds, but for which Length() == 0.
-//
-//go:nosplit
-func (r AddrRange) Intersect(r2 AddrRange) AddrRange {
- if r.Start < r2.Start {
- r.Start = r2.Start
- }
- if r.End > r2.End {
- r.End = r2.End
- }
- if r.End < r.Start {
- r.End = r.Start
- }
- return r
-}
-
-// CanSplitAt returns true if it is legal to split a segment spanning the range
-// r at x; that is, splitting at x would produce two ranges, both of which have
-// non-zero length.
-//
-//go:nosplit
-func (r AddrRange) CanSplitAt(x Addr) bool {
- return r.Contains(x) && r.Start < x
-}
diff --git a/pkg/usermem/addr_range_seq_unsafe.go b/pkg/usermem/addr_range_seq_unsafe.go
deleted file mode 100644
index c9a1415a0..000000000
--- a/pkg/usermem/addr_range_seq_unsafe.go
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package usermem
-
-import (
- "bytes"
- "fmt"
- "unsafe"
-
- "gvisor.dev/gvisor/pkg/gohacks"
-)
-
-// An AddrRangeSeq represents a sequence of AddrRanges.
-//
-// AddrRangeSeqs are immutable and may be copied by value. The zero value of
-// AddrRangeSeq represents an empty sequence.
-//
-// An AddrRangeSeq may contain AddrRanges with a length of 0. This is necessary
-// since zero-length AddrRanges are significant to MM bounds checks.
-type AddrRangeSeq struct {
- // If length is 0, then the AddrRangeSeq represents no AddrRanges.
- // Invariants: data == 0; offset == 0; limit == 0.
- //
- // If length is 1, then the AddrRangeSeq represents the single
- // AddrRange{offset, offset+limit}. Invariants: data == 0.
- //
- // Otherwise, length >= 2, and the AddrRangeSeq represents the `length`
- // AddrRanges in the array of AddrRanges starting at address `data`,
- // starting at `offset` bytes into the first AddrRange and limited to the
- // following `limit` bytes. (AddrRanges after `limit` are still iterated,
- // but are truncated to a length of 0.) Invariants: data != 0; offset <=
- // data[0].Length(); limit > 0; offset+limit <= the combined length of all
- // AddrRanges in the array.
- data unsafe.Pointer
- length int
- offset Addr
- limit Addr
-}
-
-// AddrRangeSeqOf returns an AddrRangeSeq representing the single AddrRange ar.
-func AddrRangeSeqOf(ar AddrRange) AddrRangeSeq {
- return AddrRangeSeq{
- length: 1,
- offset: ar.Start,
- limit: ar.Length(),
- }
-}
-
-// AddrRangeSeqFromSlice returns an AddrRangeSeq representing all AddrRanges in
-// slice.
-//
-// Whether the returned AddrRangeSeq shares memory with slice is unspecified;
-// clients should avoid mutating slices passed to AddrRangeSeqFromSlice.
-//
-// Preconditions: The combined length of all AddrRanges in slice <=
-// math.MaxInt64.
-func AddrRangeSeqFromSlice(slice []AddrRange) AddrRangeSeq {
- var limit int64
- for _, ar := range slice {
- len64 := int64(ar.Length())
- if len64 < 0 {
- panic(fmt.Sprintf("Length of AddrRange %v overflows int64", ar))
- }
- sum := limit + len64
- if sum < limit {
- panic(fmt.Sprintf("Total length of AddrRanges %v overflows int64", slice))
- }
- limit = sum
- }
- return addrRangeSeqFromSliceLimited(slice, limit)
-}
-
-// Preconditions:
-// * The combined length of all AddrRanges in slice <= limit.
-// * limit >= 0.
-// * If len(slice) != 0, then limit > 0.
-func addrRangeSeqFromSliceLimited(slice []AddrRange, limit int64) AddrRangeSeq {
- switch len(slice) {
- case 0:
- return AddrRangeSeq{}
- case 1:
- return AddrRangeSeq{
- length: 1,
- offset: slice[0].Start,
- limit: Addr(limit),
- }
- default:
- return AddrRangeSeq{
- data: unsafe.Pointer(&slice[0]),
- length: len(slice),
- limit: Addr(limit),
- }
- }
-}
-
-// IsEmpty returns true if ars.NumRanges() == 0.
-//
-// Note that since AddrRangeSeq may contain AddrRanges with a length of zero,
-// an AddrRange representing 0 bytes (AddrRangeSeq.NumBytes() == 0) is not
-// necessarily empty.
-func (ars AddrRangeSeq) IsEmpty() bool {
- return ars.length == 0
-}
-
-// NumRanges returns the number of AddrRanges in ars.
-func (ars AddrRangeSeq) NumRanges() int {
- return ars.length
-}
-
-// NumBytes returns the number of bytes represented by ars.
-func (ars AddrRangeSeq) NumBytes() int64 {
- return int64(ars.limit)
-}
-
-// Head returns the first AddrRange in ars.
-//
-// Preconditions: !ars.IsEmpty().
-func (ars AddrRangeSeq) Head() AddrRange {
- if ars.length == 0 {
- panic("empty AddrRangeSeq")
- }
- if ars.length == 1 {
- return AddrRange{ars.offset, ars.offset + ars.limit}
- }
- ar := *(*AddrRange)(ars.data)
- ar.Start += ars.offset
- if ar.Length() > ars.limit {
- ar.End = ar.Start + ars.limit
- }
- return ar
-}
-
-// Tail returns an AddrRangeSeq consisting of all AddrRanges in ars after the
-// first.
-//
-// Preconditions: !ars.IsEmpty().
-func (ars AddrRangeSeq) Tail() AddrRangeSeq {
- if ars.length == 0 {
- panic("empty AddrRangeSeq")
- }
- if ars.length == 1 {
- return AddrRangeSeq{}
- }
- return ars.externalTail()
-}
-
-// Preconditions: ars.length >= 2.
-func (ars AddrRangeSeq) externalTail() AddrRangeSeq {
- headLen := (*AddrRange)(ars.data).Length() - ars.offset
- var tailLimit int64
- if ars.limit > headLen {
- tailLimit = int64(ars.limit - headLen)
- }
- var extSlice []AddrRange
- extSliceHdr := (*gohacks.SliceHeader)(unsafe.Pointer(&extSlice))
- extSliceHdr.Data = ars.data
- extSliceHdr.Len = ars.length
- extSliceHdr.Cap = ars.length
- return addrRangeSeqFromSliceLimited(extSlice[1:], tailLimit)
-}
-
-// DropFirst returns an AddrRangeSeq equivalent to ars, but with the first n
-// bytes omitted. If n > ars.NumBytes(), DropFirst returns an empty
-// AddrRangeSeq.
-//
-// If !ars.IsEmpty() and ars.Head().Length() == 0, DropFirst will always omit
-// at least ars.Head(), even if n == 0. This guarantees that the basic pattern
-// of:
-//
-// for !ars.IsEmpty() {
-// n, err = doIOWith(ars.Head())
-// if err != nil {
-// return err
-// }
-// ars = ars.DropFirst(n)
-// }
-//
-// works even in the presence of zero-length AddrRanges.
-//
-// Preconditions: n >= 0.
-func (ars AddrRangeSeq) DropFirst(n int) AddrRangeSeq {
- if n < 0 {
- panic(fmt.Sprintf("invalid n: %d", n))
- }
- return ars.DropFirst64(int64(n))
-}
-
-// DropFirst64 is equivalent to DropFirst but takes an int64.
-func (ars AddrRangeSeq) DropFirst64(n int64) AddrRangeSeq {
- if n < 0 {
- panic(fmt.Sprintf("invalid n: %d", n))
- }
- if Addr(n) > ars.limit {
- return AddrRangeSeq{}
- }
- // Handle initial empty AddrRange.
- switch ars.length {
- case 0:
- return AddrRangeSeq{}
- case 1:
- if ars.limit == 0 {
- return AddrRangeSeq{}
- }
- default:
- if rawHeadLen := (*AddrRange)(ars.data).Length(); ars.offset == rawHeadLen {
- ars = ars.externalTail()
- }
- }
- for n != 0 {
- // Calling ars.Head() here is surprisingly expensive, so inline getting
- // the head's length.
- var headLen Addr
- if ars.length == 1 {
- headLen = ars.limit
- } else {
- headLen = (*AddrRange)(ars.data).Length() - ars.offset
- }
- if Addr(n) < headLen {
- // Dropping ends partway through the head AddrRange.
- ars.offset += Addr(n)
- ars.limit -= Addr(n)
- return ars
- }
- n -= int64(headLen)
- ars = ars.Tail()
- }
- return ars
-}
-
-// TakeFirst returns an AddrRangeSeq equivalent to ars, but iterating at most n
-// bytes. TakeFirst never removes AddrRanges from ars; AddrRanges beyond the
-// first n bytes are reduced to a length of zero, but will still be iterated.
-//
-// Preconditions: n >= 0.
-func (ars AddrRangeSeq) TakeFirst(n int) AddrRangeSeq {
- if n < 0 {
- panic(fmt.Sprintf("invalid n: %d", n))
- }
- return ars.TakeFirst64(int64(n))
-}
-
-// TakeFirst64 is equivalent to TakeFirst but takes an int64.
-func (ars AddrRangeSeq) TakeFirst64(n int64) AddrRangeSeq {
- if n < 0 {
- panic(fmt.Sprintf("invalid n: %d", n))
- }
- if ars.limit > Addr(n) {
- ars.limit = Addr(n)
- }
- return ars
-}
-
-// String implements fmt.Stringer.String.
-func (ars AddrRangeSeq) String() string {
- // This is deliberately chosen to be the same as fmt's automatic stringer
- // for []AddrRange.
- var buf bytes.Buffer
- buf.WriteByte('[')
- var sep string
- for !ars.IsEmpty() {
- buf.WriteString(sep)
- sep = " "
- buf.WriteString(ars.Head().String())
- ars = ars.Tail()
- }
- buf.WriteByte(']')
- return buf.String()
-}
diff --git a/pkg/usermem/bytes_io.go b/pkg/usermem/bytes_io.go
index e177d30eb..3da3c0294 100644
--- a/pkg/usermem/bytes_io.go
+++ b/pkg/usermem/bytes_io.go
@@ -16,6 +16,7 @@ package usermem
import (
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -30,7 +31,7 @@ type BytesIO struct {
}
// CopyOut implements IO.CopyOut.
-func (b *BytesIO) CopyOut(ctx context.Context, addr Addr, src []byte, opts IOOpts) (int, error) {
+func (b *BytesIO) CopyOut(ctx context.Context, addr hostarch.Addr, src []byte, opts IOOpts) (int, error) {
rngN, rngErr := b.rangeCheck(addr, len(src))
if rngN == 0 {
return 0, rngErr
@@ -39,7 +40,7 @@ func (b *BytesIO) CopyOut(ctx context.Context, addr Addr, src []byte, opts IOOpt
}
// CopyIn implements IO.CopyIn.
-func (b *BytesIO) CopyIn(ctx context.Context, addr Addr, dst []byte, opts IOOpts) (int, error) {
+func (b *BytesIO) CopyIn(ctx context.Context, addr hostarch.Addr, dst []byte, opts IOOpts) (int, error) {
rngN, rngErr := b.rangeCheck(addr, len(dst))
if rngN == 0 {
return 0, rngErr
@@ -48,7 +49,7 @@ func (b *BytesIO) CopyIn(ctx context.Context, addr Addr, dst []byte, opts IOOpts
}
// ZeroOut implements IO.ZeroOut.
-func (b *BytesIO) ZeroOut(ctx context.Context, addr Addr, toZero int64, opts IOOpts) (int64, error) {
+func (b *BytesIO) ZeroOut(ctx context.Context, addr hostarch.Addr, toZero int64, opts IOOpts) (int64, error) {
if toZero > int64(maxInt) {
return 0, syserror.EINVAL
}
@@ -64,7 +65,7 @@ func (b *BytesIO) ZeroOut(ctx context.Context, addr Addr, toZero int64, opts IOO
}
// CopyOutFrom implements IO.CopyOutFrom.
-func (b *BytesIO) CopyOutFrom(ctx context.Context, ars AddrRangeSeq, src safemem.Reader, opts IOOpts) (int64, error) {
+func (b *BytesIO) CopyOutFrom(ctx context.Context, ars hostarch.AddrRangeSeq, src safemem.Reader, opts IOOpts) (int64, error) {
dsts, rngErr := b.blocksFromAddrRanges(ars)
n, err := src.ReadToBlocks(dsts)
if err != nil {
@@ -74,7 +75,7 @@ func (b *BytesIO) CopyOutFrom(ctx context.Context, ars AddrRangeSeq, src safemem
}
// CopyInTo implements IO.CopyInTo.
-func (b *BytesIO) CopyInTo(ctx context.Context, ars AddrRangeSeq, dst safemem.Writer, opts IOOpts) (int64, error) {
+func (b *BytesIO) CopyInTo(ctx context.Context, ars hostarch.AddrRangeSeq, dst safemem.Writer, opts IOOpts) (int64, error) {
srcs, rngErr := b.blocksFromAddrRanges(ars)
n, err := dst.WriteFromBlocks(srcs)
if err != nil {
@@ -83,14 +84,14 @@ func (b *BytesIO) CopyInTo(ctx context.Context, ars AddrRangeSeq, dst safemem.Wr
return int64(n), rngErr
}
-func (b *BytesIO) rangeCheck(addr Addr, length int) (int, error) {
+func (b *BytesIO) rangeCheck(addr hostarch.Addr, length int) (int, error) {
if length == 0 {
return 0, nil
}
if length < 0 {
return 0, syserror.EINVAL
}
- max := Addr(len(b.Bytes))
+ max := hostarch.Addr(len(b.Bytes))
if addr >= max {
return 0, syserror.EFAULT
}
@@ -101,7 +102,7 @@ func (b *BytesIO) rangeCheck(addr Addr, length int) (int, error) {
return length, nil
}
-func (b *BytesIO) blocksFromAddrRanges(ars AddrRangeSeq) (safemem.BlockSeq, error) {
+func (b *BytesIO) blocksFromAddrRanges(ars hostarch.AddrRangeSeq) (safemem.BlockSeq, error) {
switch ars.NumRanges() {
case 0:
return safemem.BlockSeq{}, nil
@@ -124,7 +125,7 @@ func (b *BytesIO) blocksFromAddrRanges(ars AddrRangeSeq) (safemem.BlockSeq, erro
}
}
-func (b *BytesIO) blockFromAddrRange(ar AddrRange) (safemem.Block, error) {
+func (b *BytesIO) blockFromAddrRange(ar hostarch.AddrRange) (safemem.Block, error) {
n, err := b.rangeCheck(ar.Start, int(ar.Length()))
if n == 0 {
return safemem.Block{}, err
@@ -136,6 +137,6 @@ func (b *BytesIO) blockFromAddrRange(ar AddrRange) (safemem.Block, error) {
func BytesIOSequence(buf []byte) IOSequence {
return IOSequence{
IO: &BytesIO{buf},
- Addrs: AddrRangeSeqOf(AddrRange{0, Addr(len(buf))}),
+ Addrs: hostarch.AddrRangeSeqOf(hostarch.AddrRange{0, hostarch.Addr(len(buf))}),
}
}
diff --git a/pkg/usermem/bytes_io_unsafe.go b/pkg/usermem/bytes_io_unsafe.go
index 20de5037d..dcd5c81d1 100644
--- a/pkg/usermem/bytes_io_unsafe.go
+++ b/pkg/usermem/bytes_io_unsafe.go
@@ -20,10 +20,11 @@ import (
"gvisor.dev/gvisor/pkg/atomicbitops"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/hostarch"
)
// SwapUint32 implements IO.SwapUint32.
-func (b *BytesIO) SwapUint32(ctx context.Context, addr Addr, new uint32, opts IOOpts) (uint32, error) {
+func (b *BytesIO) SwapUint32(ctx context.Context, addr hostarch.Addr, new uint32, opts IOOpts) (uint32, error) {
if _, rngErr := b.rangeCheck(addr, 4); rngErr != nil {
return 0, rngErr
}
@@ -31,7 +32,7 @@ func (b *BytesIO) SwapUint32(ctx context.Context, addr Addr, new uint32, opts IO
}
// CompareAndSwapUint32 implements IO.CompareAndSwapUint32.
-func (b *BytesIO) CompareAndSwapUint32(ctx context.Context, addr Addr, old, new uint32, opts IOOpts) (uint32, error) {
+func (b *BytesIO) CompareAndSwapUint32(ctx context.Context, addr hostarch.Addr, old, new uint32, opts IOOpts) (uint32, error) {
if _, rngErr := b.rangeCheck(addr, 4); rngErr != nil {
return 0, rngErr
}
@@ -39,7 +40,7 @@ func (b *BytesIO) CompareAndSwapUint32(ctx context.Context, addr Addr, old, new
}
// LoadUint32 implements IO.LoadUint32.
-func (b *BytesIO) LoadUint32(ctx context.Context, addr Addr, opts IOOpts) (uint32, error) {
+func (b *BytesIO) LoadUint32(ctx context.Context, addr hostarch.Addr, opts IOOpts) (uint32, error) {
if _, err := b.rangeCheck(addr, 4); err != nil {
return 0, err
}
diff --git a/pkg/usermem/usermem.go b/pkg/usermem/usermem.go
index dc2571154..0d6d25e50 100644
--- a/pkg/usermem/usermem.go
+++ b/pkg/usermem/usermem.go
@@ -25,6 +25,8 @@ import (
"gvisor.dev/gvisor/pkg/gohacks"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/syserror"
+
+ "gvisor.dev/gvisor/pkg/hostarch"
)
// IO provides access to the contents of a virtual memory space.
@@ -37,7 +39,7 @@ type IO interface {
// any following locks in the lock order.
//
// Postconditions: CopyOut does not retain src.
- CopyOut(ctx context.Context, addr Addr, src []byte, opts IOOpts) (int, error)
+ CopyOut(ctx context.Context, addr hostarch.Addr, src []byte, opts IOOpts) (int, error)
// CopyIn copies len(dst) bytes from the memory mapped at addr to dst.
// It returns the number of bytes copied. If the number of bytes copied is
@@ -47,7 +49,7 @@ type IO interface {
// any following locks in the lock order.
//
// Postconditions: CopyIn does not retain dst.
- CopyIn(ctx context.Context, addr Addr, dst []byte, opts IOOpts) (int, error)
+ CopyIn(ctx context.Context, addr hostarch.Addr, dst []byte, opts IOOpts) (int, error)
// ZeroOut sets toZero bytes to 0, starting at addr. It returns the number
// of bytes zeroed. If the number of bytes zeroed is < toZero, it returns a
@@ -57,7 +59,7 @@ type IO interface {
// * The caller must not hold mm.MemoryManager.mappingMu or any
// following locks in the lock order.
// * toZero >= 0.
- ZeroOut(ctx context.Context, addr Addr, toZero int64, opts IOOpts) (int64, error)
+ ZeroOut(ctx context.Context, addr hostarch.Addr, toZero int64, opts IOOpts) (int64, error)
// CopyOutFrom copies ars.NumBytes() bytes from src to the memory mapped at
// ars. It returns the number of bytes copied, which may be less than the
@@ -72,7 +74,7 @@ type IO interface {
// following locks in the lock order.
// * src.ReadToBlocks must not block on mm.MemoryManager.activeMu or
// any preceding locks in the lock order.
- CopyOutFrom(ctx context.Context, ars AddrRangeSeq, src safemem.Reader, opts IOOpts) (int64, error)
+ CopyOutFrom(ctx context.Context, ars hostarch.AddrRangeSeq, src safemem.Reader, opts IOOpts) (int64, error)
// CopyInTo copies ars.NumBytes() bytes from the memory mapped at ars to
// dst. It returns the number of bytes copied. CopyInTo may return a
@@ -86,7 +88,7 @@ type IO interface {
// following locks in the lock order.
// * dst.WriteFromBlocks must not block on mm.MemoryManager.activeMu or
// any preceding locks in the lock order.
- CopyInTo(ctx context.Context, ars AddrRangeSeq, dst safemem.Writer, opts IOOpts) (int64, error)
+ CopyInTo(ctx context.Context, ars hostarch.AddrRangeSeq, dst safemem.Writer, opts IOOpts) (int64, error)
// TODO(jamieliu): The requirement that CopyOutFrom/CopyInTo call src/dst
// at most once, which is unnecessary in most cases, forces implementations
@@ -101,7 +103,7 @@ type IO interface {
// * The caller must not hold mm.MemoryManager.mappingMu or any
// following locks in the lock order.
// * addr must be aligned to a 4-byte boundary.
- SwapUint32(ctx context.Context, addr Addr, new uint32, opts IOOpts) (uint32, error)
+ SwapUint32(ctx context.Context, addr hostarch.Addr, new uint32, opts IOOpts) (uint32, error)
// CompareAndSwapUint32 atomically compares the uint32 value at addr to
// old; if they are equal, the value in memory is replaced by new. In
@@ -111,7 +113,7 @@ type IO interface {
// * The caller must not hold mm.MemoryManager.mappingMu or any
// following locks in the lock order.
// * addr must be aligned to a 4-byte boundary.
- CompareAndSwapUint32(ctx context.Context, addr Addr, old, new uint32, opts IOOpts) (uint32, error)
+ CompareAndSwapUint32(ctx context.Context, addr hostarch.Addr, old, new uint32, opts IOOpts) (uint32, error)
// LoadUint32 atomically loads the uint32 value at addr and returns it.
//
@@ -119,7 +121,7 @@ type IO interface {
// * The caller must not hold mm.MemoryManager.mappingMu or any
// following locks in the lock order.
// * addr must be aligned to a 4-byte boundary.
- LoadUint32(ctx context.Context, addr Addr, opts IOOpts) (uint32, error)
+ LoadUint32(ctx context.Context, addr hostarch.Addr, opts IOOpts) (uint32, error)
}
// IOOpts contains options applicable to all IO methods.
@@ -142,7 +144,7 @@ type IOOpts struct {
type IOReadWriter struct {
Ctx context.Context
IO IO
- Addr Addr
+ Addr hostarch.Addr
Opts IOOpts
}
@@ -159,7 +161,7 @@ func (rw *IOReadWriter) Read(dst []byte) (int, error) {
rw.Addr = end
} else {
// Disallow wraparound.
- rw.Addr = ^Addr(0)
+ rw.Addr = ^hostarch.Addr(0)
if err != nil {
err = syserror.EFAULT
}
@@ -175,7 +177,7 @@ func (rw *IOReadWriter) Write(src []byte) (int, error) {
rw.Addr = end
} else {
// Disallow wraparound.
- rw.Addr = ^Addr(0)
+ rw.Addr = ^hostarch.Addr(0)
if err != nil {
err = syserror.EFAULT
}
@@ -197,7 +199,7 @@ const (
//
// Preconditions: Same as IO.CopyFromUser, plus:
// * maxlen >= 0.
-func CopyStringIn(ctx context.Context, uio IO, addr Addr, maxlen int, opts IOOpts) (string, error) {
+func CopyStringIn(ctx context.Context, uio IO, addr hostarch.Addr, maxlen int, opts IOOpts) (string, error) {
initLen := maxlen
if initLen > copyStringMaxInitBufLen {
initLen = copyStringMaxInitBufLen
@@ -251,12 +253,12 @@ func CopyStringIn(ctx context.Context, uio IO, addr Addr, maxlen int, opts IOOpt
// the maximum, it returns a non-nil error explaining why.
//
// Preconditions: Same as IO.CopyOut.
-func CopyOutVec(ctx context.Context, uio IO, ars AddrRangeSeq, src []byte, opts IOOpts) (int, error) {
+func CopyOutVec(ctx context.Context, uio IO, ars hostarch.AddrRangeSeq, src []byte, opts IOOpts) (int, error) {
var done int
for !ars.IsEmpty() && done < len(src) {
ar := ars.Head()
cplen := len(src) - done
- if Addr(cplen) >= ar.Length() {
+ if hostarch.Addr(cplen) >= ar.Length() {
cplen = int(ar.Length())
}
n, err := uio.CopyOut(ctx, ar.Start, src[done:done+cplen], opts)
@@ -275,12 +277,12 @@ func CopyOutVec(ctx context.Context, uio IO, ars AddrRangeSeq, src []byte, opts
// maximum, it returns a non-nil error explaining why.
//
// Preconditions: Same as IO.CopyIn.
-func CopyInVec(ctx context.Context, uio IO, ars AddrRangeSeq, dst []byte, opts IOOpts) (int, error) {
+func CopyInVec(ctx context.Context, uio IO, ars hostarch.AddrRangeSeq, dst []byte, opts IOOpts) (int, error) {
var done int
for !ars.IsEmpty() && done < len(dst) {
ar := ars.Head()
cplen := len(dst) - done
- if Addr(cplen) >= ar.Length() {
+ if hostarch.Addr(cplen) >= ar.Length() {
cplen = int(ar.Length())
}
n, err := uio.CopyIn(ctx, ar.Start, dst[done:done+cplen], opts)
@@ -299,12 +301,12 @@ func CopyInVec(ctx context.Context, uio IO, ars AddrRangeSeq, dst []byte, opts I
// maximum, it returns a non-nil error explaining why.
//
// Preconditions: Same as IO.ZeroOut.
-func ZeroOutVec(ctx context.Context, uio IO, ars AddrRangeSeq, toZero int64, opts IOOpts) (int64, error) {
+func ZeroOutVec(ctx context.Context, uio IO, ars hostarch.AddrRangeSeq, toZero int64, opts IOOpts) (int64, error) {
var done int64
for !ars.IsEmpty() && done < toZero {
ar := ars.Head()
cplen := toZero - done
- if Addr(cplen) >= ar.Length() {
+ if hostarch.Addr(cplen) >= ar.Length() {
cplen = int64(ar.Length())
}
n, err := uio.ZeroOut(ctx, ar.Start, cplen, opts)
@@ -352,7 +354,7 @@ func isASCIIWhitespace(b byte) bool {
// - CopyInt32StringsInVec returns EINVAL if ars.NumBytes() == 0.
//
// Preconditions: Same as CopyInVec.
-func CopyInt32StringsInVec(ctx context.Context, uio IO, ars AddrRangeSeq, dsts []int32, opts IOOpts) (int64, error) {
+func CopyInt32StringsInVec(ctx context.Context, uio IO, ars hostarch.AddrRangeSeq, dsts []int32, opts IOOpts) (int64, error) {
if len(dsts) == 0 {
return 0, nil
}
@@ -403,7 +405,7 @@ func CopyInt32StringsInVec(ctx context.Context, uio IO, ars AddrRangeSeq, dsts [
// CopyInt32StringInVec is equivalent to CopyInt32StringsInVec, but copies at
// most one int32.
-func CopyInt32StringInVec(ctx context.Context, uio IO, ars AddrRangeSeq, dst *int32, opts IOOpts) (int64, error) {
+func CopyInt32StringInVec(ctx context.Context, uio IO, ars hostarch.AddrRangeSeq, dst *int32, opts IOOpts) (int64, error) {
dsts := [1]int32{*dst}
n, err := CopyInt32StringsInVec(ctx, uio, ars, dsts[:], opts)
*dst = dsts[0]
@@ -413,7 +415,7 @@ func CopyInt32StringInVec(ctx context.Context, uio IO, ars AddrRangeSeq, dst *in
// IOSequence holds arguments to IO methods.
type IOSequence struct {
IO IO
- Addrs AddrRangeSeq
+ Addrs hostarch.AddrRangeSeq
Opts IOOpts
}
@@ -444,28 +446,28 @@ func (s IOSequence) NumBytes() int64 {
// DropFirst returns a copy of s with s.Addrs.DropFirst(n).
//
-// Preconditions: Same as AddrRangeSeq.DropFirst.
+// Preconditions: Same as hostarch.AddrRangeSeq.DropFirst.
func (s IOSequence) DropFirst(n int) IOSequence {
return IOSequence{s.IO, s.Addrs.DropFirst(n), s.Opts}
}
// DropFirst64 returns a copy of s with s.Addrs.DropFirst64(n).
//
-// Preconditions: Same as AddrRangeSeq.DropFirst64.
+// Preconditions: Same as hostarch.AddrRangeSeq.DropFirst64.
func (s IOSequence) DropFirst64(n int64) IOSequence {
return IOSequence{s.IO, s.Addrs.DropFirst64(n), s.Opts}
}
// TakeFirst returns a copy of s with s.Addrs.TakeFirst(n).
//
-// Preconditions: Same as AddrRangeSeq.TakeFirst.
+// Preconditions: Same as hostarch.AddrRangeSeq.TakeFirst.
func (s IOSequence) TakeFirst(n int) IOSequence {
return IOSequence{s.IO, s.Addrs.TakeFirst(n), s.Opts}
}
// TakeFirst64 returns a copy of s with s.Addrs.TakeFirst64(n).
//
-// Preconditions: Same as AddrRangeSeq.TakeFirst64.
+// Preconditions: Same as hostarch.AddrRangeSeq.TakeFirst64.
func (s IOSequence) TakeFirst64(n int64) IOSequence {
return IOSequence{s.IO, s.Addrs.TakeFirst64(n), s.Opts}
}
diff --git a/pkg/usermem/usermem_arm64.go b/pkg/usermem/usermem_arm64.go
deleted file mode 100644
index 7e7529585..000000000
--- a/pkg/usermem/usermem_arm64.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// +build arm64
-
-package usermem
-
-import (
- "encoding/binary"
-
- "golang.org/x/sys/unix"
-)
-
-const (
- // PageSize is the system page size.
- // arm64 support 4K/16K/64K page size,
- // which can be get by unix.Getpagesize().
- // Currently, only 4K page size is supported.
- PageSize = 1 << PageShift
-
- // HugePageSize is the system huge page size.
- HugePageSize = 1 << HugePageShift
-
- // PageShift is the binary log of the system page size.
- PageShift = 12
-
- // HugePageShift is the binary log of the system huge page size.
- // Should be calculated by "PageShift + (PageShift - 3)"
- // when multiple page size support is ready.
- HugePageShift = 21
-)
-
-var (
- // ByteOrder is the native byte order (little endian).
- ByteOrder = binary.LittleEndian
-)
-
-func init() {
- // Make sure the page size is 4K on arm64 platform.
- if size := unix.Getpagesize(); size != PageSize {
- panic("Only 4K page size is supported on arm64!")
- }
-}
diff --git a/pkg/usermem/usermem_arm64_state_autogen.go b/pkg/usermem/usermem_arm64_state_autogen.go
deleted file mode 100644
index d7c365e5d..000000000
--- a/pkg/usermem/usermem_arm64_state_autogen.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// automatically generated by stateify.
-
-// +build arm64
-
-package usermem
diff --git a/pkg/usermem/usermem_state_autogen.go b/pkg/usermem/usermem_state_autogen.go
index 48714d65c..62f8af4c9 100644
--- a/pkg/usermem/usermem_state_autogen.go
+++ b/pkg/usermem/usermem_state_autogen.go
@@ -1,80 +1,3 @@
// automatically generated by stateify.
package usermem
-
-import (
- "gvisor.dev/gvisor/pkg/state"
-)
-
-func (a *AccessType) StateTypeName() string {
- return "pkg/usermem.AccessType"
-}
-
-func (a *AccessType) StateFields() []string {
- return []string{
- "Read",
- "Write",
- "Execute",
- }
-}
-
-func (a *AccessType) beforeSave() {}
-
-// +checklocksignore
-func (a *AccessType) StateSave(stateSinkObject state.Sink) {
- a.beforeSave()
- stateSinkObject.Save(0, &a.Read)
- stateSinkObject.Save(1, &a.Write)
- stateSinkObject.Save(2, &a.Execute)
-}
-
-func (a *AccessType) afterLoad() {}
-
-// +checklocksignore
-func (a *AccessType) StateLoad(stateSourceObject state.Source) {
- stateSourceObject.Load(0, &a.Read)
- stateSourceObject.Load(1, &a.Write)
- stateSourceObject.Load(2, &a.Execute)
-}
-
-func (v *Addr) StateTypeName() string {
- return "pkg/usermem.Addr"
-}
-
-func (v *Addr) StateFields() []string {
- return nil
-}
-
-func (r *AddrRange) StateTypeName() string {
- return "pkg/usermem.AddrRange"
-}
-
-func (r *AddrRange) StateFields() []string {
- return []string{
- "Start",
- "End",
- }
-}
-
-func (r *AddrRange) beforeSave() {}
-
-// +checklocksignore
-func (r *AddrRange) StateSave(stateSinkObject state.Sink) {
- r.beforeSave()
- stateSinkObject.Save(0, &r.Start)
- stateSinkObject.Save(1, &r.End)
-}
-
-func (r *AddrRange) afterLoad() {}
-
-// +checklocksignore
-func (r *AddrRange) StateLoad(stateSourceObject state.Source) {
- stateSourceObject.Load(0, &r.Start)
- stateSourceObject.Load(1, &r.End)
-}
-
-func init() {
- state.Register((*AccessType)(nil))
- state.Register((*Addr)(nil))
- state.Register((*AddrRange)(nil))
-}
diff --git a/pkg/usermem/usermem_x86.go b/pkg/usermem/usermem_x86.go
deleted file mode 100644
index d96f829fb..000000000
--- a/pkg/usermem/usermem_x86.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// +build amd64 386
-
-package usermem
-
-import "encoding/binary"
-
-const (
- // PageSize is the system page size.
- PageSize = 1 << PageShift
-
- // HugePageSize is the system huge page size.
- HugePageSize = 1 << HugePageShift
-
- // PageShift is the binary log of the system page size.
- PageShift = 12
-
- // HugePageShift is the binary log of the system huge page size.
- HugePageShift = 21
-)
-
-var (
- // ByteOrder is the native byte order (little endian).
- ByteOrder = binary.LittleEndian
-)
diff --git a/pkg/usermem/usermem_x86_state_autogen.go b/pkg/usermem/usermem_x86_state_autogen.go
deleted file mode 100644
index cca386593..000000000
--- a/pkg/usermem/usermem_x86_state_autogen.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// automatically generated by stateify.
-
-// +build amd64 386
-
-package usermem