Define CPUIDInstruction for arm64

There is no cpuid instruction on arm64, so we need to defined it
just to avoid a compile time error.

Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
Andrei Vagin 2020-02-21 11:00:11 -08:00
parent ce4d1e45bb
commit 413a9b7fdc
2 changed files with 33 additions and 13 deletions

View File

@ -53,6 +53,11 @@ const (
preferredPIELoadAddr usermem.Addr = maxAddr64 / 6 * 5
)
var (
// CPUIDInstruction doesn't exist on ARM64.
CPUIDInstruction = []byte{}
)
// These constants are selected as heuristics to help make the Platform's
// potentially limited address space conform as closely to Linux as possible.
const (

View File

@ -126,13 +126,39 @@ func (t *Task) doStop() {
}
}
func (*runApp) handleCPUIDInstruction(t *Task) error {
if len(arch.CPUIDInstruction) == 0 {
// CPUID emulation isn't supported, but this code can be
// executed, because the ptrace platform returns
// ErrContextSignalCPUID on page faults too. Look at
// pkg/sentry/platform/ptrace/ptrace.go:context.Switch for more
// details.
return platform.ErrContextSignal
}
// Is this a CPUID instruction?
region := trace.StartRegion(t.traceContext, cpuidRegion)
expected := arch.CPUIDInstruction[:]
found := make([]byte, len(expected))
_, err := t.CopyIn(usermem.Addr(t.Arch().IP()), &found)
if err == nil && bytes.Equal(expected, found) {
// Skip the cpuid instruction.
t.Arch().CPUIDEmulate(t)
t.Arch().SetIP(t.Arch().IP() + uintptr(len(expected)))
region.End()
return nil
}
region.End() // Not an actual CPUID, but required copy-in.
return platform.ErrContextSignal
}
// The runApp state checks for interrupts before executing untrusted
// application code.
//
// +stateify savable
type runApp struct{}
func (*runApp) execute(t *Task) taskRunState {
func (app *runApp) execute(t *Task) taskRunState {
if t.interrupted() {
// Checkpointing instructs tasks to stop by sending an interrupt, so we
// must check for stops before entering runInterrupt (instead of
@ -237,21 +263,10 @@ func (*runApp) execute(t *Task) taskRunState {
return (*runApp)(nil)
case platform.ErrContextSignalCPUID:
// Is this a CPUID instruction?
region := trace.StartRegion(t.traceContext, cpuidRegion)
expected := arch.CPUIDInstruction[:]
found := make([]byte, len(expected))
_, err := t.CopyIn(usermem.Addr(t.Arch().IP()), &found)
if err == nil && bytes.Equal(expected, found) {
// Skip the cpuid instruction.
t.Arch().CPUIDEmulate(t)
t.Arch().SetIP(t.Arch().IP() + uintptr(len(expected)))
region.End()
if err := app.handleCPUIDInstruction(t); err == nil {
// Resume execution.
return (*runApp)(nil)
}
region.End() // Not an actual CPUID, but required copy-in.
// The instruction at the given RIP was not a CPUID, and we
// fallthrough to the default signal deliver behavior below.