1// Copyright 2024 The Go Authors. All rights reserved.
 2// Use of this source code is governed by a BSD-style
 3// license that can be found in the LICENSE file.
 4
 5// Minimal copy of x/sys/unix so the cpu package can make a
 6// system call on Darwin without depending on x/sys/unix.
 7
 8//go:build darwin && amd64 && gc
 9
10package cpu
11
12import (
13	"syscall"
14	"unsafe"
15)
16
17type _C_int int32
18
19// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419
20func darwinOSRelease(release *[256]byte) error {
21	// from x/sys/unix/zerrors_openbsd_amd64.go
22	const (
23		CTL_KERN       = 0x1
24		KERN_OSRELEASE = 0x2
25	)
26
27	mib := []_C_int{CTL_KERN, KERN_OSRELEASE}
28	n := unsafe.Sizeof(*release)
29
30	return sysctl(mib, &release[0], &n, nil, 0)
31}
32
33type Errno = syscall.Errno
34
35var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes.
36
37// from x/sys/unix/zsyscall_darwin_amd64.go L791-807
38func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
39	var _p0 unsafe.Pointer
40	if len(mib) > 0 {
41		_p0 = unsafe.Pointer(&mib[0])
42	} else {
43		_p0 = unsafe.Pointer(&_zero)
44	}
45	if _, _, err := syscall_syscall6(
46		libc_sysctl_trampoline_addr,
47		uintptr(_p0),
48		uintptr(len(mib)),
49		uintptr(unsafe.Pointer(old)),
50		uintptr(unsafe.Pointer(oldlen)),
51		uintptr(unsafe.Pointer(new)),
52		uintptr(newlen),
53	); err != 0 {
54		return err
55	}
56
57	return nil
58}
59
60var libc_sysctl_trampoline_addr uintptr
61
62// adapted from internal/cpu/cpu_arm64_darwin.go
63func darwinSysctlEnabled(name []byte) bool {
64	out := int32(0)
65	nout := unsafe.Sizeof(out)
66	if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil {
67		return false
68	}
69	return out > 0
70}
71
72//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
73
74var libc_sysctlbyname_trampoline_addr uintptr
75
76// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix
77func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
78	if _, _, err := syscall_syscall6(
79		libc_sysctlbyname_trampoline_addr,
80		uintptr(unsafe.Pointer(name)),
81		uintptr(unsafe.Pointer(old)),
82		uintptr(unsafe.Pointer(oldlen)),
83		uintptr(unsafe.Pointer(new)),
84		uintptr(newlen),
85		0,
86	); err != 0 {
87		return err
88	}
89
90	return nil
91}
92
93//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib"
94
95// Implemented in the runtime package (runtime/sys_darwin.go)
96func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
97
98//go:linkname syscall_syscall6 syscall.syscall6