github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/ring0/pagetables/pagetables_amd64.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 pagetables
    16  
    17  // Address constraints.
    18  //
    19  // The lowerTop and upperBottom currently apply to four-level pagetables;
    20  // additional refactoring would be necessary to support five-level pagetables.
    21  const (
    22  	lowerTop    = 0x00007fffffffffff
    23  	upperBottom = 0xffff800000000000
    24  
    25  	pteShift = 12
    26  	pmdShift = 21
    27  	pudShift = 30
    28  	pgdShift = 39
    29  
    30  	pteMask = 0x1ff << pteShift
    31  	pmdMask = 0x1ff << pmdShift
    32  	pudMask = 0x1ff << pudShift
    33  	pgdMask = 0x1ff << pgdShift
    34  
    35  	pteSize = 1 << pteShift
    36  	pmdSize = 1 << pmdShift
    37  	pudSize = 1 << pudShift
    38  	pgdSize = 1 << pgdShift
    39  
    40  	executeDisable = 1 << 63
    41  	entriesPerPage = 512
    42  )
    43  
    44  // InitArch does some additional initialization related to the architecture.
    45  //
    46  // +checkescape:hard,stack
    47  //go:nosplit
    48  func (p *PageTables) InitArch(allocator Allocator) {
    49  	if p.upperSharedPageTables != nil {
    50  		p.cloneUpperShared()
    51  	}
    52  }
    53  
    54  //go:nosplit
    55  func pgdIndex(upperStart uintptr) uintptr {
    56  	if upperStart&(pgdSize-1) != 0 {
    57  		panic("upperStart should be pgd size aligned")
    58  	}
    59  	if upperStart >= upperBottom {
    60  		return entriesPerPage/2 + (upperStart-upperBottom)/pgdSize
    61  	}
    62  	if upperStart < lowerTop {
    63  		return upperStart / pgdSize
    64  	}
    65  	panic("upperStart should be in canonical range")
    66  }
    67  
    68  // cloneUpperShared clone the upper from the upper shared page tables.
    69  //
    70  //go:nosplit
    71  func (p *PageTables) cloneUpperShared() {
    72  	start := pgdIndex(p.upperStart)
    73  	copy(p.root[start:entriesPerPage], p.upperSharedPageTables.root[start:entriesPerPage])
    74  }
    75  
    76  // PTEs is a collection of entries.
    77  type PTEs [entriesPerPage]PTE