Skip to content

Commit

Permalink
nvproxy: allow use with KVM platform
Browse files Browse the repository at this point in the history
Updates #11436

PiperOrigin-RevId: 724028319
  • Loading branch information
nixprime authored and gvisor-bot committed Feb 7, 2025
1 parent da7cd03 commit 098a747
Show file tree
Hide file tree
Showing 37 changed files with 395 additions and 131 deletions.
14 changes: 13 additions & 1 deletion pkg/abi/nvgpu/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ type NVOS02_PARAMETERS struct {
Pad1 [4]byte
}

// Bitfields in NVOS02Parameters.Flags:
// Bitfields in NVOS02_PARAMETERS.Flags:
const (
NVOS02_FLAGS_ALLOC_SHIFT = 16
NVOS02_FLAGS_ALLOC_MASK = 0x3
Expand Down Expand Up @@ -470,6 +470,18 @@ type NVOS33_PARAMETERS struct {
Flags uint32
}

// Bitfields in NVOS33_PARAMETERS.Flags:
const (
NVOS33_FLAGS_CACHING_TYPE_SHIFT = 23
NVOS33_FLAGS_CACHING_TYPE_MASK = 0x7
NVOS33_FLAGS_CACHING_TYPE_CACHED = 0
NVOS33_FLAGS_CACHING_TYPE_UNCACHED = 1
NVOS33_FLAGS_CACHING_TYPE_WRITECOMBINED = 2
NVOS33_FLAGS_CACHING_TYPE_WRITEBACK = 5
NVOS33_FLAGS_CACHING_TYPE_DEFAULT = 6
NVOS33_FLAGS_CACHING_TYPE_UNCACHED_WEAK = 7
)

// NVOS34_PARAMETERS is the parameter type for NV_ESC_RM_UNMAP_MEMORY.
//
// +marshal
Expand Down
1 change: 1 addition & 0 deletions pkg/hostarch/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ go_library(
"hostarch.go",
"hostarch_arm64.go",
"hostarch_x86.go",
"memory_type.go",
"sizes_util.go",
],
visibility = ["//:sandbox"],
Expand Down
52 changes: 52 additions & 0 deletions pkg/hostarch/memory_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2025 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

// MemoryType specifies CPU memory access behavior.
type MemoryType uint8

const (
// MemoryTypeWriteBack is equivalent to Linux's default pgprot, or the
// following architectural memory types:
//
// - x86: Write-back (WB)
//
// - ARM64: Normal write-back cacheable
//
// This memory type is appropriate for typical application memory and must
// be the zero value for MemoryType.
MemoryTypeWriteBack MemoryType = iota

// MemoryTypeWriteCombine is equivalent to Linux's pgprot_writecombine(),
// or the following architectural memory types:
//
// - x86: Write-combining (WC)
//
// - ARM64: Normal non-cacheable
MemoryTypeWriteCombine

// MemoryTypeUncacheable is equivalent to Linux's pgprot_noncached(), or
// the following architectural memory types:
//
// - x86: Strong Uncacheable (UC) or Uncacheable (UC-); these differ in that
// UC- may be "downgraded" to WC by a setting of WC or WP in MTRR, but
// gVisor does not use MTRRs.
//
// - ARM64: Device-nGnRnE
MemoryTypeUncacheable

// NumMemoryTypes is the number of memory types.
NumMemoryTypes
)
59 changes: 30 additions & 29 deletions pkg/ring0/pagetables/pagetables_aarch64.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,26 @@ func (p *PageTables) TTBR1_EL1(noFlush bool, asid uint16) uint64 {

// Bits in page table entries.
const (
typeTable = 0x3 << 0
typeSect = 0x1 << 0
typePage = 0x3 << 0
pteValid = 0x1 << 0
pteTableBit = 0x1 << 1
pteTypeMask = 0x3 << 0
present = pteValid | pteTableBit
user = 0x1 << 6 /* AP[1] */
readOnly = 0x1 << 7 /* AP[2] */
accessed = 0x1 << 10
dbm = 0x1 << 51
writable = dbm
cont = 0x1 << 52
pxn = 0x1 << 53
xn = 0x1 << 54
dirty = 0x1 << 55
nG = 0x1 << 11
shared = 0x3 << 8
)

const (
mtDevicenGnRE = 0x1 << 2
mtNormal = 0x4 << 2
typeTable = 0x3 << 0
typeSect = 0x1 << 0
typePage = 0x3 << 0
pteValid = 0x1 << 0
pteTableBit = 0x1 << 1
pteTypeMask = 0x3 << 0
present = pteValid | pteTableBit
attrIndxShift = 2
attrIndxMask = 0x7
user = 0x1 << 6 /* AP[1] */
readOnly = 0x1 << 7 /* AP[2] */
accessed = 0x1 << 10
dbm = 0x1 << 51
writable = dbm
cont = 0x1 << 52
pxn = 0x1 << 53
xn = 0x1 << 54
dirty = 0x1 << 55
nG = 0x1 << 11
shared = 0x3 << 8
)

const (
Expand All @@ -93,6 +90,9 @@ type MapOpts struct {

// User indicates the page is a user page.
User bool

// MemoryType is the memory type.
MemoryType hostarch.MemoryType
}

// PTE is a page table entry.
Expand All @@ -119,15 +119,15 @@ func (p *PTE) Valid() bool {
//go:nosplit
func (p *PTE) Opts() MapOpts {
v := atomic.LoadUintptr((*uintptr)(p))

return MapOpts{
AccessType: hostarch.AccessType{
Read: true,
Write: v&readOnly == 0,
Execute: v&xn == 0,
},
Global: v&nG == 0,
User: v&user != 0,
Global: v&nG == 0,
User: v&user != 0,
MemoryType: hostarch.MemoryType((v >> attrIndxShift) & attrIndxMask),
}
}

Expand Down Expand Up @@ -191,11 +191,12 @@ func (p *PTE) Set(addr uintptr, opts MapOpts) {

if opts.User {
v |= user
v |= mtNormal
} else {
v = v &^ user
v |= mtNormal
}

v |= uintptr(opts.MemoryType&attrIndxMask) << attrIndxShift

atomic.StoreUintptr((*uintptr)(p), v)
}

Expand All @@ -209,7 +210,7 @@ func (p *PTE) setPageTable(pt *PageTables, ptes *PTEs) {
// This should never happen.
panic("unaligned physical address!")
}
v := addr | typeTable | protDefault | mtNormal
v := addr | typeTable | protDefault | (uintptr(hostarch.MemoryTypeWriteBack) << attrIndxShift)
atomic.StoreUintptr((*uintptr)(p), v)
}

Expand Down
10 changes: 10 additions & 0 deletions pkg/ring0/pagetables/pagetables_amd64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,13 @@ func TestSplit2MPage(t *testing.T) {
{0x00007f0000000000 + pmdSize - pteSize, pteSize, pmdSize*42 + pmdSize - pteSize, MapOpts{AccessType: hostarch.Read}},
})
}

func TestNumMemoryTypes(t *testing.T) {
// The PAT accommodates up to 8 entries. However, PTE.Set() currently
// assumes that NumMemoryTypes <= 4, since the location of the most
// significant bit of the PAT index in page table entries varies depending
// on page size (and is never bit 5 == writeThroughShift + 2).
if hostarch.NumMemoryTypes > 4 {
t.Errorf("PTE.Set() and PTE.Opts() must be altered to handle %d MemoryTypes", hostarch.NumMemoryTypes)
}
}
7 changes: 7 additions & 0 deletions pkg/ring0/pagetables/pagetables_arm64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,10 @@ func TestSplit2MPage(t *testing.T) {
{0x0000ff0000000000 + pmdSize - pteSize, pteSize, pmdSize*42 + pmdSize - pteSize, MapOpts{AccessType: hostarch.Read, User: true}},
})
}

