diff --git a/pkg/hostarch/BUILD b/pkg/hostarch/BUILD index 90952d585..3508c443f 100644 --- a/pkg/hostarch/BUILD +++ b/pkg/hostarch/BUILD @@ -34,6 +34,7 @@ go_library( "addr.go", "addr_range.go", "addr_range_seq_unsafe.go", + "addr_unsafe.go", "hostarch.go", "hostarch_arm64.go", "hostarch_x86.go", diff --git a/pkg/hostarch/addr.go b/pkg/hostarch/addr.go index c39479759..2f7dcf1d5 100644 --- a/pkg/hostarch/addr.go +++ b/pkg/hostarch/addr.go @@ -33,9 +33,10 @@ type Addr uintptr // 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)) + // As of this writing (Go 1.21), addrAtLeast64b is required to prevent the + // compiler from generating a tautological `length <= MaxUint64` check on + // 64-bit architectures. + ok = end >= v && (addrAtLeast64b || length <= uint64(^Addr(0))) return } @@ -64,6 +65,11 @@ func (v Addr) HugeRoundUp() (Addr, bool) { return HugePageRoundUp(v) } +// MustHugeRoundUp is equivalent to function MustHugePageRoundUp. +func (v Addr) MustHugeRoundUp() Addr { + return MustHugePageRoundUp(v) +} + // PageOffset is equivalent to function PageOffset, except that it casts the // result to uint64. func (v Addr) PageOffset() uint64 { @@ -75,6 +81,16 @@ func (v Addr) IsPageAligned() bool { return IsPageAligned(v) } +// HugePageOffset is equivalent to function HugePageOffset. +func (v Addr) HugePageOffset() uint64 { + return uint64(HugePageOffset(v)) +} + +// IsHugePageAligned is equivalent to function IsHugePageAligned. +func (v Addr) IsHugePageAligned() bool { + return IsHugePageAligned(v) +} + // AddrRange is a range of Addrs. // // type AddrRange @@ -91,6 +107,12 @@ func (ar AddrRange) IsPageAligned() bool { return ar.Start.IsPageAligned() && ar.End.IsPageAligned() } +// IsHugePageAligned returns true if ar.Start.IsHugePageAligned() and +// ar.End.IsHugePageAligned(). +func (ar AddrRange) IsHugePageAligned() bool { + return ar.Start.IsHugePageAligned() && ar.End.IsHugePageAligned() +} + // String implements fmt.Stringer.String. func (ar AddrRange) String() string { return fmt.Sprintf("[%#x, %#x)", ar.Start, ar.End) diff --git a/pkg/hostarch/addr_unsafe.go b/pkg/hostarch/addr_unsafe.go new file mode 100644 index 000000000..63f494e19 --- /dev/null +++ b/pkg/hostarch/addr_unsafe.go @@ -0,0 +1,22 @@ +// Copyright 2023 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 hostarch + +import ( + "unsafe" +) + +// This is used in addr.go:Addr.AddLength(). +const addrAtLeast64b = unsafe.Sizeof(Addr(0)) >= 8