kvm: prefault a root table page before switching into a user address space

The root table physical page has to be mapped to not fault in iret or sysret
after switching into a user address space.  sysret and iret are in the upper
half that is global and so page tables of lower levels are already mapped.

Fixes #5742

PiperOrigin-RevId: 371458644
This commit is contained in:
Andrei Vagin
2021-04-30 23:07:15 -07:00
committed by gVisor bot
parent 6fb8c01bb4
commit cde8e8b7a9
2 changed files with 13 additions and 0 deletions
+9
View File
@@ -322,3 +322,12 @@ func (p *PageTables) Lookup(addr hostarch.Addr, findFirst bool) (virtual hostarc
func (p *PageTables) MarkReadOnlyShared() {
p.readOnlyShared = true
}
// PrefaultRootTable touches the root table page to be sure that its physical
// pages are mapped.
//
//go:nosplit
//go:noinline
func (p *PageTables) PrefaultRootTable() PTE {
return p.root[0]
}
+4
View File
@@ -351,6 +351,10 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
// allocations occur.
entersyscall()
bluepill(c)
// The root table physical page has to be mapped to not fault in iret
// or sysret after switching into a user address space. sysret and
// iret are in the upper half that is global and already mapped.
switchOpts.PageTables.PrefaultRootTable()
prefaultFloatingPointState(switchOpts.FloatingPointState)
vector = c.CPU.SwitchToUser(switchOpts)
exitsyscall()