mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
kvm: reduce stack usage
Debug build functions use more stack space than normal, such that the KVM-nosplit function call chain doesn't fit. This patch replaces calls into unix.RawSyscall* functions with variants that do not grow the stack, and inlines some functions in ring0/pagetables in order to reduce stack usage. Additionally seccompMmapHandler is not used during debug builds anymore for making it fit into the nosplit stack size requirements. PiperOrigin-RevId: 679774881
This commit is contained in:
committed by
gVisor bot
parent
5e8dd6482c
commit
0760a3df59
@@ -114,7 +114,7 @@ type mapVisitor struct {
|
||||
//
|
||||
//go:nosplit
|
||||
func (v *mapVisitor) visit(start uintptr, pte *PTE, align uintptr) bool {
|
||||
p := v.physical + (start - uintptr(v.target))
|
||||
p := v.physical + (start - v.target)
|
||||
if pte.Valid() && (pte.Address() != p || pte.Opts() != v.opts) {
|
||||
v.prev = true
|
||||
}
|
||||
|
||||
@@ -158,14 +158,20 @@ func (p *PTE) IsSect() bool {
|
||||
//go:nosplit
|
||||
func (p *PTE) Set(addr uintptr, opts MapOpts) {
|
||||
v := (addr &^ optionMask) | nG | readOnly | protDefault
|
||||
if p.IsSect() {
|
||||
// Note: p.IsSect is manually inlined to reduce stack size for
|
||||
// nosplit-ness.
|
||||
isSect := atomic.LoadUintptr((*uintptr)(p))&pteTypeMask == typeSect
|
||||
if isSect {
|
||||
// Note that this is inherited from the previous instance. Set
|
||||
// does not change the value of Sect. See above.
|
||||
v |= typeSect
|
||||
} else {
|
||||
v |= typePage
|
||||
}
|
||||
if !opts.AccessType.Any() {
|
||||
// Note: AccessType.Any() is manually inlined to reduce stack size for
|
||||
// nosplit-ness.
|
||||
accessTypeAny := opts.AccessType.Read || opts.AccessType.Write || opts.AccessType.Execute
|
||||
if !accessTypeAny {
|
||||
// Leave as non-valid if no access is available.
|
||||
v &^= pteValid
|
||||
}
|
||||
|
||||
@@ -113,6 +113,8 @@ func isKillProcessAvailable() (bool, error) {
|
||||
//
|
||||
//go:nosplit
|
||||
func seccomp(op, flags uint32, ptr unsafe.Pointer) (uintptr, unix.Errno) {
|
||||
n, _, errno := unix.RawSyscall(SYS_SECCOMP, uintptr(op), uintptr(flags), uintptr(ptr))
|
||||
// Note: Usage of RawSyscall6 over RawSyscall is intentional in order to
|
||||
// reduce stack-growth.
|
||||
n, _, errno := unix.RawSyscall6(SYS_SECCOMP, uintptr(op), uintptr(flags), uintptr(ptr), 0, 0, 0)
|
||||
return n, errno
|
||||
}
|
||||
|
||||
@@ -17,6 +17,30 @@ go_template_instance(
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "debug_build",
|
||||
values = {
|
||||
"compilation_mode": "dbg",
|
||||
},
|
||||
)
|
||||
|
||||
# @unused
|
||||
glaze_ignore = [
|
||||
"seccomp_mmap_dbg.go",
|
||||
"seccomp_mmap_real.go",
|
||||
]
|
||||
|
||||
# Use either seccomp_mmap_dbg.go or seccomp_mmap_real.go as seccomp_mmap.go.
|
||||
genrule(
|
||||
name = "seccomp_mmap",
|
||||
srcs = select({
|
||||
":debug_build": ["seccomp_mmap_dbg.go"],
|
||||
"//conditions:default": ["seccomp_mmap_real.go"],
|
||||
}),
|
||||
outs = ["seccomp_mmap_unsafe.go"],
|
||||
cmd = "cat < $(SRCS) > $(OUTS)",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "kvm",
|
||||
srcs = [
|
||||
@@ -57,6 +81,7 @@ go_library(
|
||||
"physical_map.go",
|
||||
"physical_map_amd64.go",
|
||||
"physical_map_arm64.go",
|
||||
"seccomp_mmap_unsafe.go",
|
||||
"virtual_map.go",
|
||||
],
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
|
||||
@@ -70,7 +70,7 @@ const _SYS_KVM_RETURN_TO_HOST = ^uintptr(0)
|
||||
//
|
||||
//go:nosplit
|
||||
func redpill() {
|
||||
unix.RawSyscall(_SYS_KVM_RETURN_TO_HOST, 0, 0, 0)
|
||||
kvmSyscallErrno(_SYS_KVM_RETURN_TO_HOST, 0, 0, 0)
|
||||
}
|
||||
|
||||
// dieHandler is called by dieTrampoline.
|
||||
|
||||
@@ -91,3 +91,38 @@ TEXT ·currentCPU(SB), $0-8
|
||||
MOVQ ENTRY_CPU_SELF(GS), AX
|
||||
MOVQ AX, ret+0(FP)
|
||||
RET
|
||||
|
||||
// func kvmSyscallErrno6(trap, a1, a2, a3, a4, a5, a6 uintptr) (ret unix.Errno)
|
||||
TEXT ·kvmSyscallErrno6(SB),NOSPLIT,$0-64
|
||||
MOVQ a1+8(FP), DI
|
||||
MOVQ a2+16(FP), SI
|
||||
MOVQ a3+24(FP), DX
|
||||
MOVQ a4+32(FP), R10
|
||||
MOVQ a5+40(FP), R8
|
||||
MOVQ a6+48(FP), R9
|
||||
MOVQ trap+0(FP), AX // syscall entry
|
||||
SYSCALL
|
||||
CMPQ AX, $0xfffffffffffff001
|
||||
JLS ok
|
||||
NEGQ AX
|
||||
MOVQ AX, ret+56(FP) // ret
|
||||
RET
|
||||
ok:
|
||||
MOVQ $0, ret+56(FP) // ret
|
||||
RET
|
||||
|
||||
// func kvmSyscallErrno(trap, a1, a2, a3 uintptr) (ret unix.Errno)
|
||||
TEXT ·kvmSyscallErrno(SB),NOSPLIT,$0-40
|
||||
MOVQ a1+8(FP), DI
|
||||
MOVQ a2+16(FP), SI
|
||||
MOVQ a3+24(FP), DX
|
||||
MOVQ trap+0(FP), AX // syscall entry
|
||||
SYSCALL
|
||||
CMPQ AX, $0xfffffffffffff001
|
||||
JLS ok
|
||||
NEGQ AX
|
||||
MOVQ AX, ret+32(FP) // ret
|
||||
RET
|
||||
ok:
|
||||
MOVQ $0, ret+32(FP) // ret
|
||||
RET
|
||||
|
||||
@@ -74,7 +74,7 @@ func getHypercallID(addr uintptr) int {
|
||||
func bluepillStopGuest(c *vCPU) {
|
||||
// Interrupt: we must have requested an interrupt
|
||||
// window; set the interrupt line.
|
||||
if _, _, errno := unix.RawSyscall(
|
||||
if errno := kvmSyscallErrno(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_INTERRUPT,
|
||||
@@ -89,7 +89,7 @@ func bluepillStopGuest(c *vCPU) {
|
||||
//
|
||||
//go:nosplit
|
||||
func bluepillSigBus(c *vCPU) {
|
||||
if _, _, errno := unix.RawSyscall( // escapes: no.
|
||||
if errno := kvmSyscallErrno(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_NMI, 0); errno != 0 {
|
||||
@@ -188,7 +188,6 @@ func bluepillUserHandler(frame uintptr) {
|
||||
sigframe.Sigreturn(c.bluepillSigframe)
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func (c *vCPU) initBluepillHandler() error {
|
||||
stackSize := uintptr(hostarch.PageSize)
|
||||
|
||||
|
||||
@@ -145,3 +145,38 @@ TEXT ·addrOfDieTrampoline(SB), $0-8
|
||||
MOVD $·dieTrampoline(SB), R0
|
||||
MOVD R0, ret+0(FP)
|
||||
RET
|
||||
|
||||
// func kvmSyscallErrno6(trap, a1, a2, a3, a4, a5, a6 uintptr) (errno unix.Errno)
|
||||
TEXT ·kvmSyscallErrno6(SB),NOSPLIT,$0-64
|
||||
MOVD trap+0(FP), R8 // syscall entry
|
||||
MOVD a1+8(FP), R0
|
||||
MOVD a2+16(FP), R1
|
||||
MOVD a3+24(FP), R2
|
||||
MOVD a4+32(FP), R3
|
||||
MOVD a5+40(FP), R4
|
||||
MOVD a6+48(FP), R5
|
||||
SVC
|
||||
CMN $4095, R0
|
||||
BCC ok
|
||||
NEG R0, R0
|
||||
MOVD R0, ret+56(FP)
|
||||
RET
|
||||
ok:
|
||||
MOVD $0, ret+56(FP)
|
||||
RET
|
||||
|
||||
// func kvmSyscallErrno(trap, a1, a2, a3 uintptr) (errno unix.Errno)
|
||||
TEXT ·kvmSyscallErrno(SB),NOSPLIT,$0-40
|
||||
MOVD trap+0(FP), R8 // syscall entry
|
||||
MOVD a1+8(FP), R0
|
||||
MOVD a2+16(FP), R1
|
||||
MOVD a3+24(FP), R2
|
||||
SVC
|
||||
CMN $4095, R0
|
||||
BCC ok
|
||||
NEG R0, R0
|
||||
MOVD R0, ret+32(FP)
|
||||
RET
|
||||
ok:
|
||||
MOVD ZR, ret+32(FP)
|
||||
RET
|
||||
|
||||
@@ -88,7 +88,7 @@ func bluepillStopGuest(c *vCPU) {
|
||||
},
|
||||
}
|
||||
|
||||
if _, _, errno := unix.RawSyscall( // escapes: no.
|
||||
if errno := kvmSyscallErrno( // escapes: no.
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_SET_VCPU_EVENTS,
|
||||
@@ -111,7 +111,7 @@ func bluepillSigBus(c *vCPU) {
|
||||
}
|
||||
|
||||
// Host must support ARM64_HAS_RAS_EXTN.
|
||||
if _, _, errno := unix.RawSyscall( // escapes: no.
|
||||
if errno := kvmSyscallErrno( // escapes: no.
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_SET_VCPU_EVENTS,
|
||||
@@ -134,7 +134,7 @@ func bluepillExtDabt(c *vCPU) {
|
||||
},
|
||||
}
|
||||
|
||||
if _, _, errno := unix.RawSyscall( // escapes: no.
|
||||
if errno := kvmSyscallErrno( // escapes: no.
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_SET_VCPU_EVENTS,
|
||||
|
||||
@@ -40,7 +40,7 @@ var (
|
||||
//
|
||||
//go:nosplit
|
||||
func yield() {
|
||||
unix.RawSyscall(unix.SYS_SCHED_YIELD, 0, 0, 0)
|
||||
kvmSyscallErrno(unix.SYS_SCHED_YIELD, 0, 0, 0)
|
||||
}
|
||||
|
||||
// calculateBluepillFault calculates the fault address range.
|
||||
|
||||
@@ -28,6 +28,14 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
)
|
||||
|
||||
// Local variants of unix.RawSyscall that use slightly less stack space.
|
||||
|
||||
// kvmSyscallErrno6 only returns errno, and 0 if successful.
|
||||
func kvmSyscallErrno6(trap, a1, a2, a3, a4, a5, a6 uintptr) unix.Errno
|
||||
|
||||
// kvmSyscallErrno only returns errno, and 0 if successful.
|
||||
func kvmSyscallErrno(trap, a1, a2, a3 uintptr) unix.Errno
|
||||
|
||||
//go:linkname throw runtime.throw
|
||||
func throw(s string)
|
||||
|
||||
@@ -91,8 +99,8 @@ func printHex(title []byte, val uint64) {
|
||||
}
|
||||
str[0] = ' '
|
||||
str[17] = '\n'
|
||||
unix.RawSyscall(unix.SYS_WRITE, uintptr(unix.Stderr), uintptr(unsafe.Pointer(&title[0])), uintptr(len(title)))
|
||||
unix.RawSyscall(unix.SYS_WRITE, uintptr(unix.Stderr), uintptr(unsafe.Pointer(&str)), 18)
|
||||
kvmSyscallErrno(unix.SYS_WRITE, uintptr(unix.Stderr), uintptr(unsafe.Pointer(&title[0])), uintptr(len(title)))
|
||||
kvmSyscallErrno(unix.SYS_WRITE, uintptr(unix.Stderr), uintptr(unsafe.Pointer(&str)), 18)
|
||||
}
|
||||
|
||||
// bluepillHandler is called from the signal stub.
|
||||
|
||||
@@ -132,7 +132,7 @@ func (c *vCPU) setTSC(value uint64) error {
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *vCPU) setUserRegisters(uregs *userRegs) unix.Errno {
|
||||
if _, _, errno := unix.RawSyscall(
|
||||
if errno := kvmSyscallErrno(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_SET_REGS,
|
||||
@@ -148,7 +148,7 @@ func (c *vCPU) setUserRegisters(uregs *userRegs) unix.Errno {
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *vCPU) getUserRegisters(uregs *userRegs) unix.Errno {
|
||||
if _, _, errno := unix.RawSyscall( // escapes: no.
|
||||
if errno := kvmSyscallErrno( // escapes: no.
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_GET_REGS,
|
||||
@@ -160,7 +160,7 @@ func (c *vCPU) getUserRegisters(uregs *userRegs) unix.Errno {
|
||||
|
||||
// setSystemRegisters sets system registers.
|
||||
func (c *vCPU) setSystemRegisters(sregs *systemRegs) error {
|
||||
if _, _, errno := unix.RawSyscall(
|
||||
if errno := kvmSyscallErrno(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_SET_SREGS,
|
||||
@@ -174,7 +174,7 @@ func (c *vCPU) setSystemRegisters(sregs *systemRegs) error {
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *vCPU) getSystemRegisters(sregs *systemRegs) unix.Errno {
|
||||
if _, _, errno := unix.RawSyscall(
|
||||
if errno := kvmSyscallErrno(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(c.fd),
|
||||
KVM_GET_SREGS,
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"math"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -56,8 +55,7 @@ func (m *machine) setMemoryRegion(slot int, physical, length, virtual uintptr, f
|
||||
}
|
||||
|
||||
// Set the region.
|
||||
// Note: syscall.RawSyscall is used to fit the nosplit stack limit.
|
||||
_, _, errno := syscall.RawSyscall(
|
||||
errno := kvmSyscallErrno(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(m.fd),
|
||||
KVM_SET_USER_MEMORY_REGION,
|
||||
@@ -121,7 +119,7 @@ func (a *atomicAddressSpace) get() *addressSpace {
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *vCPU) notify() {
|
||||
_, _, errno := unix.RawSyscall6( // escapes: no.
|
||||
errno := kvmSyscallErrno6( // escapes: no.
|
||||
unix.SYS_FUTEX,
|
||||
uintptr(unsafe.Pointer(&c.state)),
|
||||
linux.FUTEX_WAKE|linux.FUTEX_PRIVATE_FLAG,
|
||||
@@ -196,53 +194,6 @@ func seccompMmapSync() {
|
||||
}
|
||||
}
|
||||
|
||||
// seccompMmapHandler is a signal handler for runtime mmap system calls
|
||||
// that are trapped by seccomp.
|
||||
//
|
||||
// It executes the mmap syscall with specified arguments and maps a new region
|
||||
// to the guest.
|
||||
//
|
||||
//go:nosplit
|
||||
func seccompMmapHandler(context unsafe.Pointer) {
|
||||
mmapCallCounter.Increment()
|
||||
|
||||
addr, length, errno := seccompMmapSyscall(context)
|
||||
if errno != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
seccompMmapHandlerCnt.Add(1)
|
||||
for i := uint32(0); i < machinePoolLen.Load(); i++ {
|
||||
m := machinePool[i].Load()
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Map the new region to the guest.
|
||||
vr := region{
|
||||
virtual: addr,
|
||||
length: length,
|
||||
}
|
||||
for virtual := vr.virtual; virtual < vr.virtual+vr.length; {
|
||||
physical, length, ok := translateToPhysical(virtual)
|
||||
if !ok {
|
||||
// This must be an invalid region that was
|
||||
// knocked out by creation of the physical map.
|
||||
return
|
||||
}
|
||||
if virtual+length > vr.virtual+vr.length {
|
||||
// Cap the length to the end of the area.
|
||||
length = vr.virtual + vr.length - virtual
|
||||
}
|
||||
|
||||
// Ensure the physical range is mapped.
|
||||
m.mapPhysical(physical, length, physicalRegions)
|
||||
virtual += length
|
||||
}
|
||||
}
|
||||
seccompMmapHandlerCnt.Add(-1)
|
||||
}
|
||||
|
||||
// disableAsyncPreemption disables asynchronous preemption of go-routines.
|
||||
func disableAsyncPreemption() {
|
||||
set := linux.MakeSignalSet(linux.SIGURG)
|
||||
|
||||
+10
-11
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 The gVisor Authors.
|
||||
// Copyright 2024 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.
|
||||
@@ -12,17 +12,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build linux && debug
|
||||
// +build linux,debug
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package platforms
|
||||
package kvm
|
||||
|
||||
import (
|
||||
// Import platforms that runsc might use.
|
||||
|
||||
// The KVM platform is not included because it's incompatible with debug
|
||||
// builds. Unoptimized functions grow the stack too much and fail the nosplit
|
||||
// check.
|
||||
_ "gvisor.dev/gvisor/pkg/sentry/platform/ptrace"
|
||||
_ "gvisor.dev/gvisor/pkg/sentry/platform/systrap"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:nosplit
|
||||
func seccompMmapHandler(context unsafe.Pointer) {
|
||||
throw("seccompMmapHandler isn't implemented for debug builds")
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package kvm
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// seccompMmapHandler is a signal handler for runtime mmap system calls
|
||||
// that are trapped by seccomp.
|
||||
//
|
||||
// It executes the mmap syscall with specified arguments and maps a new region
|
||||
// to the guest.
|
||||
//
|
||||
//go:nosplit
|
||||
func seccompMmapHandler(context unsafe.Pointer) {
|
||||
mmapCallCounter.Increment()
|
||||
|
||||
addr, length, errno := seccompMmapSyscall(context)
|
||||
if errno != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
seccompMmapHandlerCnt.Add(1)
|
||||
for i := uint32(0); i < machinePoolLen.Load(); i++ {
|
||||
m := machinePool[i].Load()
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Map the new region to the guest.
|
||||
vr := region{
|
||||
virtual: addr,
|
||||
length: length,
|
||||
}
|
||||
for virtual := vr.virtual; virtual < vr.virtual+vr.length; {
|
||||
physical, length, ok := translateToPhysical(virtual)
|
||||
if !ok {
|
||||
// This must be an invalid region that was
|
||||
// knocked out by creation of the physical map.
|
||||
return
|
||||
}
|
||||
if virtual+length > vr.virtual+vr.length {
|
||||
// Cap the length to the end of the area.
|
||||
length = vr.virtual + vr.length - virtual
|
||||
}
|
||||
|
||||
// Ensure the physical range is mapped.
|
||||
m.mapPhysical(physical, length, physicalRegions)
|
||||
virtual += length
|
||||
}
|
||||
}
|
||||
seccompMmapHandlerCnt.Add(-1)
|
||||
}
|
||||
@@ -88,3 +88,22 @@ TEXT ·retjmp(SB),NOSPLIT,$0-0
|
||||
MOVQ 8(SP), BP
|
||||
ADDQ $0x10,SP
|
||||
RET
|
||||
|
||||
// func kvmSyscallErrno6(trap, a1, a2, a3, a4, a5, a6 uintptr) (ret unix.Errno)
|
||||
TEXT ·kvmSyscallErrno6(SB),NOSPLIT,$0-64
|
||||
MOVQ a1+8(FP), DI
|
||||
MOVQ a2+16(FP), SI
|
||||
MOVQ a3+24(FP), DX
|
||||
MOVQ a4+32(FP), R10
|
||||
MOVQ a5+40(FP), R8
|
||||
MOVQ a6+48(FP), R9
|
||||
MOVQ trap+0(FP), AX // syscall entry
|
||||
SYSCALL
|
||||
CMPQ AX, $0xfffffffffffff001
|
||||
JLS ok
|
||||
NEGQ AX
|
||||
MOVQ AX, ret+56(FP) // ret
|
||||
RET
|
||||
ok:
|
||||
MOVQ $0, ret+56(FP) // ret
|
||||
RET
|
||||
|
||||
@@ -30,6 +30,9 @@ func callWithSignalFrame(stack uintptr, handler uintptr, sigframe *arch.UContext
|
||||
//go:linkname throw runtime.throw
|
||||
func throw(s string)
|
||||
|
||||
// kvmSyscallErrno6 only returns errno, and 0 if successful.
|
||||
func kvmSyscallErrno6(trap, a1, a2, a3, a4, a5, a6 uintptr) unix.Errno
|
||||
|
||||
// CallWithSignalFrame sets up a signal frame on the stack and executes a
|
||||
// user-defined callback function within that context.
|
||||
//
|
||||
@@ -38,7 +41,7 @@ func throw(s string)
|
||||
//
|
||||
//go:nosplit
|
||||
func CallWithSignalFrame(stack uintptr, handlerAddr uintptr, sigframe *arch.UContext64, fpstate uintptr, sigmask *linux.SignalSet) error {
|
||||
_, _, errno := unix.RawSyscall6(
|
||||
errno := kvmSyscallErrno6(
|
||||
unix.SYS_RT_SIGPROCMASK, linux.SIG_BLOCK,
|
||||
uintptr(unsafe.Pointer(sigmask)),
|
||||
uintptr(unsafe.Pointer(&sigframe.Sigset)),
|
||||
|
||||
@@ -13,7 +13,6 @@ exempt_go_library(
|
||||
srcs = [
|
||||
"platforms.go",
|
||||
"platforms_darwin.go",
|
||||
"platforms_debug.go",
|
||||
],
|
||||
# Nothing needs to be stateified, and stateify has trouble when select is
|
||||
# used to choose deps.
|
||||
|
||||
Reference in New Issue
Block a user