Merge pull request #918 from lubinszARM:pr_ring0

PiperOrigin-RevId: 279840214
This commit is contained in:
gVisor bot
2019-11-11 16:15:12 -08:00
11 changed files with 1133 additions and 20 deletions
+36 -5
View File
@@ -4,7 +4,7 @@ load("//tools/go_generics:defs.bzl", "go_template", "go_template_instance")
package(licenses = ["notice"])
go_template(
name = "defs",
name = "defs_amd64",
srcs = [
"defs.go",
"defs_amd64.go",
@@ -14,11 +14,29 @@ go_template(
visibility = [":__subpackages__"],
)
go_template(
name = "defs_arm64",
srcs = [
"aarch64.go",
"defs.go",
"defs_arm64.go",
"offsets_arm64.go",
],
visibility = [":__subpackages__"],
)
go_template_instance(
name = "defs_impl",
out = "defs_impl.go",
name = "defs_impl_amd64",
out = "defs_impl_amd64.go",
package = "ring0",
template = ":defs",
template = ":defs_amd64",
)
go_template_instance(
name = "defs_impl_arm64",
out = "defs_impl_arm64.go",
package = "ring0",
template = ":defs_arm64",
)
genrule(
@@ -29,17 +47,30 @@ genrule(
tools = ["//pkg/sentry/platform/ring0/gen_offsets"],
)
genrule(
name = "entry_impl_arm64",
srcs = ["entry_arm64.s"],
outs = ["entry_impl_arm64.s"],
cmd = "(echo -e '// build +arm64\\n' && $(location //pkg/sentry/platform/ring0/gen_offsets) && cat $(SRCS)) > $@",
tools = ["//pkg/sentry/platform/ring0/gen_offsets"],
)
go_library(
name = "ring0",
srcs = [
"defs_impl.go",
"defs_impl_amd64.go",
"defs_impl_arm64.go",
"entry_amd64.go",
"entry_arm64.go",
"entry_impl_amd64.s",
"entry_impl_arm64.s",
"kernel.go",
"kernel_amd64.go",
"kernel_arm64.go",
"kernel_unsafe.go",
"lib_amd64.go",
"lib_amd64.s",
"lib_arm64.go",
"ring0.go",
],
importpath = "gvisor.dev/gvisor/pkg/sentry/platform/ring0",
+109
View File
@@ -0,0 +1,109 @@
// Copyright 2019 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.
// +build arm64
package ring0
// Useful bits.
const (
_PGD_PGT_BASE = 0x1000
_PGD_PGT_SIZE = 0x1000
_PUD_PGT_BASE = 0x2000
_PUD_PGT_SIZE = 0x1000
_PMD_PGT_BASE = 0x3000
_PMD_PGT_SIZE = 0x4000
_PTE_PGT_BASE = 0x7000
_PTE_PGT_SIZE = 0x1000
_PSR_MODE_EL0t = 0x0
_PSR_MODE_EL1t = 0x4
_PSR_MODE_EL1h = 0x5
_PSR_EL_MASK = 0xf
_PSR_D_BIT = 0x200
_PSR_A_BIT = 0x100
_PSR_I_BIT = 0x80
_PSR_F_BIT = 0x40
)
const (
// KernelFlagsSet should always be set in the kernel.
KernelFlagsSet = _PSR_MODE_EL1h
// UserFlagsSet are always set in userspace.
UserFlagsSet = _PSR_MODE_EL0t
KernelFlagsClear = _PSR_EL_MASK
UserFlagsClear = _PSR_EL_MASK
PsrDefaultSet = _PSR_D_BIT | _PSR_A_BIT | _PSR_I_BIT | _PSR_F_BIT
)
// Vector is an exception vector.
type Vector uintptr
// Exception vectors.
const (
El1SyncInvalid = iota
El1IrqInvalid
El1FiqInvalid
El1ErrorInvalid
El1Sync
El1Irq
El1Fiq
El1Error
El0Sync
El0Irq
El0Fiq
El0Error
El0Sync_invalid
El0Irq_invalid
El0Fiq_invalid
El0Error_invalid
El1Sync_da
El1Sync_ia
El1Sync_sp_pc
El1Sync_undef
El1Sync_dbg
El1Sync_inv
El0Sync_svc
El0Sync_da
El0Sync_ia
El0Sync_fpsimd_acc
El0Sync_sve_acc
El0Sync_sys
El0Sync_sp_pc
El0Sync_undef
El0Sync_dbg
El0Sync_inv
VirtualizationException
_NR_INTERRUPTS
)
// System call vectors.
const (
Syscall Vector = El0Sync_svc
PageFault Vector = El0Sync_da
)
// VirtualAddressBits returns the number bits available for virtual addresses.
func VirtualAddressBits() uint32 {
return 48
}
// PhysicalAddressBits returns the number of bits available for physical addresses.
func PhysicalAddressBits() uint32 {
return 40
}
-11
View File
@@ -20,17 +20,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/usermem"
)
var (
// UserspaceSize is the total size of userspace.
UserspaceSize = uintptr(1) << (VirtualAddressBits() - 1)
// MaximumUserAddress is the largest possible user address.
MaximumUserAddress = (UserspaceSize - 1) & ^uintptr(usermem.PageSize-1)
// KernelStartAddress is the starting kernel address.
KernelStartAddress = ^uintptr(0) - (UserspaceSize - 1)
)
// Kernel is a global kernel object.
//
// This contains global state, shared by multiple CPUs.
+11
View File
@@ -20,6 +20,17 @@ import (
"gvisor.dev/gvisor/pkg/sentry/platform/ring0/pagetables"
)
var (
// UserspaceSize is the total size of userspace.
UserspaceSize = uintptr(1) << (VirtualAddressBits() - 1)
// MaximumUserAddress is the largest possible user address.
MaximumUserAddress = (UserspaceSize - 1) & ^uintptr(usermem.PageSize-1)
// KernelStartAddress is the starting kernel address.
KernelStartAddress = ^uintptr(0) - (UserspaceSize - 1)
)
// Segment indices and Selectors.
const (
// Index into GDT array.
+133
View File
@@ -0,0 +1,133 @@
// Copyright 2019 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.
// +build arm64
package ring0
import (
"gvisor.dev/gvisor/pkg/sentry/platform/ring0/pagetables"
)
var (
// UserspaceSize is the total size of userspace.
UserspaceSize = uintptr(1) << (VirtualAddressBits())
// MaximumUserAddress is the largest possible user address.
MaximumUserAddress = (UserspaceSize - 1) & ^uintptr(usermem.PageSize-1)
// KernelStartAddress is the starting kernel address.
KernelStartAddress = ^uintptr(0) - (UserspaceSize - 1)
)
// KernelOpts has initialization options for the kernel.
type KernelOpts struct {
// PageTables are the kernel pagetables; this must be provided.
PageTables *pagetables.PageTables
}
// KernelArchState contains architecture-specific state.
type KernelArchState struct {
KernelOpts
}
// CPUArchState contains CPU-specific arch state.
type CPUArchState struct {
// stack is the stack used for interrupts on this CPU.
stack [512]byte
// errorCode is the error code from the last exception.
errorCode uintptr
// errorType indicates the type of error code here, it is always set
// along with the errorCode value above.
//
// It will either by 1, which indicates a user error, or 0 indicating a
// kernel error. If the error code below returns false (kernel error),
// then it cannot provide relevant information about the last
// exception.
errorType uintptr
// faultAddr is the value of far_el1.
faultAddr uintptr
// ttbr0Kvm is the value of ttbr0_el1 for sentry.
ttbr0Kvm uintptr
// ttbr0App is the value of ttbr0_el1 for applicaton.
ttbr0App uintptr
// exception vector.
vecCode Vector
// application context pointer.
appAddr uintptr
}
// ErrorCode returns the last error code.
//
// The returned boolean indicates whether the error code corresponds to the
// last user error or not. If it does not, then fault information must be
// ignored. This is generally the result of a kernel fault while servicing a
// user fault.
//
//go:nosplit
func (c *CPU) ErrorCode() (value uintptr, user bool) {
return c.errorCode, c.errorType != 0
}
// ClearErrorCode resets the error code.
//
//go:nosplit
func (c *CPU) ClearErrorCode() {
c.errorCode = 0 // No code.
c.errorType = 1 // User mode.
}
//go:nosplit
func (c *CPU) GetFaultAddr() (value uintptr) {
return c.faultAddr
}
//go:nosplit
func (c *CPU) SetTtbr0Kvm(value uintptr) {
c.ttbr0Kvm = value
}
//go:nosplit
func (c *CPU) SetTtbr0App(value uintptr) {
c.ttbr0App = value
}
//go:nosplit
func (c *CPU) GetVector() (value Vector) {
return c.vecCode
}
//go:nosplit
func (c *CPU) SetAppAddr(value uintptr) {
c.appAddr = value
}
// SwitchArchOpts are embedded in SwitchOpts.
type SwitchArchOpts struct {
// UserASID indicates that the application ASID to be used on switch,
UserASID uint16
// KernelASID indicates that the kernel ASID to be used on return,
KernelASID uint16
}
func init() {
}
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2019 Google Inc.
//
// 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.
// +build arm64
package ring0
// This is an assembly function.
//
// The sysenter function is invoked in two situations:
//
// (1) The guest kernel has executed a system call.
// (2) The guest application has executed a system call.
//
// The interrupt flag is examined to determine whether the system call was
// executed from kernel mode or not and the appropriate stub is called.
func El1_sync_invalid()
func El1_irq_invalid()
func El1_fiq_invalid()
func El1_error_invalid()
func El1_sync()
func El1_irq()
func El1_fiq()
func El1_error()
func El0_sync()
func El0_irq()
func El0_fiq()
func El0_error()
func El0_sync_invalid()
func El0_irq_invalid()
func El0_fiq_invalid()
func El0_error_invalid()
func Vectors()
// Start is the CPU entrypoint.
//
// The CPU state will be set to c.Registers().
func Start()
func kernelExitToEl1()
func kernelExitToEl0()
// Shutdown execution
func Shutdown()
File diff suppressed because it is too large Load Diff
+12 -4
View File
@@ -4,16 +4,24 @@ load("//tools/go_generics:defs.bzl", "go_template_instance")
package(licenses = ["notice"])
go_template_instance(
name = "defs_impl",
out = "defs_impl.go",
name = "defs_impl_arm64",
out = "defs_impl_arm64.go",
package = "main",
template = "//pkg/sentry/platform/ring0:defs",
template = "//pkg/sentry/platform/ring0:defs_arm64",
)
go_template_instance(
name = "defs_impl_amd64",
out = "defs_impl_amd64.go",
package = "main",
template = "//pkg/sentry/platform/ring0:defs_amd64",
)
go_binary(
name = "gen_offsets",
srcs = [
"defs_impl.go",
"defs_impl_amd64.go",
"defs_impl_arm64.go",
"main.go",
],
visibility = ["//pkg/sentry/platform/ring0:__pkg__"],
+58
View File
@@ -0,0 +1,58 @@
// Copyright 2019 Google Inc.
//
// 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.
// +build arm64
package ring0
// init initializes architecture-specific state.
func (k *Kernel) init(opts KernelOpts) {
// Save the root page tables.
k.PageTables = opts.PageTables
}
// init initializes architecture-specific state.
func (c *CPU) init() {
// Set the kernel stack pointer(virtual address).
c.registers.Sp = uint64(c.StackTop())
}
// StackTop returns the kernel's stack address.
//
//go:nosplit
func (c *CPU) StackTop() uint64 {
return uint64(kernelAddr(&c.stack[0])) + uint64(len(c.stack))
}
// IsCanonical indicates whether addr is canonical per the arm64 spec.
//
//go:nosplit
func IsCanonical(addr uint64) bool {
return addr <= 0x0000ffffffffffff || addr > 0xffff000000000000
}
//go:nosplit
func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
// Sanitize registers.
regs := switchOpts.Registers
regs.Pstate &= ^uint64(UserFlagsClear)
regs.Pstate |= UserFlagsSet
kernelExitToEl0()
vector = c.vecCode
// Perform the switch.
return
}
+25
View File
@@ -0,0 +1,25 @@
// Copyright 2019 Google Inc.
//
// 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.
// +build arm64
package ring0
// LoadFloatingPoint loads floating point state by the most efficient mechanism
// available (set by Init).
var LoadFloatingPoint func(*byte)
// SaveFloatingPoint saves floating point state by the most efficient mechanism
// available (set by Init).
var SaveFloatingPoint func(*byte)
+124
View File
@@ -0,0 +1,124 @@
// Copyright 2019 Google Inc.
//
// 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.
// +build arm64
package ring0
import (
"fmt"
"io"
"reflect"
"syscall"
)
// Emit prints architecture-specific offsets.
func Emit(w io.Writer) {
fmt.Fprintf(w, "// Automatically generated, do not edit.\n")
c := &CPU{}
fmt.Fprintf(w, "\n// CPU offsets.\n")
fmt.Fprintf(w, "#define CPU_SELF 0x%02x\n", reflect.ValueOf(&c.self).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_REGISTERS 0x%02x\n", reflect.ValueOf(&c.registers).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_STACK_TOP 0x%02x\n", reflect.ValueOf(&c.stack[0]).Pointer()-reflect.ValueOf(c).Pointer()+uintptr(len(c.stack)))
fmt.Fprintf(w, "#define CPU_ERROR_CODE 0x%02x\n", reflect.ValueOf(&c.errorCode).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_ERROR_TYPE 0x%02x\n", reflect.ValueOf(&c.errorType).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_FAULT_ADDR 0x%02x\n", reflect.ValueOf(&c.faultAddr).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_TTBR0_KVM 0x%02x\n", reflect.ValueOf(&c.ttbr0Kvm).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_TTBR0_APP 0x%02x\n", reflect.ValueOf(&c.ttbr0App).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_VECTOR_CODE 0x%02x\n", reflect.ValueOf(&c.vecCode).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "#define CPU_APP_ADDR 0x%02x\n", reflect.ValueOf(&c.appAddr).Pointer()-reflect.ValueOf(c).Pointer())
fmt.Fprintf(w, "\n// Bits.\n")
fmt.Fprintf(w, "#define _KERNEL_FLAGS 0x%02x\n", KernelFlagsSet)
fmt.Fprintf(w, "\n// Vectors.\n")
fmt.Fprintf(w, "#define El1SyncInvalid 0x%02x\n", El1SyncInvalid)
fmt.Fprintf(w, "#define El1IrqInvalid 0x%02x\n", El1IrqInvalid)
fmt.Fprintf(w, "#define El1FiqInvalid 0x%02x\n", El1FiqInvalid)
fmt.Fprintf(w, "#define El1ErrorInvalid 0x%02x\n", El1ErrorInvalid)
fmt.Fprintf(w, "#define El1Sync 0x%02x\n", El1Sync)
fmt.Fprintf(w, "#define El1Irq 0x%02x\n", El1Irq)
fmt.Fprintf(w, "#define El1Fiq 0x%02x\n", El1Fiq)
fmt.Fprintf(w, "#define El1Error 0x%02x\n", El1Error)
fmt.Fprintf(w, "#define El0Sync 0x%02x\n", El0Sync)
fmt.Fprintf(w, "#define El0Irq 0x%02x\n", El0Irq)
fmt.Fprintf(w, "#define El0Fiq 0x%02x\n", El0Fiq)
fmt.Fprintf(w, "#define El0Error 0x%02x\n", El0Error)
fmt.Fprintf(w, "#define El0Sync_invalid 0x%02x\n", El0Sync_invalid)
fmt.Fprintf(w, "#define El0Irq_invalid 0x%02x\n", El0Irq_invalid)
fmt.Fprintf(w, "#define El0Fiq_invalid 0x%02x\n", El0Fiq_invalid)
fmt.Fprintf(w, "#define El0Error_invalid 0x%02x\n", El0Error_invalid)
fmt.Fprintf(w, "#define El1Sync_da 0x%02x\n", El1Sync_da)
fmt.Fprintf(w, "#define El1Sync_ia 0x%02x\n", El1Sync_ia)
fmt.Fprintf(w, "#define El1Sync_sp_pc 0x%02x\n", El1Sync_sp_pc)
fmt.Fprintf(w, "#define El1Sync_undef 0x%02x\n", El1Sync_undef)
fmt.Fprintf(w, "#define El1Sync_dbg 0x%02x\n", El1Sync_dbg)
fmt.Fprintf(w, "#define El1Sync_inv 0x%02x\n", El1Sync_inv)
fmt.Fprintf(w, "#define El0Sync_svc 0x%02x\n", El0Sync_svc)
fmt.Fprintf(w, "#define El0Sync_da 0x%02x\n", El0Sync_da)
fmt.Fprintf(w, "#define El0Sync_ia 0x%02x\n", El0Sync_ia)
fmt.Fprintf(w, "#define El0Sync_fpsimd_acc 0x%02x\n", El0Sync_fpsimd_acc)
fmt.Fprintf(w, "#define El0Sync_sve_acc 0x%02x\n", El0Sync_sve_acc)
fmt.Fprintf(w, "#define El0Sync_sys 0x%02x\n", El0Sync_sys)
fmt.Fprintf(w, "#define El0Sync_sp_pc 0x%02x\n", El0Sync_sp_pc)
fmt.Fprintf(w, "#define El0Sync_undef 0x%02x\n", El0Sync_undef)
fmt.Fprintf(w, "#define El0Sync_dbg 0x%02x\n", El0Sync_dbg)
fmt.Fprintf(w, "#define El0Sync_inv 0x%02x\n", El0Sync_inv)
fmt.Fprintf(w, "#define PageFault 0x%02x\n", PageFault)
fmt.Fprintf(w, "#define Syscall 0x%02x\n", Syscall)
p := &syscall.PtraceRegs{}
fmt.Fprintf(w, "\n// Ptrace registers.\n")
fmt.Fprintf(w, "#define PTRACE_R0 0x%02x\n", reflect.ValueOf(&p.Regs[0]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R1 0x%02x\n", reflect.ValueOf(&p.Regs[1]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R2 0x%02x\n", reflect.ValueOf(&p.Regs[2]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R3 0x%02x\n", reflect.ValueOf(&p.Regs[3]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R4 0x%02x\n", reflect.ValueOf(&p.Regs[4]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R5 0x%02x\n", reflect.ValueOf(&p.Regs[5]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R6 0x%02x\n", reflect.ValueOf(&p.Regs[6]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R7 0x%02x\n", reflect.ValueOf(&p.Regs[7]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R8 0x%02x\n", reflect.ValueOf(&p.Regs[8]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R9 0x%02x\n", reflect.ValueOf(&p.Regs[9]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R10 0x%02x\n", reflect.ValueOf(&p.Regs[10]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R11 0x%02x\n", reflect.ValueOf(&p.Regs[11]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R12 0x%02x\n", reflect.ValueOf(&p.Regs[12]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R13 0x%02x\n", reflect.ValueOf(&p.Regs[13]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R14 0x%02x\n", reflect.ValueOf(&p.Regs[14]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R15 0x%02x\n", reflect.ValueOf(&p.Regs[15]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R16 0x%02x\n", reflect.ValueOf(&p.Regs[16]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R17 0x%02x\n", reflect.ValueOf(&p.Regs[17]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R18 0x%02x\n", reflect.ValueOf(&p.Regs[18]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R19 0x%02x\n", reflect.ValueOf(&p.Regs[19]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R20 0x%02x\n", reflect.ValueOf(&p.Regs[20]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R21 0x%02x\n", reflect.ValueOf(&p.Regs[21]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R22 0x%02x\n", reflect.ValueOf(&p.Regs[22]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R23 0x%02x\n", reflect.ValueOf(&p.Regs[23]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R24 0x%02x\n", reflect.ValueOf(&p.Regs[24]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R25 0x%02x\n", reflect.ValueOf(&p.Regs[25]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R26 0x%02x\n", reflect.ValueOf(&p.Regs[26]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R27 0x%02x\n", reflect.ValueOf(&p.Regs[27]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R28 0x%02x\n", reflect.ValueOf(&p.Regs[28]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R29 0x%02x\n", reflect.ValueOf(&p.Regs[29]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_R30 0x%02x\n", reflect.ValueOf(&p.Regs[30]).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_SP 0x%02x\n", reflect.ValueOf(&p.Sp).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_PC 0x%02x\n", reflect.ValueOf(&p.Pc).Pointer()-reflect.ValueOf(p).Pointer())
fmt.Fprintf(w, "#define PTRACE_PSTATE 0x%02x\n", reflect.ValueOf(&p.Pstate).Pointer()-reflect.ValueOf(p).Pointer())
}