Skip to content

Commit

Permalink
Refactor nogo and provide facts render.
Browse files Browse the repository at this point in the history
This change makes the core nogo package less of a "catch all", and splits
functionality into multiple packages. Instead of separate binaries for each
function, a single "cli" package is added with subcommands, and the core
starlark wrappers are also refactored to minimize redundancy.

The new "cli" package also adds support for a "render" command, which
allows factors to be rendered via a Go text template. This is useful for
debugging, but also allows code generation to be updated to use this
mechanism. This eliminates the use of a QEMU wrapper for the older
arch_genrule, and allows the use of a native bazel transition to extract
facts for the appropriate generated file. In other words, the correct facts
will be rendered for generating XXX_arm64.s, even on amd64.

PiperOrigin-RevId: 422846459
  • Loading branch information
amscanne authored and gvisor-bot committed Jan 19, 2022
1 parent 3d578af commit 0e492a2
Show file tree
Hide file tree
Showing 51 changed files with 3,228 additions and 2,205 deletions.
2 changes: 1 addition & 1 deletion BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ doc(
yaml_test(
name = "nogo_config_test",
srcs = glob(["nogo*.yaml"]),
schema = "//tools/nogo:config-schema.json",
schema = "//tools/nogo/config:schema.json",
)

yaml_test(
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ nogo-tests:
# For unit tests, we take everything in the root, pkg/... and tools/..., and
# pull in all directories in runsc except runsc/container.
unit-tests: ## Local package unit tests in pkg/..., tools/.., etc.
@$(call test,--build_tag_filters=-nogo --test_tag_filters=-nogo --test_filter=-//runsc/container/... //:all pkg/... tools/... runsc/...)
@$(call test,--build_tag_filters=-nogo --test_tag_filters=-nogo --test_filter=-//runsc/container/... //:all pkg/... tools/... runsc/... vdso/...)
.PHONY: unit-tests

# See unit-tests: this includes runsc/container.
Expand Down
9 changes: 0 additions & 9 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ http_archive(
name = "io_bazel_rules_go",
patch_args = ["-p1"],
patches = [
# Ensure we don't destroy the facts visibility.
"//tools:rules_go_visibility.patch",
# Newer versions of the rules_go rules will automatically strip test
# binaries of symbols, which we don't want.
"//tools:rules_go_symbols.patch",
Expand All @@ -51,13 +49,6 @@ http_archive(

http_archive(
name = "bazel_gazelle",
patch_args = ["-p1"],
patches = [
# Fix permissions for facts for go_library, not just tool library.
# This is actually a no-op with the hacky patch above, but should
# slightly future proof this mechanism.
"//tools:bazel_gazelle_generate.patch",
],
sha256 = "62ca106be173579c0a167deb23358fdfe71ffa1e4cfdddf5582af26520f1c66f",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
Expand Down
79 changes: 30 additions & 49 deletions pkg/ring0/BUILD
Original file line number Diff line number Diff line change
@@ -1,69 +1,50 @@
load("//tools:defs.bzl", "arch_genrule", "go_library")
load("//tools/go_generics:defs.bzl", "go_template", "go_template_instance")
load("//tools:defs.bzl", "arch_genrule", "go_library", "select_arch")
load("//tools/nogo:defs.bzl", "nogo_facts")

package(licenses = ["notice"])

go_template(
name = "defs_amd64",
srcs = [
"defs.go",
"defs_amd64.go",
"offsets_amd64.go",
"x86.go",
],
visibility = [":__subpackages__"],
)
exports_files(glob(["*.go"]))

go_template(
name = "defs_arm64",
nogo_facts(
name = "entry_impl",
srcs = [
"aarch64.go",
"defs.go",
"defs_amd64.go",
"defs_arm64.go",
"offsets_arm64.go",
"entry_template.go",
"x86.go",
],
output = "entry_impl.s",
template = select_arch(
amd64 = "entry_amd64.s",
arm64 = "entry_arm64.s",
),
deps = [
"//pkg/abi/linux",
"//pkg/cpuid",
"//pkg/hostarch",
"//pkg/ring0/pagetables",
"//pkg/sentry/arch",
"//pkg/sentry/arch/fpu",
],
visibility = [":__subpackages__"],
)

go_template_instance(
name = "defs_impl_amd64",
out = "defs_impl_amd64.go",
package = "ring0",
template = ":defs_amd64",
)

go_template_instance(
name = "defs_impl_arm64",
out = "defs_impl_arm64.go",
package = "ring0",
template = ":defs_arm64",
)

arch_genrule(
name = "entry_impl_amd64",
srcs = ["entry_amd64.s"],
outs = ["entry_impl_amd64.s"],
cmd = "(echo -e '// build +amd64\\n' && QEMU $(location //pkg/ring0/gen_offsets) && cat $(location entry_amd64.s)) > $@",
tools = ["//pkg/ring0/gen_offsets"],
)

arch_genrule(
name = "entry_impl_arm64",
srcs = ["entry_arm64.s"],
outs = ["entry_impl_arm64.s"],
cmd = "(echo -e '// build +arm64\\n' && QEMU $(location //pkg/ring0/gen_offsets) && cat $(location entry_arm64.s)) > $@",
tools = ["//pkg/ring0/gen_offsets"],
name = "entry_impl_arch",
src = ":entry_impl",
template = "entry_impl_%s.s",
)

go_library(
name = "ring0",
srcs = [
"defs_impl_amd64.go",
"defs_impl_arm64.go",
"aarch64.go",
"defs.go",
"defs_amd64.go",
"defs_arm64.go",
"entry_amd64.go",
"entry_arm64.go",
"entry_impl_amd64.s",
"entry_impl_arm64.s",
"kernel.go",
"kernel_amd64.go",
"kernel_arm64.go",
Expand All @@ -73,15 +54,15 @@ go_library(
"lib_arm64.go",
"lib_arm64.s",
"ring0.go",
"x86.go",
":entry_impl_arch",
],
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/cpuid",
"//pkg/hostarch",
"//pkg/ring0/pagetables",
"//pkg/safecopy",
"//pkg/sentry/arch",
"//pkg/sentry/arch/fpu",
"//pkg/sync",
],
)
3 changes: 0 additions & 3 deletions pkg/ring0/defs_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,3 @@ type SwitchArchOpts struct {
// KernelASID indicates that the kernel ASID to be used on return,
KernelASID uint16
}

func init() {
}
74 changes: 71 additions & 3 deletions pkg/ring0/entry_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,77 @@
#include "funcdata.h"
#include "textflag.h"

// NB: Offsets are programmatically generated (see BUILD).
//
// This file is concatenated with the definitions.
// CPU offsets.
#define CPU_REGISTERS {{ .CPU.registers.Offset }}
#define CPU_FPU_STATE {{ .CPU.floatingPointState.Offset }}
#define CPU_ERROR_CODE ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.errorCode.Offset }})
#define CPU_ERROR_TYPE ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.errorType.Offset }})
#define CPU_ENTRY ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.kernelEntry.Offset }})
#define CPU_HAS_XSAVE ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.hasXSAVE.Offset }})
#define CPU_HAS_XSAVEOPT ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.hasXSAVEOPT.Offset }})

{{ with .kernelEntry }}
#define ENTRY_SCRATCH0 {{ .scratch0.Offset }}
#define ENTRY_STACK_TOP {{ .stackTop.Offset }}
#define ENTRY_CPU_SELF {{ .cpuSelf.Offset }}
#define ENTRY_KERNEL_CR3 {{ .kernelCR3.Offset }}
{{ end }}

// Bits.
#define _RFLAGS_IF {{ ._RFLAGS_IF.Value }}
#define _RFLAGS_IOPL0 {{ ._RFLAGS_IOPL0.Value }}
#define _KERNEL_FLAGS {{ .KernelFlagsSet.Value }}

// Vectors.
#define DivideByZero {{ .DivideByZero.Value }}
#define Debug {{ .Debug.Value }}
#define NMI {{ .NMI.Value }}
#define Breakpoint {{ .Breakpoint.Value }}
#define Overflow {{ .Overflow.Value }}
#define BoundRangeExceeded {{ .BoundRangeExceeded.Value }}
#define InvalidOpcode {{ .InvalidOpcode.Value }}
#define DeviceNotAvailable {{ .DeviceNotAvailable.Value }}
#define DoubleFault {{ .DoubleFault.Value }}
#define CoprocessorSegmentOverrun {{ .CoprocessorSegmentOverrun.Value }}
#define InvalidTSS {{ .InvalidTSS.Value }}
#define SegmentNotPresent {{ .SegmentNotPresent.Value }}
#define StackSegmentFault {{ .StackSegmentFault.Value }}
#define GeneralProtectionFault {{ .GeneralProtectionFault.Value }}
#define PageFault {{ .PageFault.Value }}
#define X87FloatingPointException {{ .X87FloatingPointException.Value }}
#define AlignmentCheck {{ .AlignmentCheck.Value }}
#define MachineCheck {{ .MachineCheck.Value }}
#define SIMDFloatingPointException {{ .SIMDFloatingPointException.Value }}
#define VirtualizationException {{ .VirtualizationException.Value }}
#define SecurityException {{ .SecurityException.Value }}
#define SyscallInt80 {{ .SyscallInt80.Value }}
#define Syscall {{ .Syscall.Value }}

{{ with .import.linux.PtraceRegs }}
#define PTRACE_R15 {{ .R15.Offset }}
#define PTRACE_R14 {{ .R14.Offset }}
#define PTRACE_R13 {{ .R13.Offset }}
#define PTRACE_R12 {{ .R12.Offset }}
#define PTRACE_RBP {{ .Rbp.Offset }}
#define PTRACE_RBX {{ .Rbx.Offset }}
#define PTRACE_R11 {{ .R11.Offset }}
#define PTRACE_R10 {{ .R10.Offset }}
#define PTRACE_R9 {{ .R9.Offset }}
#define PTRACE_R8 {{ .R8.Offset }}
#define PTRACE_RAX {{ .Rax.Offset }}
#define PTRACE_RCX {{ .Rcx.Offset }}
#define PTRACE_RDX {{ .Rdx.Offset }}
#define PTRACE_RSI {{ .Rsi.Offset }}
#define PTRACE_RDI {{ .Rdi.Offset }}
#define PTRACE_ORIGRAX {{ .Orig_rax.Offset }}
#define PTRACE_RIP {{ .Rip.Offset }}
#define PTRACE_CS {{ .Cs.Offset }}
#define PTRACE_FLAGS {{ .Eflags.Offset }}
#define PTRACE_RSP {{ .Rsp.Offset }}
#define PTRACE_SS {{ .Ss.Offset }}
#define PTRACE_FS_BASE {{ .Fs_base.Offset }}
#define PTRACE_GS_BASE {{ .Gs_base.Offset }}
{{ end }}

// Saves a register set.
//
Expand Down
95 changes: 92 additions & 3 deletions pkg/ring0/entry_arm64.s
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,98 @@
#include "funcdata.h"
#include "textflag.h"

// NB: Offsets are programatically generated (see BUILD).
//
// This file is concatenated with the definitions.
{{ with .CPU }}
#define CPU_SELF {{ .self.Offset }}
#define CPU_REGISTERS {{ .registers.Offset }}
{{ end }}
{{ with .CPUArchState }}
#define CPU_STACK_TOP ({{ .stack.Offset }} + {{ .stack.Size }})
#define CPU_ERROR_CODE {{ .errorCode.Offset }}
#define CPU_ERROR_TYPE {{ .errorType.Offset }}
#define CPU_FAULT_ADDR {{ .faultAddr.Offset }}
#define CPU_FPSTATE_EL0 {{ .el0Fp.Offset }}
#define CPU_TTBR0_KVM {{ .ttbr0Kvm.Offset }}
#define CPU_TTBR0_APP {{ .ttbr0App.Offset }}
#define CPU_VECTOR_CODE {{ .vecCode.Offset }}
#define CPU_APP_ADDR {{ .appAddr.Offset }}
#define CPU_LAZY_VFP {{ .lazyVFP.Offset }}
#define CPU_APP_ASID {{ .appASID.Offset }}
{{ end }}

// Bits.
#define _KERNEL_FLAGS {{ .KernelFlagsSet.Value }}

// Vectors.
#define El1Sync {{ .El1Sync.Value }}
#define El1Irq {{ .El1Irq.Value }}
#define El1Fiq {{ .El1Fiq.Value }}
#define El1Err {{ .El1Err.Value }}
#define El0Sync {{ .El0Sync.Value }}
#define El0Irq {{ .El0Irq.Value }}
#define El0Fiq {{ .El0Fiq.Value }}
#define El0Err {{ .El0Err.Value }}
#define El1SyncDa {{ .El1SyncDa.Value }}
#define El1SyncIa {{ .El1SyncIa.Value }}
#define El1SyncSpPc {{ .El1SyncSpPc.Value }}
#define El1SyncUndef {{ .El1SyncUndef.Value }}
#define El1SyncDbg {{ .El1SyncDbg.Value }}
#define El1SyncInv {{ .El1SyncInv.Value }}
#define El0SyncSVC {{ .El0SyncSVC.Value }}
#define El0SyncDa {{ .El0SyncDa.Value }}
#define El0SyncIa {{ .El0SyncIa.Value }}
#define El0SyncFpsimdAcc {{ .El0SyncFpsimdAcc.Value }}
#define El0SyncSveAcc {{ .El0SyncSveAcc.Value }}
#define El0SyncFpsimdExc {{ .El0SyncFpsimdExc.Value }}
#define El0SyncSys {{ .El0SyncSys.Value }}
#define El0SyncSpPc {{ .El0SyncSpPc.Value }}
#define El0SyncUndef {{ .El0SyncUndef.Value }}
#define El0SyncDbg {{ .El0SyncDbg.Value }}
#define El0SyncWfx {{ .El0SyncWfx.Value }}
#define El0SyncInv {{ .El0SyncInv.Value }}
#define El0ErrNMI {{ .El0ErrNMI.Value }}
#define PageFault {{ .PageFault.Value }}
#define Syscall {{ .Syscall.Value }}
#define VirtualizationException {{ .VirtualizationException.Value }}

{{ with .import.linux.PtraceRegs }}
#define PTRACE_R0 ({{ .Regs.Offset }} + 0*8)
#define PTRACE_R1 ({{ .Regs.Offset }} + 1*8)
#define PTRACE_R2 ({{ .Regs.Offset }} + 2*8)
#define PTRACE_R3 ({{ .Regs.Offset }} + 3*8)
#define PTRACE_R4 ({{ .Regs.Offset }} + 4*8)
#define PTRACE_R5 ({{ .Regs.Offset }} + 5*8)
#define PTRACE_R6 ({{ .Regs.Offset }} + 6*8)
#define PTRACE_R7 ({{ .Regs.Offset }} + 7*8)
#define PTRACE_R8 ({{ .Regs.Offset }} + 8*8)
#define PTRACE_R9 ({{ .Regs.Offset }} + 9*8)
#define PTRACE_R10 ({{ .Regs.Offset }} + 10*8)
#define PTRACE_R11 ({{ .Regs.Offset }} + 11*8)
#define PTRACE_R12 ({{ .Regs.Offset }} + 12*8)
#define PTRACE_R13 ({{ .Regs.Offset }} + 13*8)
#define PTRACE_R14 ({{ .Regs.Offset }} + 14*8)
#define PTRACE_R15 ({{ .Regs.Offset }} + 15*8)
#define PTRACE_R16 ({{ .Regs.Offset }} + 16*8)
#define PTRACE_R17 ({{ .Regs.Offset }} + 17*8)
#define PTRACE_R18 ({{ .Regs.Offset }} + 18*8)
#define PTRACE_R19 ({{ .Regs.Offset }} + 19*8)
#define PTRACE_R20 ({{ .Regs.Offset }} + 20*8)
#define PTRACE_R21 ({{ .Regs.Offset }} + 21*8)
#define PTRACE_R22 ({{ .Regs.Offset }} + 22*8)
#define PTRACE_R23 ({{ .Regs.Offset }} + 23*8)
#define PTRACE_R24 ({{ .Regs.Offset }} + 24*8)
#define PTRACE_R25 ({{ .Regs.Offset }} + 25*8)
#define PTRACE_R26 ({{ .Regs.Offset }} + 26*8)
#define PTRACE_R27 ({{ .Regs.Offset }} + 27*8)
#define PTRACE_R28 ({{ .Regs.Offset }} + 28*8)
#define PTRACE_R29 ({{ .Regs.Offset }} + 29*8)
#define PTRACE_R30 ({{ .Regs.Offset }} + 30*8)
#define PTRACE_SP {{ .Sp.Offset }}
#define PTRACE_PC {{ .Pc.Offset }}
#define PTRACE_PSTATE {{ .Pstate.Offset }}
{{ end }}
{{ with .import.arch.Registers }}
#define PTRACE_TLS {{ .TPIDR_EL0.Offset }}
{{ end }}

// Saves a register set.
//
Expand Down
10 changes: 3 additions & 7 deletions pkg/ring0/gen_offsets/main.go → pkg/ring0/entry_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Binary gen_offsets is a helper for generating offset headers.
package main
package ring0

import (
"os"
// Used for template generation.
_ "gvisor.dev/gvisor/pkg/abi/linux"
)

func main() {
Emit(os.Stdout)
}
Loading

0 comments on commit 0e492a2

Please sign in to comment.