gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/hostarch/addr.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package hostarch
    16  
    17  import (
    18  	"fmt"
    19  )
    20  
    21  // Addr represents an address in an unspecified address space.
    22  //
    23  // +stateify savable
    24  type Addr uintptr
    25  
    26  // AddLength adds the given length to start and returns the result. ok is true
    27  // iff adding the length did not overflow the range of Addr.
    28  //
    29  // Note: This function is usually used to get the end of an address range
    30  // defined by its start address and length. Since the resulting end is
    31  // exclusive, end == 0 is technically valid, and corresponds to a range that
    32  // extends to the end of the address space, but ok will be false. This isn't
    33  // expected to ever come up in practice.
    34  func (v Addr) AddLength(length uint64) (end Addr, ok bool) {
    35  	end = v + Addr(length)
    36  	// As of this writing (Go 1.21), addrAtLeast64b is required to prevent the
    37  	// compiler from generating a tautological `length <= MaxUint64` check on
    38  	// 64-bit architectures.
    39  	ok = end >= v && (addrAtLeast64b || length <= uint64(^Addr(0)))
    40  	return
    41  }
    42  
    43  // RoundDown is equivalent to function PageRoundDown.
    44  func (v Addr) RoundDown() Addr {
    45  	return PageRoundDown(v)
    46  }
    47  
    48  // RoundUp is equivalent to function PageRoundUp.
    49  func (v Addr) RoundUp() (Addr, bool) {
    50  	return PageRoundUp(v)
    51  }
    52  
    53  // MustRoundUp is equivalent to function MustPageRoundUp.
    54  func (v Addr) MustRoundUp() Addr {
    55  	return MustPageRoundUp(v)
    56  }
    57  
    58  // HugeRoundDown is equivalent to function HugePageRoundDown.
    59  func (v Addr) HugeRoundDown() Addr {
    60  	return HugePageRoundDown(v)
    61  }
    62  
    63  // HugeRoundUp is equivalent to function HugePageRoundUp.
    64  func (v Addr) HugeRoundUp() (Addr, bool) {
    65  	return HugePageRoundUp(v)
    66  }
    67  
    68  // MustHugeRoundUp is equivalent to function MustHugePageRoundUp.
    69  func (v Addr) MustHugeRoundUp() Addr {
    70  	return MustHugePageRoundUp(v)
    71  }
    72  
    73  // PageOffset is equivalent to function PageOffset, except that it casts the
    74  // result to uint64.
    75  func (v Addr) PageOffset() uint64 {
    76  	return uint64(PageOffset(v))
    77  }
    78  
    79  // IsPageAligned is equivalent to function IsPageAligned.
    80  func (v Addr) IsPageAligned() bool {
    81  	return IsPageAligned(v)
    82  }
    83  
    84  // HugePageOffset is equivalent to function HugePageOffset.
    85  func (v Addr) HugePageOffset() uint64 {
    86  	return uint64(HugePageOffset(v))
    87  }
    88  
    89  // IsHugePageAligned is equivalent to function IsHugePageAligned.
    90  func (v Addr) IsHugePageAligned() bool {
    91  	return IsHugePageAligned(v)
    92  }
    93  
    94  // AddrRange is a range of Addrs.
    95  //
    96  // type AddrRange <generated by go_generics>
    97  
    98  // ToRange returns [v, v+length).
    99  func (v Addr) ToRange(length uint64) (AddrRange, bool) {
   100  	end, ok := v.AddLength(length)
   101  	return AddrRange{v, end}, ok
   102  }
   103  
   104  // IsPageAligned returns true if ar.Start.IsPageAligned() and
   105  // ar.End.IsPageAligned().
   106  func (ar AddrRange) IsPageAligned() bool {
   107  	return ar.Start.IsPageAligned() && ar.End.IsPageAligned()
   108  }
   109  
   110  // IsHugePageAligned returns true if ar.Start.IsHugePageAligned() and
   111  // ar.End.IsHugePageAligned().
   112  func (ar AddrRange) IsHugePageAligned() bool {
   113  	return ar.Start.IsHugePageAligned() && ar.End.IsHugePageAligned()
   114  }
   115  
   116  // String implements fmt.Stringer.String.
   117  func (ar AddrRange) String() string {
   118  	return fmt.Sprintf("[%#x, %#x)", ar.Start, ar.End)
   119  }