github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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  //
    48  //go:nosplit
    49  func (p *PageTables) InitArch(allocator Allocator) {
    50  	if p.upperSharedPageTables != nil {
    51  		p.cloneUpperShared()
    52  	}
    53  }
    54  
    55  //go:nosplit
    56  func pgdIndex(upperStart uintptr) uintptr {
    57  	if upperStart&(pgdSize-1) != 0 {
    58  		panic("upperStart should be pgd size aligned")
    59  	}
    60  	if upperStart >= upperBottom {
    61  		return entriesPerPage/2 + (upperStart-upperBottom)/pgdSize
    62  	}
    63  	if upperStart < lowerTop {
    64  		return upperStart / pgdSize
    65  	}
    66  	panic("upperStart should be in canonical range")
    67  }
    68  
    69  // cloneUpperShared clone the upper from the upper shared page tables.
    70  //
    71  //go:nosplit
    72  func (p *PageTables) cloneUpperShared() {
    73  	start := pgdIndex(p.upperStart)
    74  	copy(p.root[start:entriesPerPage], p.upperSharedPageTables.root[start:entriesPerPage])
    75  }
    76  
    77  // PTEs is a collection of entries.
    78  type PTEs [entriesPerPage]PTE