func TestNumMemoryTypes(t *testing.T) {
// MAIR accommodates up to 8 entries.
if hostarch.NumMemoryTypes > 8 {
t.Errorf("PTE.Set() and PTE.Opts() must be altered to map %d MemoryTypes to a smaller set of MAIR entries", hostarch.NumMemoryTypes)
}
}
32 changes: 19 additions & 13 deletions pkg/ring0/pagetables/pagetables_x86.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,17 @@ func (p *PageTables) CR3(noFlush bool, pcid uint16) uint64 {

// Bits in page table entries.
const (
present = 0x001
writable = 0x002
user = 0x004
writeThrough = 0x008
cacheDisable = 0x010
accessed = 0x020
dirty = 0x040
super = 0x080
global = 0x100
optionMask = executeDisable | 0xfff
present = 0x001
writable = 0x002
user = 0x004
accessed = 0x020
dirty = 0x040
super = 0x080
global = 0x100
optionMask = executeDisable | 0xfff

writeThroughShift = 3
patIndexMask = 0x3
)

// MapOpts are x86 options.
Expand All @@ -71,6 +72,9 @@ type MapOpts struct {

// User indicates the page is a user page.
User bool

// MemoryType is the memory type.
MemoryType hostarch.MemoryType
}

// PTE is a page table entry.
Expand Down Expand Up @@ -103,8 +107,9 @@ func (p *PTE) Opts() MapOpts {
Write: v&writable != 0,
Execute: v&executeDisable == 0,
},
Global: v&global != 0,
User: v&user != 0,
Global: v&global != 0,
User: v&user != 0,
MemoryType: hostarch.MemoryType((v >> writeThroughShift) & patIndexMask),
}
}

Expand Down Expand Up @@ -154,6 +159,7 @@ func (p *PTE) Set(addr uintptr, opts MapOpts) {
if opts.AccessType.Write {
v |= writable | dirty
}
v |= uintptr(opts.MemoryType&patIndexMask) << writeThroughShift
if p.IsSuper() {
// Note that this is inherited from the previous instance. Set
// does not change the value of Super. See above.
Expand All @@ -172,7 +178,7 @@ func (p *PTE) setPageTable(pt *PageTables, ptes *PTEs) {
// This should never happen.
panic("unaligned physical address!")
}
v := addr | present | user | writable | accessed | dirty
v := addr | present | user | writable | accessed | dirty | (uintptr(hostarch.MemoryTypeWriteBack) << writeThroughShift)
atomic.StoreUintptr((*uintptr)(p), v)
}

Expand Down
1 change: 1 addition & 0 deletions pkg/sentry/devices/nvproxy/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ go_library(
"//pkg/seccomp",
"//pkg/sentry/arch",
"//pkg/sentry/devices/nvproxy/nvconf",
"//pkg/sentry/fsutil",
"//pkg/sentry/kernel",
"//pkg/sentry/memmap",
"//pkg/sentry/mm",
Expand Down
Loading

0 comments on commit 098a747

Please sign in to comment.